| From ad1c95f23551ca4bbd459f6a6d73dfd68f24ee9a Mon Sep 17 00:00:00 2001 |
| From: Jakub Narebski <jnareb@gmail.com> |
| Date: Wed, 15 Dec 2010 00:34:01 +0100 |
| Subject: gitweb: Introduce esc_attr to escape attributes of HTML elements |
| |
| It is needed only to escape attributes of handcrafted HTML elements, |
| and not those generated using CGI.pm subroutines / methods for HTML |
| generation. |
| |
| While at it, add esc_url and esc_html where needed, and prefer to use |
| CGI.pm HTML generating methods than handcrafted HTML code. Most of |
| those are probably unnecessary (could be exploited only by person with |
| write access to gitweb config, or at least access to the repository). |
| |
| This fixes CVE-2010-3906 |
| |
| Reported-by: Emanuele Gentili <e.gentili@tigersecurity.it> |
| Helped-by: John 'Warthog9' Hawley <warthog9@kernel.org> |
| Helped-by: Jonathan Nieder <jrnieder@gmail.com> |
| Signed-off-by: Jakub Narebski <jnareb@gmail.com> |
| Signed-off-by: Junio C Hamano <gitster@pobox.com> |
| (cherry picked from commit 3017ed62f47ce14a959e2d315c434d4980cf4243) |
| |
| Conflicts: |
| |
| gitweb/gitweb.perl |
| |
| Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> |
| --- |
| gitweb/gitweb.perl | 37 ++++++++++++++++++++++--------------- |
| 1 files changed, 22 insertions(+), 15 deletions(-) |
| |
| diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl |
| index 348f94b..dfa5966 100755 |
| --- a/gitweb/gitweb.perl |
| +++ b/gitweb/gitweb.perl |
| @@ -1332,6 +1332,13 @@ sub esc_url { |
| return $str; |
| } |
| |
| +# quote unsafe characters in HTML attributes |
| +sub esc_attr { |
| + |
| + # for XHTML conformance escaping '"' to '"' is not enough |
| + return esc_html(@_); |
| +} |
| + |
| # replace invalid utf8 character with SUBSTITUTION sequence |
| sub esc_html { |
| my $str = shift; |
| @@ -1737,7 +1744,7 @@ sub format_ref_marker { |
| hash=>$dest |
| )}, $name); |
| |
| - $markers .= " <span class=\"$class\" title=\"$ref\">" . |
| + $markers .= " <span class=\"".esc_attr($class)."\" title=\"".esc_attr($ref)."\">" . |
| $link . "</span>"; |
| } |
| } |
| @@ -1821,7 +1828,7 @@ sub git_get_avatar { |
| return $pre_white . |
| "<img width=\"$size\" " . |
| "class=\"avatar\" " . |
| - "src=\"$url\" " . |
| + "src=\"".esc_url($url)."\" " . |
| "alt=\"\" " . |
| "/>" . $post_white; |
| } else { |
| @@ -2532,7 +2539,7 @@ sub git_show_project_tagcloud { |
| } else { |
| my @tags = sort { $cloud->{$a}->{count} <=> $cloud->{$b}->{count} } keys %$cloud; |
| return '<p align="center">' . join (', ', map { |
| - "<a href=\"$home_link?by_tag=$_\">$cloud->{$_}->{topname}</a>" |
| + $cgi->a({-href=>"$home_link?by_tag=$_"}, $cloud->{$_}->{topname}) |
| } splice(@tags, 0, $count)) . '</p>'; |
| } |
| } |
| @@ -3429,11 +3436,11 @@ EOF |
| # print out each stylesheet that exist, providing backwards capability |
| # for those people who defined $stylesheet in a config file |
| if (defined $stylesheet) { |
| - print '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'"/>'."\n"; |
| + print '<link rel="stylesheet" type="text/css" href="'.esc_url($stylesheet).'"/>'."\n"; |
| } else { |
| foreach my $stylesheet (@stylesheets) { |
| next unless $stylesheet; |
| - print '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'"/>'."\n"; |
| + print '<link rel="stylesheet" type="text/css" href="'.esc_url($stylesheet).'"/>'."\n"; |
| } |
| } |
| if (defined $project) { |
| @@ -3446,7 +3453,7 @@ EOF |
| my $type = lc($format); |
| my %link_attr = ( |
| '-rel' => 'alternate', |
| - '-title' => "$project - $href_params{'-title'} - $format feed", |
| + '-title' => esc_attr("$project - $href_params{'-title'} - $format feed"), |
| '-type' => "application/$type+xml" |
| ); |
| |
| @@ -3473,13 +3480,13 @@ EOF |
| } else { |
| printf('<link rel="alternate" title="%s projects list" '. |
| 'href="%s" type="text/plain; charset=utf-8" />'."\n", |
| - $site_name, href(project=>undef, action=>"project_index")); |
| + esc_attr($site_name), href(project=>undef, action=>"project_index")); |
| printf('<link rel="alternate" title="%s projects feeds" '. |
| 'href="%s" type="text/x-opml" />'."\n", |
| - $site_name, href(project=>undef, action=>"opml")); |
| + esc_attr($site_name), href(project=>undef, action=>"opml")); |
| } |
| if (defined $favicon) { |
| - print qq(<link rel="shortcut icon" href="$favicon" type="image/png" />\n); |
| + print qq(<link rel="shortcut icon" href=").esc_url($favicon).qq(" type="image/png" />\n); |
| } |
| |
| print "</head>\n" . |
| @@ -3493,7 +3500,7 @@ EOF |
| if (defined $logo) { |
| print $cgi->a({-href => esc_url($logo_url), |
| -title => $logo_label}, |
| - qq(<img src="$logo" width="72" height="27" alt="git" class="logo"/>)); |
| + qq(<img src=").esc_url($logo).qq(" width="72" height="27" alt="git" class="logo"/>)); |
| } |
| print $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / "; |
| if (defined $project) { |
| @@ -5612,14 +5619,14 @@ sub git_blob { |
| } else { |
| print "<div class=\"page_nav\">\n" . |
| "<br/><br/></div>\n" . |
| - "<div class=\"title\">$hash</div>\n"; |
| + "<div class=\"title\">".esc_html($hash)."</div>\n"; |
| } |
| git_print_page_path($file_name, "blob", $hash_base); |
| print "<div class=\"page_body\">\n"; |
| if ($mimetype =~ m!^image/!) { |
| - print qq!<img type="$mimetype"!; |
| + print qq!<img type="!.esc_attr($mimetype).qq!"!; |
| if ($file_name) { |
| - print qq! alt="$file_name" title="$file_name"!; |
| + print qq! alt="!.esc_attr($file_name).qq!" title="!.esc_attr($file_name).qq!"!; |
| } |
| print qq! src="! . |
| href(action=>"blob_plain", hash=>$hash, |
| @@ -5694,7 +5701,7 @@ sub git_tree { |
| undef $hash_base; |
| print "<div class=\"page_nav\">\n"; |
| print "<br/><br/></div>\n"; |
| - print "<div class=\"title\">$hash</div>\n"; |
| + print "<div class=\"title\">".esc_html($hash)."</div>\n"; |
| } |
| if (defined $file_name) { |
| $basedir = $file_name; |
| @@ -6162,7 +6169,7 @@ sub git_blobdiff { |
| git_print_header_div('commit', esc_html($co{'title'}), $hash_base); |
| } else { |
| print "<div class=\"page_nav\"><br/>$formats_nav<br/></div>\n"; |
| - print "<div class=\"title\">$hash vs $hash_parent</div>\n"; |
| + print "<div class=\"title\">".esc_html("$hash vs $hash_parent")."</div>\n"; |
| } |
| if (defined $file_name) { |
| git_print_page_path($file_name, "blob", $hash_base); |
| -- |
| 1.7.2.3 |
| |