Introduction ############ rxgoogle.cgi is..."Provide your website visitors with your own net search program. This script allows your visitor to perform web search within your site without redirecting. You can set up RxGoogle search engine in just minutes and it's FREE!". rxgoogle.cgi is vulnerable to a simple XSS attack, potentially allowing an attacker to steal a users authentication cookie for that site (if there is one), or insert other malicious code into a search query and trick a legimate user into visiting the URL. Although rxgoogle.cgi is a new CGI script, and the bug is low risk, I considered this worth posting because a lot of people like to keep an up to date record of ALL CGI scripts known to be insecure in some way or another. The bug ####### The bug exists due to very bad user-input sanitization, hence a failure to filter bad characters such as metacharacters. PoC: http://host.com/cgi-bin/rxgoogle.cgi?query=%3Cscript%3Ealert%28%22XSS%22%29%3C%2Fscript%3E The fix ####### I have written a patch to fix the vulnerability. ----START --- rxgoogle.cgi 2004-02-04 14:20:38.000000000 -0500 +++ test 2004-02-04 14:27:29.000000000 -0500 @@ -197,7 +197,13 @@ my $req = new HTTP::Request GET => "$url"; my $res = $ua->request($req); if ($res->is_success) { $page_returned = $res->content; } return $page_returned;} -sub parse{my (@pairs, %in);my (@pairs, %in);my ($buffer, $pair, $name, $value);if ($ENV{'REQUEST_METHOD'} eq 'GET') {@pairs = split(/&/, $ENV{'QUERY_STRING'});}elsif($ENV{'REQUEST_METHOD'} eq 'POST') {read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});@pairs = split(/&/, $buffer);}PAIR: foreach $pair (@pairs) {($name, $value) = split(/=/, $pair);$name =~ tr/+/ /;$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;$value =~ tr/+/ /;$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;($value eq "---") and next PAIR;exists $in{$name} ? ($in{$name} .= "~~$value") : ($in{$name} = $value);}return %in;} + +# This parsing routine poorly sanitized user-input, thus allowing injection +# of metametachars, such as '<' and '>'. I have patched the problem now, by +# filtering input quite well now. +# +# -Shaun2k2 +sub parse{$OK_CHARS='-a-zA-Z0-9_.@'; my (@pairs, %in);my (@pairs, %in);my ($buffer, $pair, $name, $value);if ($ENV{'REQUEST_METHOD'} eq 'GET') {@pairs = split(/&/, $ENV{'QUERY_STRING'});}elsif($ENV{'REQUEST_METHOD'} eq 'POST') {read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});@pairs = split(/&/, $buffer);}PAIR: foreach $pair (@pairs) {($name, $value) = split(/=/, $pair);$name =~ tr/+/ /;$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;$name =~ s/[^$OK_CHARS]/_/go;$value =~ tr/+/ /;$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;$value =~ s/[^$OK_CHARS]/_/go;($value eq "---") and next PAIR;exists $in{$name} ? ($in{$name} .= "~~$value") : ($in{$name} = $value);}return %in;} sub html_navbar{my ($maxhits,$current,$numhits,$url)=0;my ($html, $nh, $prev_hit, $next_hit, $left, $right, $first, $last, $lower, $upper)="";$maxhits =shift; $numhits =shift; $current =shift; $url =shift; $nh=int($current/$maxhits)+1; $prev_hit=$nh-1; $next_hit=$nh+1; if (($current + $maxhits) >= $numhits) {$next_hit=0;}if ($numhits > $maxhits) { $left = $nh; $right = int($numhits/$maxhits) - $nh; ($left > 7) ? ($lower = $left - 7) : ($lower = 1); ($right > 7) ? ($upper = $nh + 7) : ($upper = int($numhits/$maxhits) + 1); (7 - $nh >= 0) and ($upper = $upper + (8 - $nh)); ($nh > ($numhits/$maxhits - 7)) and ($lower = $lower - ($nh - int($numhits/$maxhits - 7) - 1)); $html = ""; ($nh > 1) and ($html .= qq~<a href="$url&start=$prev_hit">[previous]</a> ~); for ($i = 1; $i <= int($numhits/$maxhits) + 1; $i++) { if ($i < $lower) { $html .= " ... "; $i = ($lower-1); next; } if ($i > $upper) { $html .= " ... "; last; } ($i == $nh) ? ($html .= qq~$i ~) : ($html .= qq~<a href="$url&start=$i">$i</a> ~); (($i * $maxhits) >= $numhits) and last; }if ($next_hit) { $html .= qq~<a href="$url&start=$next_hit">[next]</a> ~ unless ($nh == $i); } }return $html;} 1; @@ -224,4 +230,4 @@ print WRITEIT "$site\n"; close(WRITEIT); } - \ No newline at end of file + ---END Apply the patch as below: $ patch rxgoogle.cgi rxgoogle-xss.patch The bug is now fixed, due to proper sanitization now taking place. Credit ###### This vulnerability was discovered by shaun2k2 / Shaun Colley. The patch was written by shaun2k2 / Shaun Colley. Thank you for your time. Shaun. ___________________________________________________________ BT Yahoo! Broadband - Free modem offer, sign up online today and save £80 http://btyahoo.yahoo.co.uk