Slide 1

Slide 1 text

HTML5時代の安全なエスケープ手法 Secure Escaping method for the age of HTML5 Yoshinori TAKESAKO @takesako Cybozu Labs, Inc.

Slide 2

Slide 2 text

about:TAKESAKO OWASP JAPAN Advisory Board  2008: Microsoft MVP "Developer Security" 2011: SC22/ECMAScript (ISO/IEC 16262) 2012: HTML5 technical review (coauthor) 2013: ECMA-262 Edition 5.1 (en2ja)

Slide 3

Slide 3 text

Today's agenda XSS is a threat consistently listed in the OWASP Top 10  1. to prevent XSS, it is necessary to different appropriate escaping 2. but it cause human error and easily lead to careless mistakes 3. contextual automatic HTML escaping method became a realistic solution with popularization of HTML5 Syntax

Slide 4

Slide 4 text

ESCAPE, TO BE SECURE エスケープを、 確かなものに。

Slide 5

Slide 5 text

ESCAPE, TO BE SECURE 1. History of HTML escaping method  "PHP" of the good old days  template engines got default escaping 2. Modern HTML escaping method  "contextual" automatic escaping  AngularJS, Closure Templates … 3. HTML5 syntax  parser bugs 4. Excursus Excluding - How to prevent SQL injection - New solution of DOM based XSS

Slide 6

Slide 6 text

PHP 1. History of HTML ESCAPE

Slide 7

Slide 7 text

Simple XSS alert(1) [Input] $x alert(1) [Output] XSS... 

Slide 8

Slide 8 text

(1) htmlspecialchars alert(1) [Input] $x <script>alert(1)</script> [Output] secure? 

Slide 9

Slide 9 text

%27 ... single quote ' onfocus=alert(1) autofocus ' [Input] $x ...value='' onfocus=alert(1) autofocus ''> [Output] XSS... 

Slide 10

Slide 10 text

(2) ENT_QUOTES ' onfocus=alert(1) autofocus ' [Input] $x ' onfocus=alert(1) autofocus ' [Output] secure? 

Slide 11

Slide 11 text

%82 ... a multi-byte char

Slide 12

Slide 12 text

(3) valid charset encoding '>

Slide 13

Slide 13 text

Smarty 1. History of HTML ESCAPE

Slide 14

Slide 14 text

Smarty {$x} alert(1) [Input] $x alert(1) [Output] XSS 

Slide 15

Slide 15 text

Smarty|escape:"html" {$x|escape:"html"} alert(1) [Input] $x </title><script>alert(1)<... [Output] secure 

Slide 16

Slide 16 text

Default all ESCAPE setting {$str} == {$str|escape:"html"} Smarty 2 {$inner_html|smarty:nodefaults} Smarty 3 {$inner_html nofilter} $smarty = new Smarty(); $smarty->default_modifiers = array('escape:"html"');

Slide 17

Slide 17 text

Quiz How to ESCAPE ?

Slide 18

Slide 18 text

Q. How to ESCAPE ? $x1, $x2, $x3, $x4, $x5, $x6, $x7 {$x3} var x = '{$x4}'; var y = {$x5}; body { background:url(/path?q={$x6}); } div { font-family: "{$x7}"; }

Slide 19

Slide 19 text

Smarty|escape:"TYPE" TYPE {$str|escape:"TYPE"} 1 html htmlspecialchars($str, ENT_QUOTES, $charset); 2 htmlall htmlentities($str, ENT_QUOTES, $charset); 3 quotes '  ¥' 4 url rawurlencode($str); 5 urlpathinfo str_replace('%2F','/',rawurlencode($str)); 6 hex ABC  %41%42%43 7 hexentity ABC  ABC 8 mail str_replace('@',' [AT] '), str_replace('.',' [DOT] '), $str)); 9 javascript ¥¥¥, '¥', "¥", ¥r¥¥r, ¥n¥¥n,

Slide 20

Slide 20 text

escaping-craftworker [要]エスケープ職人

Slide 21

Slide 21 text

There are no "Swiss Army Knife" URL encode HTML escape 図:彩画職人部類(天明4年)大正期復刻版 より CSS escape

Slide 22

Slide 22 text

AngularJS 2. Modern HTML ESCAPE method

Slide 23

Slide 23 text

AngularJS Open-source JavaScript MVC framework originally developed in 2009 by Miško Hevery and Adam Abrons.

Slide 24

Slide 24 text

A[ng]ularJS ng-app Declares an element as a root element of the application allowing behavior to be modified through custom HTML tags. ng-bind ng-bind-html Automatically changes the text of an HTML element to the value of a given expression. ng-model Similar to ng-bind, but allows two-way data binding between the view and the scope. ng-class Allows class attributes to be dynamically loaded. ng-controller Specifies a JavaScript controller class that evaluates HTML expressions. ng-repeat Instantiate an element once per item from a collection. ng-show ng-hide Conditionally show or hide an element, depending on the value of a boolean expression. Show and hide is achieved by setting the CSS display style. ng-switch Conditionally instantiate one template from a set of choices, depending on the value of a selection expression. ng-view The base directive responsible for handling routes that resolve JSON before rendering templates driven by specified controllers. ng-if Basic if statement directive which allow to show the following element if the conditions are true. When the condition is false, the element is removed from the DOM. When true, a clone of the compiled element is re-inserted.

Slide 25

Slide 25 text

AngularJS: ng.$sce SCE = Strict Context Escaping {{x}}

Slide 26

Slide 26 text

AngularJS: ng.$sce  demo

Slide 27

Slide 27 text

AngularJS: ng.$sce 

Slide 28

Slide 28 text

docs.angularjs.org/api/ng/service/$sce Context Notes $sce.HTML For HTML that's safe to source into the application. The ngBindHtml directive uses this context for bindings. $sce.URL For URLs that are safe to follow as links. Currently unused (

Slide 29

Slide 29 text

[FYI] AngularJS security 30分かも…

Slide 30

Slide 30 text

Closure Templates 2. Modern HTML ESCAPE method

Slide 31

Slide 31 text

Closure Templates Java & JavaScript templating tools

Slide 32

Slide 32 text

example.soy (1/2) {namespace example autoescape="contextual"} /** * example of autoescape contextual * @param x1 * @param x2 * @param x3 * @param x4 * @param x5 * @param x6 * @param x7 */ {template .render} ... {/template} example.soy (2/2)

Slide 33

Slide 33 text

example.soy (2/2) {template .render} {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb}

Slide 34

Slide 34 text

Closure Templates SoyToJsSrcCompiler.jar [INPUT] example.soy [OUTPUT] example.js Compiled to JavaScript source code > java -jar SoyToJsSrcCompiler.jar --outputPathFormat example.js --srcs example.soy

Slide 35

Slide 35 text

Result ??? soy.$$escapeHtml(opt_data.x1); soy.$$escapeHtml(opt_data.x2); soy.$$escapeHtml(opt_data.x3); soy.$$escapeHtml(opt_data.x4); soy.$$escapeHtml(opt_data.x5); soy.$$escapeHtml(opt_data.x6); soy.$$escapeHtml(opt_data.x7);

Slide 36

Slide 36 text

Result : example.js // This file was automatically generated from example.soy. // Please don't edit this file by hand. if (typeof example == 'undefined') { var example = {}; } example.render = function(opt_data, opt_ignored) { return '' + soy.$$escapeHtml(opt_data.x3) + '' + 'var x = ¥'' + soy.$$escapeJsString(opt_data.x4) + '¥'; var y = ' + soy.$$escapeJsValue(opt_data.x5) + ';<¥/script>' + '<style>body{ ' + 'background:url(/path?q=' + soy.$$escapeUri(opt_data.x6) + '); }' + 'div { font-family: "' + soy.$$escapeCssString(opt_data.x7) + '"; }' + '</style>'; };

Slide 37

Slide 37 text

Result (autoescape="contextual") soy.$$escapeHtmlAttribute( soy.$$filterNormalizeUri(opt_data.x1) ); soy.$$escapeHtmlAttribute( soy.$$escapeJsValue(opt_data.x2) ); soy.$$escapeHtml(opt_data.x3); soy.$$escapeJsString(opt_data.x4); soy.$$escapeJsValue(opt_data.x5); soy.$$escapeUri(opt_data.x6); soy.$$escapeCssString(opt_data.x7);

Slide 38

Slide 38 text

Result (autoescape="contextual") {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb}

Slide 39

Slide 39 text

Result (autoescape="contextual") {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb} soy.$$escapeHtmlAttribute( soy.$$filterNormalizeUri(opt_data.x1) );

Slide 40

Slide 40 text

Result (autoescape="contextual") {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb} soy.$$escapeHtmlAttribute( soy.$$escapeJsValue(opt_data.x2) );

Slide 41

Slide 41 text

Result (autoescape="contextual") {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb} soy.$$escapeHtml(opt_data.x3);

Slide 42

Slide 42 text

Result (autoescape="contextual") {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb} soy.$$escapeJsString(opt_data.x4);

Slide 43

Slide 43 text

Result (autoescape="contextual") {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb} soy.$$escapeJsValue(opt_data.x5); null, true, false, 3.14, 'toString()'

Slide 44

Slide 44 text

Result (autoescape="contextual") {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb} soy.$$escapeUri(opt_data.x6);

Slide 45

Slide 45 text

Result (autoescape="contextual") {$x3} var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb} soy.$$escapeCssString(opt_data.x7);

Slide 47

Slide 47 text

Substitutions in CSS div#{$id} { } Classes and IDs 1 "foo-bar" → div#foo-bar { }
Property Names 5 "left" →
6 "right" →
URLs in CSS are handled as in attributes above 9 "/foo/bar" →
10 "javascript:alert(1337)" →
11 "?q=(O'Reilly) OR Books" →
Quantities 2 "red" →
3 "#f00" →
4 "expression('alert(1337)')" →
p{font-family:'{$x}'} Quoted Values 7 "Arial" → p{font-family:'Arial'} 8 "" → p{font-family:'¥3c /style¥3e '}

Slide 48

Slide 48 text

[FYI] autoescape="contextual"

Slide 49

Slide 49 text

However, HTML parser is valid? {$x3} <!-- -- broken HTML--- -><!-!> var x = '{$x4}'; var y = {$x5}; body{lb} background:url(/path?q={$x6});{rb} div {lb} font-family: "{$x7}"; {rb}

Slide 50

Slide 50 text

Parser bugs 3. HTML syntax

Slide 51

Slide 51 text

HTML syntax

Slide 52

Slide 52 text

HTML syntax checker [demo] HTML5 Syntax Checker

Your Browser is...


http://www.w3.org/TR/html5/syntax.html

Slide 53

Slide 53 text

Opera8.54

Slide 54

Slide 54 text

Internet Explorer 8

Slide 55

Slide 55 text

Netscape6.23

Slide 56

Slide 56 text

Netscape7.1

Slide 57

Slide 57 text

Safari 4.0.3 (531.9.1)

Slide 58

Slide 58 text

Firefox 3.6.12

Slide 59

Slide 59 text

Lynx2.8.5

Slide 60

Slide 60 text

HTML 45 3. HTML syntax

Slide 61

Slide 61 text

HTM5 Syntax (W3C)

Slide 62

Slide 62 text

defined HTML5 Syntax

Your Browser is...

Slide 63

Slide 63 text

Safari 5.1.1+

Slide 64

Slide 64 text

Google Chrome7.0.517.44+

Slide 65

Slide 65 text

Firefox 10.0.2 +

Slide 66

Slide 66 text

Shazzer 3. HTML syntax

Slide 67

Slide 67 text

Shazzer - shared online fuzzing

Slide 68

Slide 68 text

fuzz.shazzer.co.uk test

Slide 69

Slide 69 text

Characters-allowed-after-slash test

Slide 70

Slide 70 text

JS Parser 3. HTML syntax

Slide 71

Slide 71 text

ECMA-262 (5th Edition)

Slide 72

Slide 72 text

ISO/IEC 16262:2011

Slide 73

Slide 73 text

ECMAScript 5 Conformance Suite

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

No content

Slide 77

Slide 77 text

CSS Hacks 4. Excursus

Slide 78

Slide 78 text

CSS Hacks CSS Hacks must die ...  body { color: red; /* all browsers */ color: green¥9; /* IE6,7,8 */ *color: yellow; /* IE6,7 */ _color: orange; /* IE6 */ }

Slide 79

Slide 79 text

Data-Taint Security 4. Excursus

Slide 80

Slide 80 text

JavaScript Data-Taint security

Slide 81

Slide 81 text

Netscape Navigator 2.0 / 3.0

Slide 82

Slide 82 text

set NS_ENABLE_TAINT=1 taint(), untaint() Object Tainted properties and methods document cookie, domain, forms[], lastModified, links[], location, referrer, title, URL form action all form input elements: button, checkbox, fileupload, hidden, password, radio, reset, select, submit, text, textarea checked, defaultChecked, defaultValue, name, selectedIndex, toString(), value history current, next, previous,toString(), all array elements location, link, area hash, host, hostname, href, pathname, port, protocol, search, toString() option defaultSelected, selected, text, value window defaultStatus, status

Slide 83

Slide 83 text

Netscape Navigator 2.0+ navigator.taintEnabled() Mozilla Firefox 28 Opera 15  no method Internet Explorer 11 Historical reasons: removed in JavaScript version 1.2

Slide 84

Slide 84 text

MooTools 1.2.6 browser detect Browser = $merge({ Engine: {name: 'unknown', version: 0}, Engines: { presto: function(){ return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }, trident: function(){ return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); }, webkit: function(){ return (navigator.taintEnabled) ? false : ((Browser.Features.xpath)?((Browser.Features.query) ? 525 : 420) : 419); }, gecko: function(){ return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18); } },

Slide 85

Slide 85 text

温故知新 Taking a lesson from the past !

Slide 86

Slide 86 text

References AngularJS  http://angularjs.org/ Closure Templates  https://code.google.com/p/closure-templates/ Shazzer  http://shazzer.co.uk/ teppeis blog (ja)  http://teppeis.hatenablog.com/

Slide 87

Slide 87 text

Conclutions 5. Conclusions

Slide 88

Slide 88 text

Conclusions 1. Contextual automatic HTML escaping became a new solution to prevent XSS 2. HTML5 Syntax HTML5 Parser can be implemented same algorithm in the server-side and client-side 3. Broken HTML5 parser is browser's bug If you find a parse error, please report it  4. Static analysis is very useful But it can not solved the DOM based XSS Needs dynamic data-tainting security model

Slide 89

Slide 89 text

Thank you ご清聴ありがとうございました