<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/web/13970

            0x00 前言


            在第一章結尾的時候我就已經說了,這一章將會更詳細的介紹前端防火墻的報警機制及代碼。在一章出來后,有人會問為什么不直接防御,而是不防御報警呢。很簡單,因為防御的話,攻擊者會定位到那一段的JavaScript代碼,從而下次攻擊的時候繞過代碼。如果不防御而報警的話,攻擊者會降低警覺,不會在看JavaScript代碼(至少我是這樣)。回到正題,下面說的代碼,是基于thinkphp框架和bootstrap3.3.5框架。如果你的網站沒有使用thinkphp3.2.3框架的話,可以參照我的思路重新寫一個。這里我強調一下“前端防御XSS是建立在后端忘記做過濾,沒有做過濾,疏忽做過濾的基礎上的...

            0x01 前端要做的事


            其實標題應該改成“XSS報警機制”的,因為在這一章里使用了大量的后端代碼。但是第一章的標題都出來了,也沒法改了。

            前端要做的事情在第一章的時候就已經說了,代碼如下:

            p1

            現在我們就是針對第38行進行修改,改成我們后臺接受的API URL。就像這樣:

            p2

            對,就這一行。沒有其他代碼。在實際的線上環境中,也只需要上面5行。可以直接copy到您的線上環境中,記得把倒數第二行的url改成自己的地址就行了。難道就那么簡單?不,0x05節還有一部分前端代碼。0x01~0x04主要是針對于平臺。

            0x02 數據庫要做的事


            一共兩個表。fecm_user和fecm_bugdata。

            fecm_user的字段信息如下:

            p3

            為了安全起見(其實就是懶)沒有寫添加管理員的,自行在數據庫里添加

            fecm_bugdata的字段信息如下:

            p4

            0x03 后端要做的事


            因為后端代碼太多,所以我就說一些核心的后端處理代碼。

            在0x01節里,有個核心的代碼是new Image().src = 'http://fecm.cn/Api/addVul/';

            接下來我們來說說這個Api的處理方式(ThinkPHP代碼)

            #!php
            public function addVul(){
                if(I('get.category','','int') == ""){
                    $this->ajaxReturn(array(
                        "typeMsg" =>  "error",
                        "msgText" =>  "漏洞類型錯誤",
                    ));
                }
                switch (I('get.category','','int')) {
                    case '1':
                        $vul['category'] = "觸發alret函數";
                        break;
                    case '2':
                        $vul['category'] = "發現不在白名單里的第三方JavaScript資源";
                        break;
                    default:
                        $this->ajaxReturn(array(
                            "typeMsg" =>  "error",
                            "msgText" =>  "漏洞類型錯誤",
                        ));
                        break;
                }
                if($_SERVER['HTTP_X_FORWARDED_FOR'] === null){
                    $vul['hxff_ip'] = "攻擊者沒有通過代理服務器訪問";
                }else{
                    $vul['hxff_ip'] = I('server.HTTP_X_FORWARDED_FOR'); //獲取攻擊者的HTTP_X_FORWARDED_FOR
                }
                if($_SERVER['HTTP_CLIENT_IP'] === null){
                    $vul['hci_ip'] = "攻擊者數據包頭部沒有HTTP_CLIENT_IP";
                }else{
                    $vul['hci_ip'] = I('server.HTTP_CLIENT_IP');//獲取攻擊者的HTTP_CLIENT_IP
                }
                $vul['ra_ip'] = I('server.REMOTE_ADDR');    //獲取攻擊者的REMOTE_ADDR
                $vulcookie    = I('cookie.');   //獲取攻擊者的cookies
                for($i = 0;$i<count($vulcookie);$i++){
                    $vul['cookies'] .= array_keys($vulcookie)[$i].'='.$vulcookie[array_keys($vulcookie)[$i]].'; ';  //拼接成方便查看的cookies格式
                }
                $vul['url']   = I('server.HTTP_REFERER');   //獲取攻擊者攻擊成功的url
                $vul['ua']    = I('server.HTTP_USER_AGENT');    //獲取攻擊者的User-Agent
                $vul['time']  = date("Y-m-d");  //獲取攻擊者攻擊的時間
                $vul['fixes'] = 0;  //默認為漏洞未修復
                $bugData = M('bugdata');    //連接fecm_bugdata數據庫
                $bugData->data($vul)->add();    //添加到數據庫中
            }
            

            因為這里是接受攻擊信息,不能有管理員驗證。

            后臺有一個數據庫可視化的表格,這里我使用的Chart.js,下面是后端代碼:

            #!php
            public function index(){
                $reportForm = M('bugdata'); //連接fecm_bugdata數據庫
                $dateTimeLabels = [];
                $dateTimeTotal = [];
                for($i = 0;$i < 7;$i++){    //獲取近7天的數據
                    $time = date("Y-m-d",strtotime(-$i." day"));
                    array_unshift($dateTimeLabels,$time);
                    $data['time'] = array('like','%'.$time.'%');
                    array_unshift($dateTimeTotal,$reportForm->where($data)->count());
                }
                $reportForm = json_encode(["Labels" => $dateTimeLabels,"Total" => $dateTimeTotal]); //轉化成json格式
                $this->assign('reportForm',$reportForm)->assign('total',total());   //交給前端模塊
                $this->display();   //前端頁面生成
            }
            

            前端代碼:

            #!js
            var lineChartData = {
                labels :eval({$reportForm})['Labels'],
                datasets : [
                    {
                        fillColor : "rgba(151,187,205,0.5)",
                        strokeColor : "rgba(151,187,205,1)",
                        pointColor : "rgba(151,187,205,1)",
                        pointStrokeColor : "#fff",
                        data : eval({$reportForm})['Total']
                    }
                ]
            }
            var myLine = new Chart(document.getElementById("Statistics").getContext("2d")).Line(lineChartData);
            

            實際的效果圖:

            p5

            p6

            p7

            0x04 讓我們實際測試一下


            代碼就用0x01節的代碼。我們輸入<script>alert(1)</script>。看一下:

            p8

            我們再去平臺看一下:

            p9

            p10

            成功顯示了。

            0x05 檢測第三方js資源是否為xss腳本


            這一節需要用到之前長短短分享的代碼:

            #!js
            for(var i=0,tags=document.querySelectorAll('iframe[src],frame[src],script[src],link[rel=stylesheet],object[data],embed[src]'),tag;tag=tags[i];i++){ 
                var a = document.createElement('a'); 
                a.href = tag.src||tag.href||tag.data; 
                if(a.hostname!=location.hostname){ 
                    console.warn(location.hostname+' 發現第三方資源['+tag.localName+']:'+a.href); 
                }
            }
            

            但是他這里只是在console里顯示,沒有進一步的操作,而且他這里同時檢測了iframe、frame、script、link、object、embed標簽,對我們來說只需要script標簽就行了,于是我重寫了這段代碼,首先我們需要一個白名單列表,用于放置網站允許第三方加載的url地址:

            #!js
            var scriptList = [
                location.hostname,
            ]
            

            這里只是默認的只允許當前域名加載,打擊愛可以根據自己的需要添加。

            然后就是獲取當前網頁的所有script標簽:

            #!js
            var webScript = document.querySelectorAll('script[src]');
            

            在把當前的地址賦值var webHost = location.hostname;至于為什么不放在for循環里,因為根據js優化規則,for循環里避免多次一樣的賦值。

            接下來就是for循環里的代碼了:

            #!js
            for(var i = 0;i < webScript.length;i++){
                var a = document.createElement('a');    //建立一個新的a標簽,方便取值
                a.href = webScript[i].src;  //把script里的src賦值給a標簽里的href屬性
                if(a.hostname != webHost){  //對比,是否為第三方資源
                    for(var j = 0;j < scriptList.length;j++){
                        if(a.hostname != scriptList[i]){    //判斷當前的第三方資源是否在白名單里
                            new Image().src = 'http://fecm.cn/Api/addVul/category/2';   //發送給FECM
                        }
                    }
                }
            }
            

            這里我做了一個測試,加載hi.baidu.com的資源:

            p11

            刷新后,打開FECM平臺,看一下:

            p12

            p13

            0x06 結語


            因為窮,沒有服務器和域名,也沒法添加郵件自動提醒功能了。感興趣的可以自己添加,如果后來我有錢了,我買個服務器,會添加郵件自動提醒的,第一時間會在烏云社區里發布。本來打算采用ED的on事件攔截代碼的,但是發現on事件在程序里也會大量使用,索性就沒有添加,如果你有思路

            下載地址:http://pan.baidu.com/s/1jGVP7Ps

            使用時記得在Application\Home\Conf\config.php改下配置(我已經全部加了注釋,即使不會thinkphp的也可以搭建)

            個人代碼寫的沒有多好,思路可能也比較爛。如果您有什么意見歡迎提出來,我會進一步修改的。

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线