A small feature of PHP anti-sequence Unserialize
these days WordPress that anti-sequence vulnerability comparison fire, specific loopholes I do not do analysis, see this article: http://drops.wooyun.org/papers/596,?
You can also go to read the original English: http://vagosec.org/2013/09/wordpress-php-object-injection/.?
WP Official website hit the patch, I tried to bypass patch, but let me think the success of the time, found me naïve, and did not successfully bypass the patch of WP, but found a small feature of unserialize, here and everyone to share.
1.unserialize () function related source code:?
if ((Yylimit-yycursor) < 7) Yyfill (7);?
???????? Yych = *yycursor;?
???????? Switch (yych) {?
???????? Case ' C ':?
???????? Case ' O ':???????? Goto YY13;?
???????? Case ' N ':???????? Goto yy5;?
???????? Case ' R ':???????? Goto yy2;?
???????? Case ' S ':???????? Goto Yy10;?
???????? Case ' a ':???????? Goto Yy11;?
???????? Case ' B ':???????? Goto yy6;?
???????? Case ' d ':???????? Goto yy8;?
???????? Case ' I ':???????? Goto Yy7;?
???????? Case ' O ':???????? Goto yy12;?
???????? Case ' R ':???????? Goto Yy4;?
???????? Case ' s ':???????? Goto Yy9;?
???????? Case '} ':???????? Goto YY14;?
???????? Default:???????? Goto YY16;?
????????}
The above code is the process of judging sequence string, such as sequence string o:4: "Test": 1:{s:1: "a"; S:3: "AAA";}, processing this sequence string, first get the string first character is O, then case ' O ':?? Goto YY13?
yy13:?
????????yych = *(YYMARKER = ++YYCURSOR);?
????????if (yych == ':') goto yy17;?
????????goto yy3;
As seen from the above code, the pointer moves one pointer to the second character, determines if the character is:, and then goto YY17?
YY17:?
???????? Yych = *++yycursor;?
???????? if (Yybm[0+yych] & 128) {?
???????????????? Goto Yy20;?
????????}?
???????? if (Yych = = ' + ') goto yy19;?
.......?
Yy19:?
???????? Yych = *++yycursor;?
???????? if (Yybm[0+yych] & 128) {?
???????????????? Goto Yy20;?
????????}?
???????? Goto Yy18;
As seen from the above code, the pointer moves, judging the next character, if the character is a number directly goto yy20, if it is ' + ' on goto yy19, and Yy19 is the next character to judge, if the next character is the number goto Yy20, not goto Yy18, Yy18 is the direct exit sequence processing, YY20 is the processing of the sequence of the object, so from the top can be seen:?
O:+4:"test":1:{s:1:"a";s:3:"aaa";}?
O:4:"test":1:{s:1:"a";s:3:"aaa";}
can be deserialized by unserialize and the results are the same.
2. Actual test:?
var_dump(unserialize('O:+4:"test":1:{s:1:"a";s:3:"aaa";}'));?
var_dump(unserialize('O:4:"test":1:{s:1:"a";s:3:"aaa";}'));?
?>
output:?
object(__PHP_Incomplete_Class)#1 (2) { ["__PHP_Incomplete_Class_Name"]=> string(4) "test" ["a"]=> string(3) "aaa" }?
object(__PHP_Incomplete_Class)#1 (2) { ["__PHP_Incomplete_Class_Name"]=> string(4) "test" ["a"]=> string(3) "aaa" }
in fact, not only object type processing can be more than one ' + ', other types can also, specific tests do not do too much description.
3. We look at the WP patch:?
function is_serialized ($data, $strict = True) {?
???????? If it isn ' t a string, it isn ' t serialized?
???????? if (! is_string ($data))?
???????????????? return false;?
???????? $data = Trim ($data);?
???????? if (' N; ' = = $data)?
???????????????? return true;?
???????? $length = strlen ($data);?
???????? if ($length < 4)?
???????????????? return false;?
???????? if (': '!== $data [1])?
???????????????? return false;?
???????? if ($strict) {//output?
???????????????? $LASTC = $data [$length-1];?
???????????????? if ('; '!== $lastc && '} '!== $LASTC)?
???????????????????????? return false;?
????????} else {//input?
???????????????? $semicolon = Strpos ($data, '; ');?
???????????????? $brace???? = Strpos ($data, '} ');?
???????????????? either; or} must exist.?
???????????????? if (false = = = $semicolon && false = = = $brace)?
???????????????????????? return false;?
???????????????? But neither must is in the first X characters.?
???????????????? if (false!== $semicolon && $semicolon < 3)?
???????????????????????? return false;?
???????????????? if (false!== $brace && $brace < 4)?
???????????????????????? return false;?
????????}?
???????? $token = $data [0];?
???????? Switch ($token) {?
???????????????? Case ' s ':?
???????????????????????? if ($strict) {?
???????????????????????????????? if (' "'!== $data [$length-2])?
???????????????????????????????????????? return false;?
????????????????????????} ElseIf (false = = = Strpos ($data, ' "')}) {?
???????????????????????????????? return false;?
????????????????????????}?
???????????????? Case ' a ':?
???????????????? Case ' O ':?
???????????????????????? echo "a";?
???????????????????????? return (BOOL) preg_match ("/^{$token}:[0-9]+:/s", $data);?
???????????????? Case ' B ':?
???????????????? Case ' I ':?
???????????????? Case ' d ':?
???????????????????????? $end = $strict? '$' : '';?
???????????????????????? return (BOOL) preg_match ("/^{$token}:[0-9.e-]+; $end/", $data);?
????????}?
???????? return false;?
}
in the patch?
return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
can be more than a ' + ' to bypass, although we use this method to write the sequence value to the database, but the data extracted from the database, the time to validate again can not be bypassed, I this plus does not make the data in and out of the database any changes, I personally think that the focus of the patch bypass data in and out of the changes.
4. Summary?
Although the WP patch is not bypassed, the small feature of this unserialize () may be overlooked by many developers, causing the program to become a security flaw.
What's wrong with the above analysis please leave a message to indicate.
5. Reference?
"WordPress < 3.6.1 PHP Object injection"?
http://vagosec.org/2013/09/wordpress-php-object-injection/?
"var_unserializer.c source"?
https://github.com/php/php-src/blob/73cd2e0ab14d804c6bf0b689490bdd4fd6e969b1/ext/standard/var_unserializer.c?
"PHP string serialization and deserialization syntax parsing inconsistent security implications"?
http://zone.wooyun.org/content/1664