0%

华为武研所一日游

好久没写博客了,刚好有空能写一写,这个月大部分时间在忙Datacon的邮件比赛,其实按理来说能有一点输出,但是感觉知识还是论文里面的东西,写博客还不如看论文。

10月31号去武研所参加了线下的CTF比赛,可能因为本人没有什么羞耻心,所以完全冲着包饭去的,也没想着要做出题拿奖什么的。

10道题,只有一道Web题,然后特别搞,因为它是一道原题,网上有完整的Write up,说实话还挺离谱的(有个队在主持人还在讲开场白的时候就做出来了)。然后因为其他题特别难,基本上做出这道题就有个优胜奖了。

解题

第一层

首先给了一段代码,大概就是通过query发送sql的查询语句。

第一想法是,注入吗?然后不是;

第二想法是,直接通过sql语句写木马。然后他正则是把log、file这些拉黑名单了,而且要求query必须是string,所以没办法通过数组或者其他方法绕过正则匹配;

第三想法是,算了,随便查询一下吧,然后select * from flag,居然真的就输出了查询结果,是gO0d_j0b_f0r_you2333333,我以为这道题就这样猝不及防的结束了,其实才刚刚开始。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
include 'conn.php';
if(isset($_GET["query"])){
$query = $_GET["query"];
if(!is_string($query)){
die('give me a string ok?');
}
if(preg_match('/log|local|set|file/i', $query)){
die('no hack');
}
$result = $mysqli->query($query);
if ($result === false) {
die("database error, please check your input");
}
$row = $result->fetch_assoc();
if($row === NULL){
die("searched nothing");
}
if(in_array($query, $row)){
echo $secret;
}
$result->free();
$mysqli->close();
}else{
highlight_file('index.php');
}

?>

因为gO0d_j0b_f0r_you2333333提交不对,所以访问对应的网址,成功下载了压缩包,里面有三个文件,gO0d_j0b_f0r_you2333333.phpadmin_test_class.phpfunction.php

第二层

gO0d_j0b_f0r_you2333333.php文件很简单,就是设置cookie,但是这个文件中有一个unserialize的操作,那么这道题应该就是php的反序列化了。我理解的序列化就是,把对象存储成固定的格式,内置一些函数进行解析。

1
2
3
4
5
6
7
8
9
10
<?php
include 'config.php';
include 'function.php';

if(!isset($_COOKIE['user'])){
setcookie("user", serialize('ctfer'), time()+3600);
}else{
echo "hello";
echo unserialize($_COOKIE['user']);
}

admin_test_class.php 里面有一个test类,包含cmd指令,指定为ls,__destruct的时候会执行cmd命令,__destruct一般都在反序列化的时候调用。并且__destruct包含了system这样的危险函数,并且cmd是外部可控的值,那么自然而然就会希望,能够在gO0d_j0b_f0r_you2333333.php中反序列化test,触发__destruct函数进行任意命令执行。

1
2
3
4
5
6
7
8
9
<?php

class test
{
public $cmd = 'ls';
function __destruct(){
system($this->cmd);
}
}

function.php 中包含一个输出flag的操作。

1
2
3
4
5
6
7
8
9
10
11
12
<?php
function get_flag($cmd){
if($cmd === 1){
echo $flag;
}
}


function __autoload($classname){
require "./$classname.php";
}
?>

看完三个文件之后,我的第一想法就是构造test对象,然后序列化后放入cookie,但是gO0d_j0b_f0r_you2333333.php只include了function.php,我只见过字符串和对象序列化,并没有见过函数序列化,然后我搜了一圈,没搜到(中途还和Write up擦肩而过,因为它的标题看着就让人没有点进去的欲望)。

然后陷入一系列奇怪的想法里面,比如希望构造字符串,能echo写木马进文件,但是只停留在输出字符串,真的是基础不牢,对这一块了解还是不太深入。

纠结了半天很想直接跑路,早点回去睡觉(7点爬起来颠簸一路过去),但是不知道怎么没跑(可能因为“来都来了”?)。

然后看到function.php里面有个__autoload函数,这个函数之前没见过,然后就搜到了Write up,直接原地裂开,这个Write up写的还蛮好的,我就懒得继续写(洗稿)了。

总结

但是在做题的过程中看到一篇写的很好的博客——php-unserialize-初识,里面讲构造POP链和ROP链的地方蛮有意思,在都有一定的了解的时候,会发现知识都是融会贯通的。PWN和Web在某种程度上也是贯通的,只不过面对的层面不一样罢了。

最后的感觉就是,少壮不努力,老大徒伤悲。自己已经是条老狗了,年轻人还有无限的未来。