$30 off During Our Annual Pro Sale. View Details »

JSでDoSる/ Shibuya.XSS techtalk #11

JSでDoSる/ Shibuya.XSS techtalk #11

Shibuya.XSS techtalk #11 の発表資料です。

Masato Kinugawa

May 16, 2019
Tweet

More Decks by Masato Kinugawa

Other Decks in Technology

Transcript

  1. for(;;){
    alert(`
    `);
    } /* 2019/05/16 Shibuya.XSS techtalk #11*/
    /* Masato Kinugawa */

    View Slide




  2. View Slide

  3. View Slide






  4. View Slide





  5. View Slide












  6. View Slide

  7. while(1){
    alert(`
    `);
    }

    View Slide



  8. View Slide


  9. View Slide



  10. > decodeURIComponent("%E3%81%82");
    < " "
    > decodeURIComponent("%FF");
    ‣ Uncaught URIError: URI malformed

    View Slide

  11. View Slide




  12. > encodeURIComponent(" ");
    < "%E3%81%82"
    > encodeURIComponent("\uDC00");
    ‣ Uncaught URIError: URI malformed

    View Slide

  13. https://www.ecma-international.org/ecma-262/9.0/index.html#sec-encode

    View Slide

  14. (function a(){
    alert(`
    `);
    a();
    })()

    View Slide




  15. • / \/
    • " \"
    • \ \\
    <br/>userInput = "AAA\\\";alert(1)\/\/ <\/script>";<br/>displayContents();<br/>

    View Slide


  16. <br/>userInput = "AAA [ ] BBB";<br/>displayContents();<br/>

    View Slide


  17. <br/>userInput = "AAA<br/>BBB";<br/>displayContents();<br/>

    View Slide


  18. https://www.ecma-international.org/ecma-262/9.0/index.html#table-33

    View Slide


  19. https://www.ecma-international.org/ecma-262/9.0/index.html#table-33

    View Slide


  20. <br/>userInput = "AAA [U+2028] BBB";<br/>displayContents();<br/>

    View Slide






  21. View Slide

  22. <br/>userInput = "<!--<script>";<br/>displayContents();<br/>

    View Slide



  23. <br/>userInput = "<!--<script>";<br/>



    View Slide



  24. https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-
    elements

    View Slide


  25. <br/>userInput = "<%";<br/>
    %>

    https://html5sec.org/#91
    <%
    %>

    View Slide






  26. View Slide

  27. setInterval(`
    alert(\`
    \`)
    `,1);

    View Slide



  28. View Slide


  29. View Slide




  30. userInfo = {"name": 123}//
    name = userInfo.name.toUpperCase()
    Uncaught TypeError:
    userInfo.name.toUpperCase is not a function

    View Slide

  31. siteData =
    {"url":"https:// ...","title":{"toString":null},...};
    url = "url: " + siteData.url;
    title = "title: " + siteData.title;

    View Slide




  32. ({toString: function(){alert(1)} })+"";
    ({valueOf : function(){alert(2)} })+"";

    View Slide




  33. > ({toString:null})+"";
    ‣ Uncaught TypeError:
    Cannot convert object to primitive value

    View Slide






  34. View Slide


  35. > typeof "aaa";
    < ‣ "string"
    > typeof 123;
    < ‣ "number"
    > typeof true;
    < ‣ "boolean"
    > typeof [];
    < ‣ "object"
    > typeof {};
    < ‣ "object"
    > typeof null;
    < ‣ "object"

    View Slide



  36. > Array.isArray([]);
    < ‣ true
    > Array.isArray({});
    < ‣ false
    > null === null
    < ‣ true

    View Slide



  37. > Object.prototype.toString.call("aaa");
    < ‣ "[object String]"
    > Object.prototype.toString.call(123);
    < ‣ "[object Number]"
    > Object.prototype.toString.call(true);
    < ‣ "[object Boolean]"
    > Object.prototype.toString.call([]);
    < ‣ "[object Array]"
    > Object.prototype.toString.call({});
    < ‣ "[object Object]"
    > Object.prototype.toString.call(null);
    < ‣ "[object Null]"

    View Slide

  38. *{<br/>color:expression(<br/>alert("<br/>")<br/>)}<br/>

    View Slide




  39. AAA

    View Slide




  40. View Slide



  41. function tellMeFruitColor(USER_INPUT){
    fruits = {
    "apple":"red",
    "lemon":"yellow",
    "peach":"pink"
    };
    if(fruits[USER_INPUT]){
    return USER_INPUT + ": " + fruits[USER_INPUT];
    }else{
    return "I don't know that fruit";
    }
    }

    View Slide

  42. > tellMeFruitColor("apple");
    < "apple: red"
    > tellMeFruitColor("lemon");
    < "lemon: yellow"
    > tellMeFruitColor("strawberry");
    < "I don't know that fruit"
    > tellMeFruitColor("toString");
    < "toString: function toString() { [native code] }"
    > tellMeFruitColor("constructor");
    < "constructor: function Object() { [native code] }"
    > tellMeFruitColor("__proto__");
    < "__proto__: [object Object]"

    View Slide

  43. View Slide



  44. View Slide

  45. https://qiita.com/howdy39/items/35729490b024ca295d6c

    View Slide

  46. if(fruits["toString"]){
    return "toString" + ": " + fruits["toString"];
    }else{
    return "I don't know that fruit";
    }

    View Slide

  47. if(fruits["toString"]){
    return "toString" + ": " + fruits["toString"];
    }else{
    return "I don't know that fruit";
    }

    View Slide

  48. if(fruits["toString"]){
    return "toString" + ": " + fruits["toString"];
    }else{
    return "I don't know that fruit";
    }

    View Slide

  49. if(fruits["toString"]){
    return "toString" + ": " + fruits["toString"];
    }else{
    return "I don't know that fruit";
    }

    View Slide

  50. if(fruits["toString"]){
    return "toString" + ": " + fruits["toString"];
    }else{
    return "I don't know that fruit";
    }

    View Slide

  51. if(fruits["toString"]){
    return "toString" + ": " + fruits["toString"];
    }else{
    return "I don't know that fruit";
    }

    View Slide

  52. > ({"toString":function(){return "a"}})+"";
    < " "
    > ({"prop":"a"})+"";
    < "[object Object]"

    View Slide

  53. whiteListTags = {
    "span":funcForSanitizingSpanElem,
    "div": funcForSanitizingDivElem,
    "a":" funcForSanitizingAElem, ...
    }
    // whiteListTags[ ]

    whiteListTags["toString"]()

    View Slide

  54. fileIcons = {
    "txt":"https://example.com/img/icon-txt.gif",
    "png":"https://example.com/img/icon-png.gif",
    "jpg":" https://example.com/img/icon-jpg.gif ", ...
    }
    // fileIcons[ ]
    dos.constructor
    fileIcons["constructor"]

    View Slide





  55. View Slide



  56. function tellMeFruitColor(USER_INPUT){
    fruits = { ... };
    - if(fruits[USER_INPUT]){
    + if(Object.prototype.hasOwnProperty.call(fruits,USER_INPUT)){
    return USER_INPUT + ": " + fruits[USER_INPUT];
    }else{
    return "I don't know that fruit";
    }
    }

    View Slide

  57. > tellMeFruitColor("apple");
    < "apple: red"
    > tellMeFruitColor("lemon");
    < "lemon: yellow"
    > tellMeFruitColor("strawberry");
    < "I don't know that fruit"
    > tellMeFruitColor("toString");
    < "I don't know that fruit"
    > tellMeFruitColor("constructor");
    < "I don't know that fruit"
    > tellMeFruitColor("__proto__");
    < "I don't know that fruit"

    View Slide


  58. • fruits["toString"] undefined
    function tellMeFruitColor(USER_INPUT){
    - fruits = { ... };
    + fruits = Object.create(null);
    + fruits = Object.assign(fruits,{"apple":"red","lemon": ... })
    if(fruits[USER_INPUT]){
    return USER_INPUT + ": " + fruits[USER_INPUT];
    }else{
    return "I don't know that fruit";
    }
    }

    View Slide



  59. function tellMeFruitColor(USER_INPUT){
    - fruits = { ... };
    + fruits = new Map(["apple","red"],
    + ["lemon","yellow"],
    + ["peach","pink"]);
    - if(fruits[USER_INPUT]){
    - return USER_INPUT + ": " + fruits[USER_INPUT];
    + if(fruits.get(USER_INPUT)){
    + return USER_INPUT + ": " + fruits.get(USER_INPUT);
    }else{
    return "I don't know that fruit";
    }
    }

    View Slide

  60. ({toString:
    function(){
    alert(`
    `);
    this+"";
    }
    })+"";

    View Slide



  61. View Slide




  62. USER_INPUT = {"length": 1e10,"constructor":{"name":"Array"}};
    if(USER_INPUT.constructor.name === "Array"){
    array = [];
    for (var i = 0; i < USER_INPUT.length; i++) {
    array.push(USER_INPUT[i]);
    }
    }

    View Slide

  63. ==== JS stack trace =========================================
    Security context: 00000099763A5549
    1: /* anonymous */ [repl:~1] [pc=000000C1A3E8B9B9](this=00000382794865D9 Object>)
    5: /* anonymous */ [vm.js:65] [bytecode=000002EDD76E8421
    offset=87](this=0000021A2A00C731 00000203C25E1319>,options=0000021A2A00C709 )
    6: defaultEval [repl.js:244] [bytecode=000002EDD76E7089
    offset=445](this=0000021A2A00C7A1 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
    1: node::DecodeWrite
    2: node_module_register
    3: v8::internal::FatalProcessOutOfMemory
    4: v8::internal::FatalProcessOutOfMemory
    5: v8::internal::Factory::NewUninitializedFixedArray
    6: v8::internal::WasmDebugInfo::SetupForTesting
    7: v8::internal::interpreter::BytecodeArrayRandomIterator::UpdateOffsetFromIndex
    8: 000000C1A3D043C1

    View Slide




  64. View Slide


  65. View Slide






  66. View Slide

  67. for(;;){
    alert(`
    `);
    } /* */

    View Slide