root/HTML-XSSLint/trunk/lib/HTML/XSSLint.pm

Revision 705 (checked in by miyagawa, 18 years ago)

warranty

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 package HTML::XSSLint;
2
3 use strict;
4 use vars qw($VERSION);
5 $VERSION = 0.01;
6
7 require LWP::UserAgent;
8 use base qw(LWP::UserAgent);
9
10 use Digest::MD5;
11 use HTML::XSSLint::Result;
12 use HTML::Form;
13 use HTTP::Request;
14 use URI;
15
16 sub _croak { require Carp; Carp::croak(@_); }
17
18 sub audit {
19     my($self, $uri) = @_;
20     $uri = URI->new($uri);
21
22     my $request  = HTTP::Request->new(GET => $uri);
23     my $response = $self->request($request);
24     $response->is_success or _croak("Can't fetch $uri");
25
26     my @forms = HTML::Form->parse($response->content, $uri);
27     return wantarray ? (map $self->do_audit($_), @forms) : $self->do_audit($forms[0]);
28 }
29
30 sub do_audit {
31     my($self, $form) = @_;
32     my $params   = $self->make_params($form->inputs);
33     my $request  = $self->fillin_and_click($form, $params);
34     my $response = $self->request($request);
35     $response->is_success or _croak("Can't fetch " . $form->action);
36
37     my @names = $self->compare($response->content, $params);
38     return HTML::XSSLint::Result->new(
39         form => $form,
40         names => \@names,
41     );
42 }
43
44 sub make_params {
45     my($self, @inputs) = @_;
46     my %params = map {
47         my $value = $self->random_string;
48         ($_->name => "<>$value");
49     } grep {
50         defined($_->name) && length($_->name)
51     } @inputs;
52     return \%params;
53 }
54
55 sub random_string {
56     my $self = shift;
57     return substr(Digest::MD5::md5_hex(rand() . {} . $$ . time), 0, 8);
58 }
59
60 sub fillin_and_click {
61     my($self, $form, $params) = @_;
62     local *HTML::Form::ListInput::value = \&hf_li_value; # hack it
63     for my $name (keys %$params) {
64         $form->value($name => $params->{$name});
65     }
66     return $form->click;
67 }
68
69 sub compare {
70     my($self, $html, $params) = @_;
71     return grep {
72         my $value = $params->{$_};
73         $html =~ /$value/;
74     } keys %$params;
75 }
76
77 sub hf_li_value {
78     my $self = shift;
79     my $old = $self->{value};
80     $self->{value} = shift if @_;
81     $old;
82 }
83
84 1;
85 __END__
86
87 =head1 NAME
88
89 HTML::XSSLint - audit XSS vulnerability of web pages
90
91 =head1 SYNOPSIS
92
93   use HTML::XSSLint;
94
95   my $agent   = HTML::XSSLint->new;
96
97   # there may be multiple forms in a single HTML
98   # if there's no from, @result is empty
99   my @result  = $agent->audit($url);
100
101   for my $result (grep { $_->vulnerable } @result) {
102       my $action  = $result->action;
103       my @names   = $result->names;
104       my $example = $result->example;
105   }
106
107 =head1 DESCRIPTION
108
109 HTML::XSSLint is a subclass of LWP::UserAgent to audit Cross Site
110 Scripting (XSS) vulnerability by generating random input against HTML
111 forms in a web page.
112
113 Note that the way this module works is not robust, so you can't say a
114 web page is XSS free because it passes HTML::XSSLint audit.
115
116 This module is a backend for command line utility C<xsslint> bundled
117 in the distribution. See L<xsslint> for details.
118
119 =head1 AUTHOR
120
121 Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
122
123 This library is free software; you can redistribute it and/or modify
124 it under the same terms as Perl itself.
125
126 This module comes with B<NO WARRANTY>.
127
128 =head1 SEE ALSO
129
130 L<xsslint>, L<HTML::XSSLint::Result>, L<LWP>, L<HTML::Form>
131
132 =cut
Note: See TracBrowser for help on using the browser.