Aleksander Machniak
2016-05-06 acf633c73bc8df9a5036bc52d7568f4213ab73c7
commit | author | age
b37954 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
27     /**
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
40     /**
acf633 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     /**
b37954 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
e7d1a8 67         $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>p2</p>', $washed, "HTML conditional comments (#1489004)");
b37954 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)");
2d233b 73
AM 74         $html   = "<p>para1</p><!-- comment --><p>para2</p>";
75         $washed = $washer->wash($html);
76
e7d1a8 77         $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>para1</p><p>para2</p>', $washed, "HTML comments - simple comment");
2d233b 78
AM 79         $html   = "<p>para1</p><!-- <hr> comment --><p>para2</p>";
80         $washed = $washer->wash($html);
81
e7d1a8 82         $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>para1</p><p>para2</p>', $washed, "HTML comments - tags inside (#1489904)");
b37954 83     }
AM 84
85     /**
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
98     /**
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
111     /**
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
05d419 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
168     /**
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\" />
174             <body><span style='font-family:\"新細明體\",\"serif\";color:red'>test</span></body></html>";
175
176         $washer = new rcube_washtml;
177         $washed = $washer->wash($html);
178
049940 179         $this->assertRegExp('|style="font-family: \&quot;新細明體\&quot;,\&quot;serif\&quot;; color: red"|', $washed, "Unicode chars in style attribute - quoted (#1489697)");
05d419 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)");
188     }
49e260 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");
202     }
049940 203
AM 204     /**
205      * Test invalid style cleanup - XSS prevention (#1490227)
206      */
207     function test_style_wash_xss()
208     {
209         $html = "<img style=aaa:'\"/onerror=alert(1)//'>";
210         $exp  = "<img style=\"aaa: '&quot;/onerror=alert(1)//'\" />";
211
212         $washer = new rcube_washtml;
213         $washed = $washer->wash($html);
214
215         $this->assertTrue(strpos($washed, $exp) !== false, "Style quotes XSS issue (#1490227)");
216
217         $html = "<img style=aaa:'&quot;/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     }
73f8b5 225
AM 226     /**
227      * Test SVG cleanup
228      */
229     function test_style_wash_svg()
230     {
231         $svg = '<?xml version="1.0" standalone="no"?>
232 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
233 <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">
234   <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400" onmouseover="alert(1)" />
235   <text x="50" y="68" font-size="48" fill="#FFF" text-anchor="middle"><![CDATA[410]]></text>
236   <script type="text/javascript">
237     alert(document.cookie);
238   </script>
239   <text x="10" y="25" >An example text</text>
240   <a xlink:href="http://www.w.pl"><rect width="100%" height="100%" /></a>
241   <foreignObject xlink:href="data:text/xml,%3Cscript xmlns=\'http://www.w3.org/1999/xhtml\'%3Ealert(1)%3C/script%3E"/>
242   <set attributeName="onmouseover" to="alert(1)"/>
243   <animate attributeName="onunload" to="alert(1)"/>
244   <animate attributeName="xlink:href" begin="0" from="javascript:alert(1)" />
245 </svg>';
246
247         $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">
248   <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400" x-washed="onmouseover" />
249   <text x="50" y="68" font-size="48" fill="#FFF" text-anchor="middle">410</text>
250   <!-- script not allowed -->
251   <text x="10" y="25">An example text</text>
252   <a xlink:href="http://www.w.pl"><rect width="100%" height="100%" /></a>
253   <!-- foreignObject ignored -->
254   <set attributeName="onmouseover" x-washed="to" />
255   <animate attributeName="onunload" x-washed="to" />
256   <animate attributeName="xlink:href" begin="0" x-washed="from" />
257 </svg>';
258
259         $washer = new rcube_washtml;
260         $washed = $washer->wash($svg);
261
262         $this->assertSame($washed, $exp, "SVG content");
263     }
b37954 264 }