PHP弱类型
1.两种等于号 ==,===
===:比较的时候先判断两种字符串的类型是否相等,再比较
==:比较的时候会将字符串的类型转化 为相同的,再比较
如果在比较的时候涉及字符串与数字的比较则会将字符串转化为数字再比较
转换数字的规则:从第一位开始是数字则保留,遇到不是数字的则这一位后面的所有都去除。
比如:123admin =>123 123a1231327123 => 123 admin => 0
当一个字符串被当作一个数值来取值,其结果和类型如下:如果该字符串没有包含'.','e','E'并且其数值值在整形的范围内,则该字符串被当作int来取值,其他情况当作float来取值
例题:
if(isset($_POST['message'])){
$message = json_decode($_POST['message']);
$key = "****";//保密
if($message->key == $key){
echo "flag";
}
else{
echo"fail";
}
} else{
echo"~~~~";
}
知识点:json_decode函数:json_decode接受一个JSON格式的字符串并且把它转换为PHP变量 ,当该参数$assoc为TRUE时,将返回array,否则返回object。
JSON 格式的字符串
$json = '{"a":"php","b":"mysql","c":3}';
其中a为键,php为a的键值。
实例:
<?php
$json = '{"a":"php","b":"mysql","c":3}';
$json_Class=json_decode($json);
$json_Array=json_decode($json, true);
print_r($json_Class);
print_r($json_Array);
?>
输出:
stdClass Object (
[a] => php
[b] => mysql
[c] => 3 )
Array (
[a] => php
[b] => mysql
[c] => 3 )
回到该题,需要用post传参传入一个message。并且创建一个类等于对message转换为的php变量使得key等于类message中的key。可以看见题中的比较是==比较,又可知key是一个字符串,那我们可以大胆猜测key中不存在数字开头即转换为数值为0,那我们的payload则为:message={"key":0} 从而得到flag。如果猜测不对我们使用burpsuite来爆破就行。
2.array_search与is_array绕过
知识点:is_array:判断传入的是不是一个数组,array_search(x,$数组):在数组中寻找与指定值(x)相等的值,array_search函数 类似
<?php
if(!is_array($_GET['test'])){exit();}
$test=$_GET['test'];
for($i=0;$i<count($test);$i++){
if($test[$i]==="admin"){
echo "error";
exit();
}
$test[$i]=intval($test[$i]);
}
if(array_search("admin",$test)===0){
echo "flag";
}
else{
echo "false";
}
?>
判断传入的是不是数组,然后循环遍历数组中的每一个值,并将数组中的每一个值不能与admin相等,并且将每一个值转化为int类型,在判断传入的数组是否有admin,有则返回flag。
构造test[]=0
在数组test中找到了与admin相等的值0,所以等于0,成功输出flag。
mixed array_search ( mixed $needle , array $haystack [], bool $strict = false ] )
array_search函数类似于==,但如果第三个参数为true则不能绕过,但默认为false
3.strcmp漏洞绕过
strcmp是比较两个字符串,str1<str2,返回<0,str1>str2,返回>0,相等时返回等于0。
strcmp比较的是字符串类型,如果强行传入其它类型的参数,就会报错并返回值0,正是利用这一点进行绕过。
我们可以传入非字符串类型,比如数组:
<?php
$password="***************";
$pass[]="admin";
if (strcmp($pass, $password) == 0)
{
echo "Right!!!login success";
exit();
} else
{
echo "Wrong password..";
}
?>
pass[]=xxx就可以绕过。
4.switch绕过
看两个例子:
<?php
$a = 0;
switch ($a) {
case $a <= 10:
echo '小于10';
break;
case $a <= 20:
echo '小于20';
break;
case $a <= 30:
echo '小于30';
break;
default:
echo '大于30';
break;
}
该例子输出的时:大于30
第二个例子:
<?php
$a = 0;
switch ($a) {
case $a <= 10:
echo '小于10';
break;
case $a > 20:
echo '大于20';
break;
default:
echo '大于30';
break;
}
该例子输出的是:大于20。
第一个例子中a=0<10返回true,然后判断0==true?,不是,继续下一个case一直到最后一个case都不相等则走default。
第二个例子是a=0,a<=10返回true,判断0==true?,不等,则继续下一个case,a>=20?返回false,0==false?,成立则输出大于20。
5.intval绕过
intval()函数用于获取变量的整数值
echo intval(53);
echo intval(5.3);
当过滤5时就可以使用5.3
用法:int intval( var,base)
var是要转换成 integer 的数量值,base指转化所使用的进制
如果 base 是 0,通过检测 var 的格式来决定使用的进制;
如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);
如果字符串以 "0" 开始,使用 8 进制(octal);
否则使用 10 进制 (decimal)。
我们可以利用它的进制转换来实现绕过。成功时返回 var 的 integer 值,失败时返回 0;空的 array 返回 0,非空的 array 返回 1
如果是一个弱比较a==b,则可以传入两个数组a[]=1,b[]=2,都返回1,便可以用于绕过。
关于intval这个函数存在一个漏洞:
单引号传值的时候,它只识别字母前面的一部分,当我们进行get传参时,其实就是默认加单引号的,在PHP中,+号会被判定成把他强制转换成科学计数法进行计算,而不是一个字符串+1。
初识盲注
select*from users where id= '1'and 1=1
select*from users where id ='1'and 1=2
select*from users where id= '1'and substr((select database()),1,1)='a'
select*from users where id= '1'and substr((select database()),1,1)='c'
知识点:and与or运算符:and需要两个条件都正确才返回true,而or只需要一个条件正确即可返回true。
以此类推可以一直查询首字母,从而知道首字母。知道首字母后,可以将1改为2,从而把所有都查出来。
1.布尔盲注:
盲注的两大基本问题:
1.字符串的截取
1.substr() substring()推荐使用
substr(str,pos):截取从pos位置到最后的所有str字符串
substr(str,pos,len)
2.mid()与substr()差不多使用
3.right()/left()
从右往左截
right()函数不可以精确查找某一个字符,因此可以使用ascii()函数。可将字母转换为ascii,在该函数中如果放入了字符串则返还字符串中第一个字符的ascii值。因此可以与right()函数一同使用,这样就可以精确查找每一个字符。
4.trim()
过滤指定的字符串,最常见的用途就是移除字首或字尾的空白{trim(),rtrim(),ltrim()}
** trim(both/leading//training 目标字符串 from 源字符串)
用该函数截取的方法:
trim(leading i from 'abcd') = trim(leading i+1 from 'abcd') 如果返回值不相等说明正确结果是i或者i+1
trim(leading i+2 from 'abcd') = trim(leading i+1 from 'abcd')返回值相等则正确为i;不相等则i+1正确。这样第一位就截取出来了,要截取第二位时换成ai,ai+1,ai+2即可。
2.比较
1.等于 大于 小于
2.like
用来查询一个字段中的一部分,比如我需要查找一个学校2023级的学生,只需要查找学号开头为2023即可。在like语句中%代表任意字符,就像2023%意味着查找2023开头的学号后面是任意。
如果在没有%时,like与=的作用是相同的
3.regexp(rlike)
但是regexp是大小写不敏感的,如果需要大小写敏感则需要加上binary关键字
4.between
expr [not] between begin_expr and end_expr;(闭区间)
between筛选的时expr>=begin_expr并且expr<=end_expr的数据,如果不存在则返回的是0;
not between筛选的时expr<=begin_expr并且expr>=end_expr的数据,如果不存在则返回的是0;
6.In
依然大小写不敏感 字符数字都可用 也有 not In
7.and or
8.异或(当不允许使用注释符时使用)
Xor 逻辑异或 ^按位异或
2.延时盲注
当不给布尔状态的时候不管查询是否成功都回显查询完成
条件表达式
1.if
if(exp1,exp2,exp3) 含义:if exp1:return exp2 else:return exp3
2.case
case exp1 when exp2 then exp3 else exp4 end;
通过两个条件表达式可以判断是否延时
3.报错盲注
if error, return ERR
else return OK!
可以构造一个布尔盲注。
哈希(md5)绕过问题
登录的哈希验证
$a != $b;
md5($a) == md5($b);
解法:'0e1561515614816561165548456241535' == '0e51515151555151551154789635241896'
$a != $b;
md5($a) === md5($b);
使用数组,如果在MD5中放入一个数组会回显出null,即可绕过强相等
(string)$a != (string)$b;
md5($a) === md5($b);
md5 碰撞 两个不同的东西拥有相同的md5
https://www.jianshu.com/p/c9089fd5b1ba
Md5绕过
$md5=$_GET['md5'];
$md5==md5($md5)