|
| 1 | +# Escape |
| 2 | + |
| 3 | +The following helpers can **escape output in view scripts and defend from XSS |
| 4 | +and related vulnerabilities**. To escape different contexts of a HTML document, |
| 5 | +zend-view provides 5 helpers: |
| 6 | + |
| 7 | +* [`EscapeCss`](#escapecss) |
| 8 | +* [`EscapeHtml`](#escapehtml) |
| 9 | +* [`EscapeHtmlAttr`](#escapehtmlattr) |
| 10 | +* [`EscapeJs`](#escapejs) |
| 11 | +* [`EscapeUrl`](#escapeurl) |
| 12 | + |
| 13 | +More informations to the operation and the background of security can be found |
| 14 | +in the |
| 15 | +[documentation of zend-escaper](https://docs.zendframework.com/zend-escaper/configuration/). |
| 16 | + |
| 17 | +> ### Installation Requirements |
| 18 | +> |
| 19 | +> The escape helpers depends on the zend-escaper component, so be sure to have |
| 20 | +> it installed before getting started: |
| 21 | +> |
| 22 | +> ```bash |
| 23 | +> $ composer require zendframework/zend-escaper |
| 24 | +> ``` |
| 25 | +
|
| 26 | +## EscapeCss |
| 27 | +
|
| 28 | +```php |
| 29 | +$css = <<<CSS |
| 30 | +body { |
| 31 | + background-image: url('http://example.com/foo.jpg?</style><script>alert(1)</script>'); |
| 32 | +} |
| 33 | +CSS; |
| 34 | +
|
| 35 | +echo $this->escapeCss($css); |
| 36 | +``` |
| 37 | +
|
| 38 | +Output: |
| 39 | + |
| 40 | +```css |
| 41 | +body\20 \7B \D \A \20 \20 \20 \20 background\2D image\3A \20 url\28 \27 http\3A \2F \2F example\2E com\2F foo\2E jpg\3F \3C \2F style\3E \3C script\3E alert\28 1\29 \3C \2F script\3E \27 \29 \3B \D \A \7D |
| 42 | +``` |
| 43 | + |
| 44 | +## EscapeHtml |
| 45 | + |
| 46 | +```php |
| 47 | +$html = "<script>alert('zend-framework')</script>"; |
| 48 | + |
| 49 | +echo $this->escapeHtml($html); |
| 50 | +``` |
| 51 | + |
| 52 | +Output: |
| 53 | + |
| 54 | +```html |
| 55 | +<script>alert('zend-framework')</script> |
| 56 | +``` |
| 57 | + |
| 58 | +## EscapeHtmlAttr |
| 59 | + |
| 60 | +```php+html |
| 61 | +<?php $html = 'faketitle onmouseover=alert(/zend-framework/);'; ?> |
| 62 | +
|
| 63 | +<a title=<?= $this->escapeHtmlAttr($html) ?>>click</a> |
| 64 | +``` |
| 65 | + |
| 66 | +Output: |
| 67 | + |
| 68 | +```html |
| 69 | +<a title=faketitle onmouseover=alert(/zend-framework/);>click</a> |
| 70 | +``` |
| 71 | + |
| 72 | +## EscapeJs |
| 73 | + |
| 74 | +```php |
| 75 | +$js = "window.location = 'https://framework.zend.com/?cookie=' + document.cookie"; |
| 76 | + |
| 77 | +echo $this->escapeJs($js); |
| 78 | +``` |
| 79 | + |
| 80 | +Output: |
| 81 | + |
| 82 | +```js |
| 83 | +window.location\x20\x3D\x20\x27https\x3A\x2F\x2Fframework.zend.com\x2F\x3Fcookie\x3D\x27\x20\x2B\x20document.cookie |
| 84 | +``` |
| 85 | + |
| 86 | +## EscapeUrl |
| 87 | + |
| 88 | +```php |
| 89 | +<?php |
| 90 | +$url = <<<JS |
| 91 | +" onmouseover="alert('zf2') |
| 92 | +JS; |
| 93 | +?> |
| 94 | + |
| 95 | +<a href="http://example.com/?name=<?= $this->escapeUrl($url) ?>">click</a> |
| 96 | +``` |
| 97 | + |
| 98 | +Output: |
| 99 | + |
| 100 | +```html |
| 101 | +<a href="http://example.com/?name=%22%20onmouseover%3D%22alert%28%27zf2%27%29">click</a> |
| 102 | +``` |
| 103 | + |
| 104 | +## Using Encoding |
| 105 | + |
| 106 | +```php |
| 107 | +$this->escapeHtml()->setEncoding('iso-8859-15'); |
| 108 | +``` |
| 109 | + |
| 110 | +All allowed encodings can be found in the |
| 111 | +[documentation of zend-escaper](https://docs.zendframework.com/zend-escaper/configuration/). |
| 112 | + |
| 113 | +### Get Current Value |
| 114 | + |
| 115 | +To get the current value of this option, use the `getEncoding()` method. |
| 116 | + |
| 117 | +```php |
| 118 | +$this->escapeHtml()->setEncoding('iso-8859-15'); |
| 119 | + |
| 120 | +echo $this->escapeHtml()->getEncoding(); // iso-8859-15 |
| 121 | +``` |
| 122 | + |
| 123 | +### Default Value |
| 124 | + |
| 125 | +The default value for all escape helpers is `utf-8`. |
| 126 | + |
| 127 | +## Using Recursion |
| 128 | + |
| 129 | +All escape helpers can use recursion for the given values during the escape |
| 130 | +operation. This allows the escaping of the datatypes `array` and `object`. |
| 131 | + |
| 132 | +### Escape an Array |
| 133 | + |
| 134 | +To escape an `array`, the second parameter `$recurse` must be use the constant |
| 135 | +`RECURSE_ARRAY` of an escape helper: |
| 136 | + |
| 137 | +```php |
| 138 | +$html = [ |
| 139 | + 'headline' => '<h1>Foo</h1>', |
| 140 | + 'content' => [ |
| 141 | + 'paragraph' => '<p>Bar</p>', |
| 142 | + ], |
| 143 | +]; |
| 144 | + |
| 145 | +var_dump($this->escapeHtml($html, Zend\View\Helper\EscapeHtml::RECURSE_ARRAY)); |
| 146 | +``` |
| 147 | + |
| 148 | +Output: |
| 149 | + |
| 150 | +```php |
| 151 | +array(2) { |
| 152 | + 'headline' => |
| 153 | + string(24) "<h1>Foo</h1>" |
| 154 | + 'content' => |
| 155 | + array(1) { |
| 156 | + 'paragraph' => |
| 157 | + string(22) "<p>Bar</p>" |
| 158 | + } |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +### Escape an Object |
| 163 | + |
| 164 | +An escape helper can use the `__toString()` method of an object. No additional |
| 165 | +parameter is needed: |
| 166 | + |
| 167 | +```php |
| 168 | +$object = new class { |
| 169 | + public function __toString() : string |
| 170 | + { |
| 171 | + return '<h1>Foo</h1>'; |
| 172 | + } |
| 173 | +}; |
| 174 | + |
| 175 | +echo $this->escapeHtml($object); // "<h1>Foo</h1>" |
| 176 | +``` |
| 177 | + |
| 178 | +An escape helper can also use the `toArray()` method of an object. The second |
| 179 | +parameter `$recurse` must be use the constant `RECURSE_OBJECT` of an escape |
| 180 | +helper: |
| 181 | + |
| 182 | +```php |
| 183 | +$object = new class { |
| 184 | + public function toArray() : array |
| 185 | + { |
| 186 | + return ['headline' => '<h1>Foo</h1>']; |
| 187 | + } |
| 188 | +}; |
| 189 | + |
| 190 | +var_dump($this->escapeHtml($object, Zend\View\Helper\EscapeHtml::RECURSE_OBJECT)); |
| 191 | +``` |
| 192 | + |
| 193 | +Output: |
| 194 | + |
| 195 | +```php |
| 196 | +array(1) { |
| 197 | + 'headline' => |
| 198 | + string(3) "<h1>Foo</h1>" |
| 199 | +} |
| 200 | +``` |
| 201 | + |
| 202 | +If the object does not contains the methods `__toString()` or `toArray()` then |
| 203 | +the object is casted to an `array`: |
| 204 | + |
| 205 | +```php |
| 206 | +$object = new class { |
| 207 | + public $headline = '<h1>Foo</h1>'; |
| 208 | +}; |
| 209 | + |
| 210 | +var_dump($this->escapeHtml($object, Zend\View\Helper\EscapeHtml::RECURSE_OBJECT)); |
| 211 | +``` |
| 212 | + |
| 213 | +Output: |
| 214 | + |
| 215 | +```php |
| 216 | +array(1) { |
| 217 | + 'headline' => |
| 218 | + string(3) "<h1>Foo</h1>" |
| 219 | +} |
| 220 | +``` |
| 221 | + |
| 222 | +## Using Custom Escaper |
| 223 | + |
| 224 | +Create an own instance of `Zend\Escaper\Escaper` and set to any of the escape |
| 225 | +helpers: |
| 226 | + |
| 227 | +```php |
| 228 | +$escaper = new Zend\Escaper\Escaper('utf-8'); |
| 229 | + |
| 230 | +$this->escapeHtml()->setEscaper($escaper); |
| 231 | +``` |
| 232 | + |
| 233 | +### Get Current Value |
| 234 | + |
| 235 | +To get the current value, use the `getEscaper()` method. |
| 236 | + |
| 237 | +```php |
| 238 | +<?php |
| 239 | +$escaper = new Zend\Escaper\Escaper('utf-8'); |
| 240 | +$this->escapeHtml()->setEscaper($escaper); |
| 241 | + |
| 242 | +var_dump($this->escapeHtml()->getEscaper()); // instance of Zend\Escaper\Escaper |
| 243 | +``` |
| 244 | + |
| 245 | +### Default Value |
| 246 | + |
| 247 | +The default value is an instance of `Zend\Escaper\Escaper`, created by the |
| 248 | +helper. |
0 commit comments