你真的会php吗?

今天来讨论一道php代码审计的题,这是一道实验吧的题,连接: http://ctf5.shiyanbar.com/web/PHP/index.php 。
首先咱们点开连接,而且查看源代码,
这里写图片描述
发现什么都没有,这时候咱们想,咱们想源码可能在服务器端,咱们用burpsuit抓个包,发给Reapeater。
这里写图片描述
从服务器响应的文件,咱们能够发现如下对咱们有用的信息。
1.服务器的系统是32位的系统。
2.响应的文件是6c525af4059b4fe7d8c33a.txt
接下来咱们访问一下6c525af4059b4fe7d8c33a.txt文件,进行代码审计。php

<?php $info = ""; $req = []; $flag="xxxxxxxxxx"; ini_set("display_error", false); error_reporting(0); if(!isset($_POST['number'])){ header("hint:6c525af4059b4fe7d8c33a.txt"); die("have a fun!!"); } //遍历 foreach([$_POST] as $global_var) { foreach($global_var as $key => $value) { $value = trim($value); //trim() 函数移除字符串两侧的空白字符或其余预约义字符。 is_string($value) && $req[$key] = addslashes($value); } } //global $var是外部$var的同名引用或者指针。 //函数 function is_palindrome_number($number) { $number = strval($number); //本函数可将数组及类以外的变量类型转换成字符串类型。 $i = 0; $j = strlen($number) - 1;//strlen() 函数返回字符串的长度  while($i < $j) { if($number[$i] !== $number[$j]) { return false; } $i++; $j--; } return true; } //判断是否为数值型 if(is_numeric($_REQUEST['number'])){ $info="sorry, you cann't input a number!"; }elseif($req['number']!=strval(intval($req['number']))){ $info = "number must be equal to it's integer!! "; }else{ $value1 = intval($req["number"]); $value2 = intval(strrev($req["number"])); //strrev() 函数反转字符串。  if($value1!=$value2){ $info="no, this is not a palindrome number!"; }else{ //判断回文数 if(is_palindrome_number($req["number"])){ $info = "nice! {$value1} is a palindrome number!"; }else{ $info=$flag; } } } echo $info;

通过审计咱们能够发现若是咱们要拿到flag,POST的number须要知足如下条件:
1.不为空,且不能是一个数值型数字,包括小数。(由is_numeric函数判断)
2.不能是一个回文数。(is_palindrome_number判断)
3.该数的反转的整数值应该和它自己的整数值相等。即:web

intval($req["number"])=intval(strrev($req["number"]))

回文数就是相似于121这样的数。从上面能够看出2,3条件彷佛是冲突滴!数组

下面给出两种解法:bash

1.利用intval函数溢出绕过

Intval函数获取变量整数值。
函数介绍清点这里
Intval最大的值取决于操做系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, intval(‘1000000000000’) 会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。服务器

经过上面咱们知道服务器的操做系统是32位的,因此咱们构造2147483647就能够同时知足2,3条件。经过把空字符能够绕过is_numeric的判断(如%00,%20),因此咱们构造如下poc,number=2147483647%00 和number=2147483647%20均可。svg

对于第一个条件,咱们须要构造是让咱们的poc被函数判断为非数值,但又不影响它值的构造,理所固然想到空格字符和空字符。函数

而通过测试我发现is_numeric函数对于空字符%00,不管是%00放在先后均可以判断为非数值,而%20空格字符只能放在数值后。因此,查看函数发现该函数对对于第一个空格字符会跳过空格字符判断,接着后面的判断!!
这里写图片描述测试

2.用科学计数法构造0=0

由于要求不能为回文数,但又要知足intval($req["number"])=intval(strrev($req["number"])),因此咱们采用科学计数法构造poc为number=0e-0%00,这样的话咱们就能够绕过。
这里写图片描述
不积硅步无以致千里,但愿你们在进步的阶梯里不断前行!ui