2016年2月18日 星期四

CVE-2015-7547


這篇簡單記錄了我第一次驗證別人poc(proof-of-concept)的過程。

poc就是驗證某個概念、原理,在資安領域講簡單一點就是去exploit。


前言


CVE-2015-7547 是glibc中的 getaddrinfo()存在stack-based buffer overflow漏洞。這個漏洞其實從2015年就發現了,後來google和red hat的人一起研究並寫出了poc表示這個漏洞有其嚴重性。
漏洞主要發生在glibc 2.9版以後,查了一下發現我手邊的server全部中招。
比較完整的資訊可以參考:

CVE-2015-7547: Critical Vulnerability in glibc getaddrinfo


getaddrinfo() 主要用來查一個 host 所對應的 IP address,底層會去query DNS Server並得到結果。
此時若 DNS Server 回應了惡意的 payload ,可以造成 getaddrinfo() buffer overflow,利用這個漏洞來exploit client端的主機。

驗證過程



先將 poc code clone下來,
$ git clone https://github.com/fjserna/CVE-2015-7547
其中 CVE-2015-7547-poc.py 是惡意的DNS Server code, CVE-2015-7547-client.c 是client端呼叫 getaddrinfo() 的code。

我讓 CVE-2015-7547-poc.py bind 在本機的port 53,這需要root權限。如果 port 53 有其他服務(像是ubuntu有dnsmasq)請先將它disable再執行.py檔。
$ sudo ./CVE-2015-7547-poc.py

再來更改本機 nameserver 的設定,把原本的nameserver設定註解掉,改成指向本機端的DNS Server,讓本機的DNS query都向我們的惡意DNS Server查詢。
/etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
#nameserver 140.112.2.2
nameserver 127.0.0.1

最後,將 CVE-2015-7547-client.c 編譯成可執行檔並執行,就會發生seg fault了。
$ make
gcc -o CVE-2015-7547-client CVE-2015-7547-client.c

$ ./CVE-2015-7547-client
Segmentation fault (core dumped) 
接著我會嘗試利用這個漏洞拿到shell,但好像沒那麼簡單XD,如果成功的話會再把payload貼上來。

2016年1月12日 星期二

TW.edu CTF 2015 Write-up


My Write-up

2016/01/06 ~ 2016/01/10 是計算機安全課的期末競賽,有台大,台科,中央的修課同學參賽。

這次有幸和強者們同隊,隊名叫作shareifagree,然後拿下了不錯的成績XD。

雖然我都只寫Web而且只貢獻了1/6的分數,但真的是學到不少阿,總之就是要擅於google,學習新技巧,然後應用到實務上。

以後有空時應該就會玩玩CTF練練功吧,算是找到一個比較有興趣的領域了。

2015年9月16日 星期三

包rpm的骯髒事

最近在自己包rpm包,CentOS與Fedora的openssl rpm包因為某些版權問題把bitcoin所需要的橢圓曲線拿掉了,因此必須自己compile一個openssl給bitcoin使用。

無奈的是要讓其他人自己在configure下參數來找到我們自己編的openssl實在是太麻煩了,只好想辦法讓bitcoin在configure與compile時不下任何參數也能避開系統的openssl,而是用到我們包的版本。

我們的server清一色都是CentOS 7,因此團隊裡的大大們覺得乾脆我們自己包一個好了,然後就是由我來負責Orz。

首先,rpm specfile雖然簡單明瞭,但在很容易不小心把沒列在file section中的file install到BUILD_ROOT,這樣會造成錯誤。install section是在整個包的過程最後一步,openssl build一次又需要5~10分鐘,各種低級的error就浪費了我很多時間。

最後終於包好了,要怎麼讓bitcoin找到我們自己compile的libssl.so與libcrypto.so呢?
(以下方法滿髒的但小弟是新手又有deadline只好出此下策)
  1. /etc/profile中加入export PKG_CONFIG_PATH=/usr/local/openssl/lib ,讓每個使用者登入時都會設好PKG_CONFIG_PATH,這樣在configure時autoconf會找到我們要的SSL_CFLAGS和SSL_LD_FLAGS並產生好Makefile。
  2. 這時去make還是會發現我們仍是抓到系統的.so,真的很奇怪。打開verbose模式 make V=1 才發現需要用到openssl的某幾條gcc指令竟然還有幾個-L/usr/lib之類的linker path參數放在我們的-L/usr/local/openssl/lib之前!
  3. 最後我們只好在/etc/profile中又加上了export CXX="c++ -L/usr/local/openssl/lib" 這樣就保證了我們的路徑比系統的還優先找到XDD
此時,我們已經能抓到正確的openssl來編了。然而一執行bitcoind …
 ./bitcoind: /usr/lib/libcrypto.so: no version information available ...
去google才發現若執行時ld.so發現抓到的.so版本比編譯時的.so還舊,就會報這個error。

此時才想到忘記把.so的path加入ld.so.cache。在/etc/ld.so.conf.d/下創一個檔案並把路徑加入後,再執行
 $ ldconfig
讓路徑load至cache中就完成了!
最後,感謝強者lantw44的指導阿!

2015年8月21日 星期五

Cross Initialization

今天和朋友聊到了會發生在Switch statement與goto statement的Cross Initialization問題。
switch (ch) {
    case 1:
        int jval = 1;
        break;
    case 2:
        jval = 2;
}
compile時會出現

error: crosses initialization of 'int jval'

然而只要改成
switch (ch) {
    case 1:
        int jval;
        break;
    case 2:
        jval = 2;
}
就不會出現error了
或者是使用block來限制變數的scope也可解決這問題。
switch (ch) {
    case 1: {
        int jval;
        break;
    }
    case 2: {
        jval = 2;
    }
}
去google了一下,stackoverflow有許多篇在介紹這個問題,似乎是compiler不允許在同一個scope中jump over initialization.

ISO C++ ‘03 6.7/3 有規範
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer (8.5)

還需要弄懂的是為什麼只有initialization被禁止(不只有explicit的使用initializer來init,default init和value init也都不行),但是卻可以做definition與assignment。