Chris@0
|
1 # Escaping HTML Attributes
|
Chris@0
|
2
|
Chris@0
|
3 Escaping data in **HTML Attribute** contexts is most often done incorrectly, if
|
Chris@0
|
4 not overlooked completely by developers. Regular [HTML
|
Chris@0
|
5 escaping](escaping-html.md) can be used for escaping HTML attributes *only* if
|
Chris@0
|
6 the attribute value can be **guaranteed as being properly quoted**! To avoid
|
Chris@0
|
7 confusion, we recommend always using the HTML Attribute escaper method when
|
Chris@0
|
8 dealing with HTTP attributes specifically.
|
Chris@0
|
9
|
Chris@0
|
10 To escape data for an HTML Attribute, use `Zend\Escaper\Escaper`'s
|
Chris@0
|
11 `escapeHtmlAttr()` method. Internally it will convert the data to UTF-8, check
|
Chris@0
|
12 for its validity, and use an extended set of characters to escape that are not
|
Chris@0
|
13 covered by `htmlspecialchars()` to cover the cases where an attribute might be
|
Chris@0
|
14 unquoted or quoted illegally.
|
Chris@0
|
15
|
Chris@0
|
16 ## Examples of Bad HTML Attribute Escaping
|
Chris@0
|
17
|
Chris@0
|
18 An example of incorrect HTML attribute escaping:
|
Chris@0
|
19
|
Chris@0
|
20 ```php
|
Chris@0
|
21 <?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
Chris@0
|
22 <!DOCTYPE html>
|
Chris@0
|
23 <?php
|
Chris@0
|
24 $input = <<<INPUT
|
Chris@0
|
25 ' onmouseover='alert(/ZF2!/);
|
Chris@0
|
26 INPUT;
|
Chris@0
|
27
|
Chris@0
|
28 /**
|
Chris@0
|
29 * NOTE: This is equivalent to using htmlspecialchars($input, ENT_COMPAT)
|
Chris@0
|
30 */
|
Chris@0
|
31 $output = htmlspecialchars($input);
|
Chris@0
|
32 ?>
|
Chris@0
|
33 <html>
|
Chris@0
|
34 <head>
|
Chris@0
|
35 <title>Single Quoted Attribute</title>
|
Chris@0
|
36 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
Chris@0
|
37 </head>
|
Chris@0
|
38 <body>
|
Chris@0
|
39 <div>
|
Chris@0
|
40 <?php
|
Chris@0
|
41 // the span tag will look like:
|
Chris@0
|
42 // <span title='' onmouseover='alert(/ZF2!/);'>
|
Chris@0
|
43 ?>
|
Chris@0
|
44 <span title='<?= $output ?>'>
|
Chris@0
|
45 What framework are you using?
|
Chris@0
|
46 </span>
|
Chris@0
|
47 </div>
|
Chris@0
|
48 </body>
|
Chris@0
|
49 </html>
|
Chris@0
|
50 ```
|
Chris@0
|
51
|
Chris@0
|
52 In the above example, the default `ENT_COMPAT` flag is being used, which does
|
Chris@0
|
53 not escape single quotes, thus resulting in an alert box popping up when the
|
Chris@0
|
54 `onmouseover` event happens on the `span` element.
|
Chris@0
|
55
|
Chris@0
|
56 Another example of incorrect HTML attribute escaping can happen when unquoted
|
Chris@0
|
57 attributes are used (which is, by the way, perfectly valid HTML5):
|
Chris@0
|
58
|
Chris@0
|
59 ```php
|
Chris@0
|
60 <?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
Chris@0
|
61 <!DOCTYPE html>
|
Chris@0
|
62 <?php
|
Chris@0
|
63 $input = <<<INPUT
|
Chris@0
|
64 faketitle onmouseover=alert(/ZF2!/);
|
Chris@0
|
65 INPUT;
|
Chris@0
|
66
|
Chris@0
|
67 // Tough luck using proper flags when the title attribute is unquoted!
|
Chris@0
|
68 $output = htmlspecialchars($input, ENT_QUOTES);
|
Chris@0
|
69 ?>
|
Chris@0
|
70 <html>
|
Chris@0
|
71 <head>
|
Chris@0
|
72 <title>Quoteless Attribute</title>
|
Chris@0
|
73 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
Chris@0
|
74 </head>
|
Chris@0
|
75 <body>
|
Chris@0
|
76 <div>
|
Chris@0
|
77 <?php
|
Chris@0
|
78 // the span tag will look like:
|
Chris@0
|
79 // <span title=faketitle onmouseover=alert(/ZF2!/);>
|
Chris@0
|
80 ?>
|
Chris@0
|
81 <span title=<?= $output ?>>
|
Chris@0
|
82 What framework are you using?
|
Chris@0
|
83 </span>
|
Chris@0
|
84 </div>
|
Chris@0
|
85 </body>
|
Chris@0
|
86 </html>
|
Chris@0
|
87 ```
|
Chris@0
|
88
|
Chris@0
|
89 The above example shows how it is easy to break out from unquoted attributes in
|
Chris@0
|
90 HTML5.
|
Chris@0
|
91
|
Chris@0
|
92 ## Example of Good HTML Attribute Escaping
|
Chris@0
|
93
|
Chris@0
|
94 Both of the previous examples can be avoided by simply using the
|
Chris@0
|
95 `escapeHtmlAttr()` method:
|
Chris@0
|
96
|
Chris@0
|
97 ```php
|
Chris@0
|
98 <?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
Chris@0
|
99 <!DOCTYPE html>
|
Chris@0
|
100 <?php
|
Chris@0
|
101 $input = <<<INPUT
|
Chris@0
|
102 faketitle onmouseover=alert(/ZF2!/);
|
Chris@0
|
103 INPUT;
|
Chris@0
|
104
|
Chris@0
|
105 $escaper = new Zend\Escaper\Escaper('utf-8');
|
Chris@0
|
106 $output = $escaper->escapeHtmlAttr($input);
|
Chris@0
|
107 ?>
|
Chris@0
|
108 <html>
|
Chris@0
|
109 <head>
|
Chris@0
|
110 <title>Quoteless Attribute</title>
|
Chris@0
|
111 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
Chris@0
|
112 </head>
|
Chris@0
|
113 <body>
|
Chris@0
|
114 <div>
|
Chris@0
|
115 <?php
|
Chris@0
|
116 // the span tag will look like:
|
Chris@0
|
117 // <span title=faketitle onmouseover=alert(/ZF2!/);>
|
Chris@0
|
118 ?>
|
Chris@0
|
119 <span title=<?= $output ?>>
|
Chris@0
|
120 What framework are you using?
|
Chris@0
|
121 </span>
|
Chris@0
|
122 </div>
|
Chris@0
|
123 </body>
|
Chris@0
|
124 </html>
|
Chris@0
|
125 ```
|
Chris@0
|
126
|
Chris@0
|
127 In the above example, the malicious input from the attacker becomes completely
|
Chris@0
|
128 harmless as we used proper HTML attribute escaping!
|