﻿{"id":847,"date":"2012-11-21T20:12:14","date_gmt":"2012-11-21T12:12:14","guid":{"rendered":"http:\/\/notes.zerobox.org\/?p=847"},"modified":"2012-11-21T20:12:14","modified_gmt":"2012-11-21T12:12:14","slug":"php-string%e5%ba%8f%e5%88%97%e5%8c%96%e4%b8%8e%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96%e8%af%ad%e6%b3%95%e8%a7%a3%e6%9e%90%e4%b8%8d%e4%b8%80%e8%87%b4%e5%b8%a6%e6%9d%a5%e7%9a%84%e5%ae%89%e5%85%a8%e9%9a%90","status":"publish","type":"post","link":"http:\/\/zerobox.org\/notes\/847.html","title":{"rendered":"PHP string\u5e8f\u5217\u5316\u4e0e\u53cd\u5e8f\u5217\u5316\u8bed\u6cd5\u89e3\u6790\u4e0d\u4e00\u81f4\u5e26\u6765\u7684\u5b89\u5168\u9690\u60a3"},"content":{"rendered":"<pre>PHP string\u5e8f\u5217\u5316\u4e0e\u53cd\u5e8f\u5217\u5316\u8bed\u6cd5\u89e3\u6790\u4e0d\u4e00\u81f4\u5e26\u6765\u7684\u5b89\u5168\u9690\u60a3\r\n\r\nauthor: ryat#www.wolvez.org\r\nteam:http:\/\/www.80vul.com\r\ndate:2012-11-19\r\n\r\n   \u4e0d\u4e45\u524d IPB \u7206\u51fa\u4e86\u4e00\u4e2a unserialize() \u6f0f\u6d1e\uff3b1\uff3d\uff0c\u6f0f\u6d1e\u672c\u8eab\u6ca1\u6709\u4ec0\u4e48\u7279\u522b\u7684\uff0c\u4f46 IPB \u5b98\u65b9\u53d1\u5e03\u7684 patch \u5374\u5f88\u6709\u610f\u601d\uff3b2\uff3d\uff0c\u5f88\u5feb Stefan Esser \u5728\u5176 twitter \u4e0a\u7ed9\u51fa\u4e86 bypass \u7684\u65b9\u6cd5\uff3b3\uff3d\u3002\u968f\u540e IPB \u5b98\u65b9\u9488\u5bf9\u6b64 bypass \u53d1\u5e03\u4e86\u65b0\u7684 patch\uff0c\u4f46 Stefan Esser \u8868\u793a\u65b0 patch \u901a\u8fc7\u6539\u53d8\u5904\u7406\u65b9\u5f0f\u6700\u7ec8\u5316\u89e3\u4e86\u6b64\u6f0f\u6d1e\uff0c\u4f46\u5176\u63d0\u4f9b\u7684\u8fc7\u6ee4\u51fd\u6570 safeUnserialize() \u4f9d\u65e7\u662f\u5b58\u5728\u5b89\u5168\u95ee\u9898\u7684\u3002\u867d\u7136 Stefan Esser \u6ca1\u6709\u900f\u6f0f\u95ee\u9898\u5177\u4f53\u6240\u5728\uff0c\u4f46\u7b14\u8005\u901a\u8fc7\u67e5\u770b\u76f8\u5173 PHP \u6e90\u7801\uff0c\u53d1\u73b0 PHP \u5728\u5bf9 string \u8fdb\u884c\u5e8f\u5217\u5316\u4e0e\u53cd\u5e8f\u5217\u5316\u5904\u7406\u8fc7\u7a0b\u4e2d\u5b58\u5728\u8bed\u6cd5\u89e3\u6790\u4e0d\u4e00\u81f4\u7684\u95ee\u9898\uff0c\u8fd9\u6709\u53ef\u80fd\u4f1a\u5bfc\u81f4\u5f88\u4e25\u91cd\u7684\u5b89\u5168\u95ee\u9898\uff0c\u540c\u65f6\u4e5f\u53ef\u4ee5\u5f88\u5bb9\u6613\u7684 bypass safeUnserialize() \u51fd\u6570\u7684\u8fc7\u6ee4\u3002\r\n\r\ni. PHP string serialize() \u76f8\u5173\u6e90\u7801\u5206\u6790\r\n------------------------------------\r\n\r\n{% highlight c %}\r\n\r\n\tstatic inline void php_var_serialize_string(smart_str *buf, char *str, int len) \/* {{{ *\/\r\n\t{\r\n\t\tsmart_str_appendl(buf, \"s:\", 2);\r\n\t\tsmart_str_append_long(buf, len);\r\n\t\tsmart_str_appendl(buf, \":\\\"\", 2);\r\n\t\tsmart_str_appendl(buf, str, len);\r\n\t\tsmart_str_appendl(buf, \"\\\";\", 2);\r\n\t}\r\n\r\n{% endhighlight %}\r\n\r\n\u901a\u8fc7\u4e0a\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u53ef\u4ee5\u770b\u5230 serialize() \u5bf9 string \u5e8f\u5217\u5316\u5904\u7406\u65b9\u5f0f\u5982\u4e0b\uff1a\r\n\r\n{% highlight php %}\r\n\r\n\t$str = 'ryatsyne';\r\n\tvar_dump(serialize($str));\r\n\t\/\/ $str serialized string output\r\n\t\/\/ s:8:\"ryatsyne\";\r\n\r\n{% endhighlight %}\r\n\r\nii. PHP string unserialize() \u76f8\u5173\u6e90\u7801\u5206\u6790\r\n---------------------------------------\r\n\r\nunserialize() \u51fd\u6570\u5bf9 string \u7684\u53cd\u5e8f\u5217\u5316\u5219\u5206\u4e3a\u4e24\u79cd\uff0c\u4e00\u79cd\u662f\u5bf9 `s:` \u683c\u5f0f\u7684\u5e8f\u5217\u5316 string \u8fdb\u884c\u5904\u7406\uff1a\r\n\r\n{% highlight c %}\r\n\r\n\tswitch (yych) {\r\n    \t...\r\n\t\tcase 's':\tgoto yy9;\r\n\t\t...\r\n\tyy9:\r\n\t\tyych = *(YYMARKER = ++YYCURSOR);\r\n\t\tif (yych == ':') goto yy46;\r\n\t\tgoto yy3;\r\n\t\t...\r\n\tyy46:\r\n\t\tyych = *++YYCURSOR;\r\n\t\tif (yych == '+') goto yy47;\r\n\t\tif (yych &lt;= '\/') goto yy18;\r\n\t\tif (yych &lt;= '9') goto yy48;\r\n\t\tgoto yy18;\r\n\tyy47:\r\n\t\tyych = *++YYCURSOR;\r\n\t\tif (yych &lt;= '\/') goto yy18;\r\n\t\tif (yych &gt;= ':') goto yy18;\r\n\tyy48:\r\n\t\t++YYCURSOR;\r\n\t\tif ((YYLIMIT - YYCURSOR) &lt; 2) YYFILL(2);\r\n\t\tyych = *YYCURSOR;\r\n\t\tif (yych &lt;= '\/') goto yy18;\r\n\t\tif (yych &lt;= '9') goto yy48;\r\n\t\tif (yych &gt;= ';') goto yy18;\r\n\t\tyych = *++YYCURSOR;\r\n\t\tif (yych != '\"') goto yy18;\r\n\t\t++YYCURSOR;\r\n\t\t{\r\n\t\tsize_t len, maxlen;\r\n\t\tchar *str;\r\n\r\n\t\tlen = parse_uiv(start + 2);\r\n\t\tmaxlen = max - YYCURSOR;\r\n\t\tif (maxlen &lt; len) {\r\n\t\t\t*p = start + 2;\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t\tstr = (char*)YYCURSOR;\r\n\r\n\t\tYYCURSOR += len;\r\n\r\n\t\tif (*(YYCURSOR) != '\"') {\r\n\t\t\t*p = YYCURSOR;\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\/\/ \u786e\u4fdd\u683c\u5f0f\u4e3a s:x:\"x\"\r\n\r\n\t\tYYCURSOR += 2;\r\n\t\t*p = YYCURSOR;\r\n\t\/\/ \u6ce8\u610f\u8fd9\u91cc\uff0c*p \u6307\u9488\u76f4\u63a5\u540e\u79fb\u4e86\u4e24\u4f4d\uff0c\u4e5f\u5c31\u662f\u8bf4\u6ca1\u6709\u5224\u65ad \" \u540e\u9762\u662f\u5426\u4e3a ;\r\n\r\n\t\tINIT_PZVAL(*rval);\r\n\t\tZVAL_STRINGL(*rval, str, len, 1);\r\n\t\treturn 1;\r\n\r\n{% endhighlight %}\r\n\r\n\u53e6\u4e00\u79cd\u662f\u5bf9 S: \u683c\u5f0f\u7684\u5e8f\u5217 string \u8fdb\u884c\u5904\u7406\uff08\u6b64\u683c\u5f0f\u5728 serialize() \u51fd\u6570\u5e8f\u5217\u5316\u5904\u7406\u4e2d\u5e76\u6ca1\u6709\u5b9a\u4e49\uff09\uff1a\r\n\r\n{% highlight c %}\r\n\r\n\tstatic char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen)\r\n\t{\r\n\t\tsize_t i, j;\r\n\t\tchar *str = safe_emalloc(*len, 1, 1);\r\n\t\tunsigned char *end = *(unsigned char **)p+maxlen;\r\n\r\n\t\tif (end &lt; *p) {\r\n\t\t\tefree(str);\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\tfor (i = 0; i &lt; *len; i++) {\r\n\t\t\tif (*p &gt;= end) {\r\n\t\t\t\tefree(str);\r\n\t\t\t\treturn NULL;\r\n\t\t\t}\r\n\t\t\tif (**p != '\\\\') {\r\n\t\t\t\tstr[i] = (char)**p;\r\n\t\t\t} else {\r\n\t\t\t\tunsigned char ch = 0;\r\n\r\n\t\t\t\tfor (j = 0; j &lt; 2; j++) {\r\n\t\t\t\t\t(*p)++;\r\n\t\t\t\t\tif (**p &gt;= '0' &amp;&amp; **p &lt;= '9') {\r\n\t\t\t\t\t\tch = (ch &lt;&lt; 4) + (**p -'0');\r\n\t\t\t\t\t} else if (**p &gt;= 'a' &amp;&amp; **p &lt;= 'f') {\r\n\t\t\t\t\t\tch = (ch &lt;&lt; 4) + (**p -'a'+10);\r\n\t\t\t\t\t} else if (**p &gt;= 'A' &amp;&amp; **p &lt;= 'F') {\r\n\t\t\t\t\t\tch = (ch &lt;&lt; 4) + (**p -'A'+10);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tefree(str);\r\n\t\t\t\t\t\treturn NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tstr[i] = (char)ch;\r\n\t\t\t}\r\n\t\t\t(*p)++;\r\n\t\t}\r\n\t\tstr[i] = 0;\r\n\t\t*len = i;\r\n\t\treturn str;\r\n\t}\r\n\t\/\/ \u4e0a\u9762\u7684\u51fd\u6570\u662f\u5bf9 \\72\\79\\61\\74\\73\\79\\6e\\65 \u8fd9\u6837\u5341\u516d\u8fdb\u5236\u5f62\u5f0f\u5b57\u7b26\u4e32\u8fdb\u884c\u8f6c\u6362\r\n\t...\r\n\tswitch (yych) {\r\n\t\t...\r\n\t\tcase 'S':\tgoto yy10;\r\n\t\t\/\/ \u5904\u7406\u8fc7\u7a0b\u4e0e s: \u76f8\u540c\t\t\t\t\r\n\t\tif ((str = unserialize_str(&amp;YYCURSOR, &amp;len, maxlen)) == NULL) {\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\t\/\/ \u5904\u7406\u8fc7\u7a0b\u4e0e s: \u76f8\u540c\r\n\r\n{% endhighlight %}\r\n\r\n\u4ece\u4e0a\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u53ef\u4ee5\u770b\u5230 unserialize() \u5bf9\u5e8f\u5217\u5316\u540e\u7684 string \u53cd\u5e8f\u5217\u5316\u5904\u7406\u5982\u4e0b\uff1a\r\n\r\n{% highlight php %}\r\n\r\n\t$str1 = 's:8:\"ryatsyne\";';\r\n\t$str2 = 's:8:\"ryatsyne\"t';\r\n\t$str3 = 'S:8:\"\\72\\79\\61\\74\\73\\79\\6e\\65\"';\r\n\tvar_dump(unserialize($str));\r\n\t\/\/ $str1, $str2 and $str3 unserialized string output\r\n\t\/\/ ryatsyne;\r\n\r\n{% endhighlight %}\r\n\r\niii. \u8bed\u6cd5\u89e3\u6790\u5904\u7406\u4e0d\u4e00\u81f4\u5bfc\u81f4\u7684\u5b89\u5168\u9690\u60a3\r\n-----------------------------\r\n\r\n\u4ece\u4e0a\u8ff0\u5206\u6790\u8fc7\u7a0b\u53ef\u4ee5\u770b\u5230 PHP \u5728\u53cd\u5e8f\u5217\u5316 string \u65f6\u6ca1\u6709\u4e25\u683c\u6309\u7167\u5e8f\u5217\u5316\u683c\u5f0f s:x:\"x\"; \u8fdb\u884c\u5904\u7406\uff0c\u6ca1\u6709\u5bf9 \" \u540e\u9762\u7684\u662f\u5426\u5b58\u5728 ; \u8fdb\u884c\u5224\u65ad\uff0c\u540c\u65f6\u589e\u52a0\u4e86\u5bf9\u5341\u516d\u8fdb\u5236\u5f62\u5f0f\u5b57\u7b26\u4e32\u7684\u5904\u7406\uff0c\u8fd9\u6837\u524d\u540e\u5904\u7406\u7684\u4e0d\u4e00\u81f4\u8ba9\u4eba\u5f88\u8d39\u89e3\uff0c\u540c\u65f6\u7531\u4e8e PHP \u624b\u518c\u4e2d\u5bf9\u6b64\u6ca1\u6709\u8be6\u7ec6\u7684\u8bf4\u660e\uff0c\u5927\u90e8\u5206\u7a0b\u5e8f\u5458\u5bf9\u6b64\u5904\u7406\u8fc7\u7a0b\u5e76\u4e0d\u4e86\u89e3\uff0c\u8fd9\u53ef\u80fd\u5bfc\u81f4\u5176\u5728\u7f16\u7801\u8fc7\u7a0b\u4e2d\u51fa\u73b0\u758f\u6f0f\uff0c\u751a\u81f3\u5bfc\u81f4\u4e25\u91cd\u7684\u5b89\u5168\u95ee\u9898\u3002\r\n\r\n\u56de\u5230\u6587\u7ae0\u5f00\u5934\u63d0\u5230\u7684 IPB \u6f0f\u6d1e\u4e0a\uff0c\u5229\u7528\u8fd9\u4e2a funny feature of PHP \u53ef\u4ee5\u5f88\u5bb9\u6613\u7684 bypass safeUnserialize() \u51fd\u6570\u7684\u8fc7\u6ee4\uff1a\uff09\r\n\r\n{% highlight php %}\r\n\r\n    * mixed safe_unserialize(string $serialized)\r\n    * Safely unserialize, that is only unserialize string, numbers and arrays, not objects\r\n    *\r\n    * @license Public Domain\r\n    * @author dcz (at) phpbb-seo (dot) com\r\n    *\/\r\n    static public function safeUnserialize( $serialized )\r\n    {\r\n        \/\/ unserialize will return false for object declared with small cap o\r\n        \/\/ as well as if there is any ws between O and :\r\n        if ( is_string( $serialized ) &amp;&amp; strpos( $serialized, \"\\0\" ) === false )\r\n        {\r\n            if ( strpos( $serialized, 'O:' ) === false )\r\n            {\r\n                \/\/ the easy case, nothing to worry about\r\n                \/\/ let unserialize do the job\r\n                return @unserialize( $serialized );\r\n            }\r\n            else if ( ! preg_match('\/(^|;|{|})O:[+\\-0-9]+:\"\/', $serialized ) )\r\n            {\r\n                \/\/ in case we did have a string with O: in it,\r\n                \/\/ but it was not a true serialized object\r\n                return @unserialize( $serialized );\r\n            }\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    \/\/ a:1:{s:8:\"ryatsyne\"tO:8:\"ryatsyne\":0:{}}\r\n    \/\/ \u53ea\u8981\u6784\u9020\u7c7b\u4f3c\u7684\u5e8f\u5217\u5316\u5b57\u7b26\u4e32\u5c31\u53ef\u4ee5\u8f7b\u6613\u7a81\u7834\u8fd9\u91cc\u7684\u8fc7\u6ee4\u4e86\r\n\r\n{% endhighlight %}\r\n\r\niiii. \u53c2\u8003\r\n----------\r\n\r\n* \uff3b1\uff3d[http:\/\/seclists.org\/bugtraq\/2012\/Nov\/17](http:\/\/seclists.org\/bugtraq\/2012\/Nov\/17)\r\n* \uff3b2\uff3d[http:\/\/adminextra.com\/threads\/ip-board-3-1-x-3-2-x-and-3-3-x-hacked.6125\/](http:\/\/adminextra.com\/threads\/ip-board-3-1-x-3-2-x-and-3-3-x-hacked.6125\/)\r\n* \uff3b3\uff3d[http:\/\/twitter.com\/i0n1c](http:\/\/twitter.com\/i0n1c)<\/pre>\n<div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>PHP string\u5e8f\u5217\u5316\u4e0e\u53cd\u5e8f\u5217\u5316\u8bed\u6cd5\u89e3\u6790\u4e0d\u4e00\u81f4\u5e26\u6765\u7684\u5b89\u5168\u9690\u60a3 author: &hellip;<\/p>\n<p class=\"read-more\"><a href=\"http:\/\/zerobox.org\/notes\/847.html\">\u7ee7\u7eed\u9605\u8bfb &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[207],"class_list":["post-847","post","type-post","status-publish","format-standard","hentry","tag-php-string"],"views":1030,"_links":{"self":[{"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/posts\/847","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/comments?post=847"}],"version-history":[{"count":0,"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/posts\/847\/revisions"}],"wp:attachment":[{"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/media?parent=847"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/categories?post=847"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/zerobox.org\/notes\/wp-json\/wp\/v2\/tags?post=847"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}