Aleksander Machniak
2016-05-06 6652367d656de7e5f404935be04e10aa281add53
commit | author | age
7ac944 1 <?php
AM 2
3 /**
4  * Test class to test rcube_washtml class
5  *
6  * @package Tests
7  */
8 class Framework_Washtml extends PHPUnit_Framework_TestCase
9 {
10
11     /**
12      * Test the elimination of some XSS vulnerabilities
13      */
14     function test_html_xss3()
15     {
16         // #1488850
17         $html = '<p><a href="data:text/html,&lt;script&gt;alert(document.cookie)&lt;/script&gt;">Firefox</a>'
18             .'<a href="vbscript:alert(document.cookie)">Internet Explorer</a></p>';
19
20         $washer = new rcube_washtml;
21         $washed = $washer->wash($html);
22
23         $this->assertNotRegExp('/data:text/', $washed, "Remove data:text/html links");
24         $this->assertNotRegExp('/vbscript:/', $washed, "Remove vbscript: links");
25     }
26
1f910c 27     /**
AM 28      * Test fixing of invalid href (#1488940)
29      */
30     function test_href()
31     {
32         $html = "<p><a href=\"\nhttp://test.com\n\">Firefox</a>";
33
34         $washer = new rcube_washtml;
35         $washed = $washer->wash($html);
36
37         $this->assertRegExp('|href="http://test.com">|', $washed, "Link href with newlines (#1488940)");
38     }
39
1e2468 40     /**
665236 41      * Test XSS in area's href (#5240)
AM 42      */
43     function test_href_area()
44     {
45         $html = '<p><area href="data:text/html,&lt;script&gt;alert(document.cookie)&lt;/script&gt;">'
46             . '<area href="vbscript:alert(document.cookie)">Internet Explorer</p>'
47             . '<area href="javascript:alert(document.domain)" shape=default>';
48
49         $washer = new rcube_washtml;
50         $washed = $washer->wash($html);
51
52         $this->assertNotRegExp('/data:text/', $washed, "data:text/html in area href");
53         $this->assertNotRegExp('/vbscript:/', $washed, "vbscript: in area href");
54         $this->assertNotRegExp('/javascript:/', $washed, "javascript: in area href");
55     }
56
57     /**
1e2468 58      * Test handling HTML comments
AM 59      */
60     function test_comments()
61     {
62         $washer = new rcube_washtml;
63
64         $html   = "<!--[if gte mso 10]><p>p1</p><!--><p>p2</p>";
65         $washed = $washer->wash($html);
66
923490 67         $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>p2</p>', $washed, "HTML conditional comments (#1489004)");
1e2468 68
AM 69         $html   = "<!--TestCommentInvalid><p>test</p>";
70         $washed = $washer->wash($html);
71
72         $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>test</p>', $washed, "HTML invalid comments (#1487759)");
82ed25 73
AM 74         $html   = "<p>para1</p><!-- comment --><p>para2</p>";
75         $washed = $washer->wash($html);
76
923490 77         $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>para1</p><p>para2</p>', $washed, "HTML comments - simple comment");
82ed25 78
AM 79         $html   = "<p>para1</p><!-- <hr> comment --><p>para2</p>";
80         $washed = $washer->wash($html);
81
923490 82         $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>para1</p><p>para2</p>', $washed, "HTML comments - tags inside (#1489904)");
1e2468 83     }
AM 84
cb3e2f 85     /**
AM 86      * Test fixing of invalid self-closing elements (#1489137)
87      */
88     function test_self_closing()
89     {
90         $html = "<textarea>test";
91
92         $washer = new rcube_washtml;
93         $washed = $washer->wash($html);
94
95         $this->assertRegExp('|<textarea>test</textarea>|', $washed, "Self-closing textarea (#1489137)");
96     }
97
ffec85 98     /**
AM 99      * Test fixing of invalid closing tags (#1489446)
100      */
101     function test_closing_tag_attrs()
102     {
103         $html = "<a href=\"http://test.com\">test</a href>";
104
105         $washer = new rcube_washtml;
106         $washed = $washer->wash($html);
107
108         $this->assertRegExp('|</a>|', $washed, "Invalid closing tag (#1489446)");
109     }
110
c72507 111     /**
AM 112      * Test fixing of invalid lists nesting (#1488768)
113      */
114     function test_lists()
115     {
116         $data = array(
117             array(
118                 "<ol><li>First</li><li>Second</li><ul><li>First sub</li></ul><li>Third</li></ol>",
119                 "<ol><li>First</li><li>Second<ul><li>First sub</li></ul></li><li>Third</li></ol>"
120             ),
121             array(
122                 "<ol><li>First<ul><li>First sub</li></ul></li></ol>",
123                 "<ol><li>First<ul><li>First sub</li></ul></li></ol>",
124             ),
125             array(
126                 "<ol><li>First<ol><li>First sub</li></ol></li></ol>",
127                 "<ol><li>First<ol><li>First sub</li></ol></li></ol>",
128             ),
129             array(
130                 "<ul><li>First</li><ul><li>First sub</li><ul><li>sub sub</li></ul></ul><li></li></ul>",
131                 "<ul><li>First<ul><li>First sub<ul><li>sub sub</li></ul></li></ul></li><li></li></ul>",
132             ),
133             array(
134                 "<ul><li>First</li><li>second</li><ul><ul><li>sub sub</li></ul></ul></ul>",
135                 "<ul><li>First</li><li>second<ul><ul><li>sub sub</li></ul></ul></li></ul>",
136             ),
137             array(
138                 "<ol><ol><ol></ol></ol></ol>",
139                 "<ol><ol><ol></ol></ol></ol>",
140             ),
141             array(
142                 "<div><ol><ol><ol></ol></ol></ol></div>",
143                 "<div><ol><ol><ol></ol></ol></ol></div>",
144             ),
145         );
146
147         foreach ($data as $element) {
148             rcube_washtml::fix_broken_lists($element[0]);
149
150             $this->assertSame($element[1], $element[0], "Broken nested lists (#1488768)");
151         }
152     }
153
68cf8f 154     /**
AM 155      * Test color style handling (#1489697)
156      */
157     function test_color_style()
158     {
159         $html = "<p style=\"font-size: 10px; color: rgb(241, 245, 218)\">a</p>";
160
161         $washer = new rcube_washtml;
162         $washed = $washer->wash($html);
163
164         $this->assertRegExp('|color: rgb\(241, 245, 218\)|', $washed, "Color style (#1489697)");
165         $this->assertRegExp('|font-size: 10px|', $washed, "Font-size style");
166     }
167
5e3ee8 168     /**
AM 169      * Test handling of unicode chars in style (#1489777)
170      */
171     function test_style_unicode()
172     {
173         $html = "<html><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
f96fec 174             <body><span style='font-family:\"新細明體\",\"serif\";color:red'>test</span></body></html>";
5e3ee8 175
AM 176         $washer = new rcube_washtml;
177         $washed = $washer->wash($html);
178
786aa0 179         $this->assertRegExp('|style="font-family: \&quot;新細明體\&quot;,\&quot;serif\&quot;; color: red"|', $washed, "Unicode chars in style attribute - quoted (#1489697)");
f96fec 180
AM 181         $html = "<html><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
182             <body><span style='font-family:新細明體;color:red'>test</span></body></html>";
183
184         $washer = new rcube_washtml;
185         $washed = $washer->wash($html);
186
187         $this->assertRegExp('|style="font-family: 新細明體; color: red"|', $washed, "Unicode chars in style attribute (#1489697)");
5e3ee8 188     }
5bf83d 189
AM 190     /**
191      * Test style item fixes
192      */
193     function test_style_wash()
194     {
195         $html = "<p style=\"line-height: 1; height: 10\">a</p>";
196
197         $washer = new rcube_washtml;
198         $washed = $washer->wash($html);
199
200         $this->assertRegExp('|line-height: 1;|', $washed, "Untouched line-height (#1489917)");
201         $this->assertRegExp('|; height: 10px|', $washed, "Fixed height units");
f4c512 202
AM 203         $html     = "<div style=\"padding: 0px\n   20px;border:1px solid #000;\"></div>";
204         $expected = "<div style=\"padding: 0px 20px; border: 1px solid #000\"></div>";
205
206         $washer = new rcube_washtml;
207         $washed = $washer->wash($html);
208
209         $this->assertTrue(strpos($washed, $expected) !== false, "White-space and new-line characters handling");
5bf83d 210     }
786aa0 211
AM 212     /**
213      * Test invalid style cleanup - XSS prevention (#1490227)
214      */
215     function test_style_wash_xss()
216     {
217         $html = "<img style=aaa:'\"/onerror=alert(1)//'>";
218         $exp  = "<img style=\"aaa: '&quot;/onerror=alert(1)//'\" />";
219
220         $washer = new rcube_washtml;
221         $washed = $washer->wash($html);
222
223         $this->assertTrue(strpos($washed, $exp) !== false, "Style quotes XSS issue (#1490227)");
224
225         $html = "<img style=aaa:'&quot;/onerror=alert(1)//'>";
226         $exp  = "<img style=\"aaa: '&quot;/onerror=alert(1)//'\" />";
227
228         $washer = new rcube_washtml;
229         $washed = $washer->wash($html);
230
231         $this->assertTrue(strpos($washed, $exp) !== false, "Style quotes XSS issue (#1490227)");
232     }
ed1d21 233
AM 234     /**
235      * Test SVG cleanup
236      */
237     function test_style_wash_svg()
238     {
239         $svg = '<?xml version="1.0" standalone="no"?>
240 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
241 <svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" viewBox="0 0 100 100">
242   <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400" onmouseover="alert(1)" />
243   <text x="50" y="68" font-size="48" fill="#FFF" text-anchor="middle"><![CDATA[410]]></text>
244   <script type="text/javascript">
245     alert(document.cookie);
246   </script>
247   <text x="10" y="25" >An example text</text>
248   <a xlink:href="http://www.w.pl"><rect width="100%" height="100%" /></a>
249   <foreignObject xlink:href="data:text/xml,%3Cscript xmlns=\'http://www.w3.org/1999/xhtml\'%3Ealert(1)%3C/script%3E"/>
250   <set attributeName="onmouseover" to="alert(1)"/>
251   <animate attributeName="onunload" to="alert(1)"/>
252   <animate attributeName="xlink:href" begin="0" from="javascript:alert(1)" />
253 </svg>';
254
255         $exp = '<svg xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" viewBox="0 0 100 100">
256   <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400" x-washed="onmouseover" />
257   <text x="50" y="68" font-size="48" fill="#FFF" text-anchor="middle">410</text>
258   <!-- script not allowed -->
259   <text x="10" y="25">An example text</text>
260   <a xlink:href="http://www.w.pl"><rect width="100%" height="100%" /></a>
261   <!-- foreignObject ignored -->
262   <set attributeName="onmouseover" x-washed="to" />
263   <animate attributeName="onunload" x-washed="to" />
264   <animate attributeName="xlink:href" begin="0" x-washed="from" />
265 </svg>';
266
267         $washer = new rcube_washtml;
268         $washed = $washer->wash($svg);
269
270         $this->assertSame($washed, $exp, "SVG content");
271     }
7ac944 272 }