实验吧_登陆一下好吗(骚注入)&你真的会PHP吗?(代码审计)

登陆一下好吗

 

首先看到两个输入框,分别对应账号密码,随手输个admin,admin进去,提交后发现有回显,既然题目说了过滤了一切,那就先看看过滤了些啥

经过一波测试,发现服务器过滤了union,select,or,for,#,/,*

这就很让人头疼了,没了or就没了万能密码,select也被过滤,我还真想不起来有什么注入语句了

只能去翻看wp学习一下了

一看真的是觉得脑洞大开

方法1:

username--> '='

password--> '='

膜一下大佬的思路:

首先猜测sql语句为:select * from user where username=’用户名’ and password=’密码’

这样当我们提交以上的payload后,查询语句就成了: select * from user where username=''='' and password=''=''

这里 ''='' 即 (空=空) 返回就是True,所以and前后都为True,查询语句就正确执行了

方法2:

利用mysql的数据类型转换:

原理是这样的:username是字符串类型的,当它接收到整型变量且值为0时,就会返回库内所有数据

这里同时也要用到mysql的数据类型转换,拿这里来说username=0与username='a'+0返回的结果是一样的('a'+0会自动进行类型转换,结果还是0)

目的是要构造sql语句:select * from user where username=0

还有另外一个小知识点:mysql的注释不仅有– ,/**/,#,还有一个 ;%00

所以这里第二种payload如下:

username--> a'+0;%00

passward--> 

但我并没有成功,不过知道学到原理,要有成功的老哥请告诉我如何操作

方法3

原理同2,不过构造语句的思路不同

先给payload:

username--> \

passward--> ^'a

还是之前的查询语句,这次提交后变为select * from user where username='\' and password='^'a'

根据运算的优先级,这里会先比较两个字符串'\' and password=''a'异或的结果会返回0

这也就达到了我们上面所描述的目的了

 

 

 

你真的会PHP吗?

在响应头中看到提示:6c525af4059b4fe7d8c33a.txt,应该就是一个代码审计

 1 <?php
 2 
 3 
 4 $info = ""; 
 5 $req = [];
 6 $flag="xxxxxxxxxx";
 7 
 8 ini_set("display_error", false); 
 9 error_reporting(0); 
10 
11 //判断是否以POST 方式传入number,若没有就返回“have a fun!!”
12 if(!isset($_POST['number'])){
13    header("hint:6c525af4059b4fe7d8c33a.txt");
14 
15    die("have a fun!!"); 
16 }
17 //遍历POST数组中的键与值,将键赋给key,再将值得两侧去掉空格,再判断值是否是字符串,若是则将其中的特殊字符转义后赋给req数组
18 foreach([$_POST] as $global_var) { 
19     foreach($global_var as $key => $value) { 
20         $value = trim($value); 
21         is_string($value) && $req[$key] = addslashes($value); 
22     } 
23 } 
24 
25 //构造的一个函数来判断传入的number是否是回文格式的,即一二三三二一这种格式
26 function is_palindrome_number($number) { 
27     $number = strval($number); 
28     $i = 0; 
29     $j = strlen($number) - 1; 
30     while($i < $j) { 
31         if($number[$i] !== $number[$j]) { 
32             return false; 
33         } 
34         $i++; 
35         $j--; 
36     } 
37     return true; 
38 } 
39 
40 /*
首先获取number的值,判断是不是纯数字,若不是,则判断req数组中number键对应的值是否等于值本身int化再字符串化的值,若相等,接着判断int化的number对应的值是否
等于其反转后的值,若相等就判断number的值是否是回文形式,不是的话就返回flag
*/
41 if(is_numeric($_REQUEST['number'])){ 42 43 $info="sorry, you cann't input a number!"; 44 45 }elseif($req['number']!=strval(intval($req['number']))){ 46 47 $info = "number must be equal to it's integer!! "; 48 49 }else{ 50 51 $value1 = intval($req["number"]); 52 $value2 = intval(strrev($req["number"])); 53 54 if($value1!=$value2){ 55 $info="no, this is not a palindrome number!"; 56 }else{ 57 58 if(is_palindrome_number($req["number"])){ 59 $info = "nice! {$value1} is a palindrome number!"; 60 }else{ 61 $info=$flag; 62 } 63 } 64 65 } 66 67 echo $info;

代码分析就请看代码中的注释,我给每段都进行了说明

这里再给出几个函数的解释:

trim(str):去除str字符串两端的空格

addslashes(str):在str中的预定义字符前加上反斜杠,预定义字符有:单引号(')、双引号(")、反斜杠(\)、NULL

strval()/intval():将值转换为字符串/整型

strrev():反转字符串,比如将abc转为cba

 

总结一下这里要获取flag的要求:

1.以POST方式传入number的值

2.number的值为字符串且不能是纯数字的字符串

3.number的值=strval(intval($req['number']))

4.number整型化的值要与反转后的number整型化的值要相等

5.number的值不能是回文形式

 

这里的条件2,3是一对矛盾,4,5又是一对矛盾

要求number不是纯数字字符串那么intval后会把后面的字符给省略,这样就与3矛盾

4,5一看就是一对矛盾

 

经过一番搜索,参考了数篇wp,我了解到:

2,3可以通过空字符来绕过(如:%00)

is_numeric会判断%00为非数值,而且%00并不会被trim影响

接着就是解决4,5的矛盾

这里也有两种方法

方法1:intval函数溢出绕过

Intval最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, intval(‘1000000000000’) 会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。这里就是应用最大值得反转,2147483647反转后为7463847412明显大于2147483647了,那它的值就会等于最大值2147483647,而且不是回文形式,所以这里POST的number=2147483647%00

方法2:用科学计数法构造0=0

构造number=0e-0%00,可直接绕过了

 

转载于:https://www.cnblogs.com/Ragd0ll/p/8682084.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值