0%

CTF-AWD线下赛劫持流量和流量转发WAF的开发

前言

​ 没参加过CTF线下赛,用别人的waf又不了解其他人写的WAF的代码,万一出了问题也不好解决。因此昨晚连夜写了个WAF。WAF参考了360WAF的正则,对网站流量劫持并转发,cookie流量转发尚未完成。主要是使用了file_get_contents()发送POST和GET流量。如果使用注入等语句,将会对其进行拦截,本项目会劫持所有流量并以json的形式储存在waflog文件夹下(默认),项目初始化会读取waflog下的ip.txt的ip写入数组,对劫持到的所有流量原样转发至该数组下的所有ip,如果存在flag{}(根据比赛修改flag的样式)将会保存至flag.txt

测试

  • 两个服务器存在相同的靶机,分别是120..\.*和本地127.0.0.1

img

  • 本地挂上WAF

img

  • 将远程的靶机添加到waflog\ip.txt,然后对本地靶机进行攻击。发现流量和flag存储在waflog文件夹下。当然也就可以自动提交flag根据不同比赛的发送流量。
  • 本地flag是flag{abc}而远程的flag是flag{I_wan_to_have_a_girlfriend}
  • 发现flag.txt下保存了远程的flag

img

成品代码

<?php
error_reporting(0);
class CTF_WAF{
    public $getfilter;
    public $postfilter;
    public $cookiefilter;
    public $url;
    public $dir;
    public $ip;
    public function __construct() {
         $this->getfilter = "\\<.+javascript:window\\[.{1}\\\\x|<.*=(&#\\d+?;?)+?>|<.*(data|src)=data:text\\/html.*>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*?\(.*\)|sleep\s*?\(.*\)|\\b(group_)?concat[\\s\\/\\*]*?\\([^\\)]+?\\)|\bcase[\s\/\*]*?when[\s\/\*]*?\([^\)]+?\)|load_file\s*?\\()|<[a-z]+?\\b[^>]*?\\bon([a-z]{4,})\s*?=|^\\+\\/v(8|9)|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.*\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`|'|\").*?(`|'|\")\s*)|UPDATE\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`|'|\").*?(`|'|\")\s*)SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE)@{0,2}(\\(.+\\)|\\s+?.+?\\s+?|(`|'|\").*?(`|'|\"))FROM(\\(.+\\)|\\s+?.+?|(`|'|\").*?(`|'|\"))|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)|<.*(iframe|frame|style|embed|object|frameset|meta|xml|a|img)|hacker";
        //post拦截规则
        $this->postfilter = "<.*=(&#\\d+?;?)+?>|<.*data=data:text\\/html.*>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*?\(.*\)|sleep\s*?\(.*\)|\\b(group_)?concat[\\s\\/\\*]*?\\([^\\)]+?\\)|\bcase[\s\/\*]*?when[\s\/\*]*?\([^\)]+?\)|load_file\s*?\\()|<[^>]*?\\b(onerror|onmousemove|onload|onclick|onmouseover)\\b|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.*\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`|'|\").*?(`|'|\")\s*)|UPDATE\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`|'|\").*?(`|'|\")\s*)SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE)(\\(.+\\)|\\s+?.+?\\s+?|(`|'|\").*?(`|'|\"))FROM(\\(.+\\)|\\s+?.+?|(`|'|\").*?(`|'|\"))|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)|<.*(iframe|frame|style|embed|object|frameset|meta|xml|a|img)|hacker";
        //cookie拦截规则
        $this->cookiefilter = "benchmark\s*?\(.*\)|sleep\s*?\(.*\)|load_file\s*?\\(|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.*\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`|'|\").*?(`|'|\")\s*)|UPDATE\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`|'|\").*?(`|'|\")\s*)SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE)@{0,2}(\\(.+\\)|\\s+?.+?\\s+?|(`|'|\").*?(`|'|\"))FROM(\\(.+\\)|\\s+?.+?|(`|'|\").*?(`|'|\"))|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
        $this->url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        $this->dir = __DIR__.'\\'.'waflog\\';
        $this->ip = [];
        $this->read_ip();

    }

    public function Flux($Value,$style){
                switch ($style) {
                    case 'post':
                        $this->Check_Flux($Value, $this->postfilter);
                        if(is_array($Value)){
                            $Value = http_build_query($Value);
                        }

                        $this->data_to_file("{\"".$this->url."\":"."\"".$Value."\"}","post.txt",'post');
                        break;
                    case 'get':
                        $this->Check_Flux($Value, $this->getfilter);
                        if(is_array($Value)){
                            $Value = implode($Value);
                        }
                        $this->data_to_file($this->url."\r\n","get.txt",'get');
                        break;
                    default:
                        $this->Check_Flux($Value, $this->cookiefilter);
                        if(is_array($Value)){
                            $Value = http_build_query($Value);
                        }

                        $this->data_to_file("{\"".$this->url."\":"."\"".$Value."\"}","cookie.txt",'cookie');
                        break;
                }            
            }
    public function read_ip(){
        $file = fopen($this->dir."ip.txt", "r") or exit("Unable to open file!");
        while(!feof($file))
        {
         array_push($this->ip, fgets($file));
        }
        fclose($file);
    }    

    public function Check_Flux($Value,$ArrFiltReq){
            if(is_array($Value)){
            $Value=implode($Value);
            }
            if (preg_match("/".$ArrFiltReq."/is",$Value)==1){
            die();
            }
        }

    public function Request_Post($data,$url){
        if(is_array($data)){
                $query = http_build_query($data); //使用给出的关联(或下标)数组生成一个经过 URL-encode 的请求字符串。
            }else{
                $query = $data;
            }
        $options['http'] = array(
         'timeout'=>60,
         'method' => 'POST',
         'header' => 'Content-type:application/x-www-form-urlencoded',
         'content' => $query
        );//构造一个post包

        $context = stream_context_create($options);//创建并返回一个资源流上下文
        $result = file_get_contents($url, false, $context);
        return $result; 
    }

    public function Request_Get($url){
        $result = file_get_contents($url);
         //var_dump($result);
        return $result; 
    }

    public function Get_Flag($result){
        if(stristr($result,'flag')){
           preg_match_all('/flag{(.*?)}/', $result,$flag);
            $this->data_to_file($flag[0][0]."\r\n","flag.txt",'flag');
        }
    }

    public function data_to_file($data,$filename,$style=''){
        if(is_array($data)){
            $data = implode($data);
        }
        switch ($style) {
            case 'post':
            //$jsonData = json_decode('['.file_get_contents(__DIR__.'\\'.$filename).']',true);
                if(!stristr(file_get_contents($this->dir.$filename),$data)){

                    if(file_exists($this->dir.$filename)){
                        file_put_contents($this->dir.$filename,",".$data,FILE_APPEND);    
                    }else{
                        file_put_contents($this->dir.$filename,$data,FILE_APPEND);
                    }
                    for($i=0;$i<count($this->ip);$i++){
                        $this->Get_Flag($this->Request_Post(json_decode($data,true)[$this->url],'http://'.$this->ip[$i].'/'));
                    }
                }
                //var_dump($jsonData);
                break;
            case 'get':
             $js_data = $data;
                if(!stristr(file_get_contents($this->dir.$filename),str_replace('http://'.$_SERVER['HTTP_HOST'], '', $data))){
                    file_put_contents($this->dir.$filename, $js_data ,FILE_APPEND);
                    for($i=0;$i<count($this->ip);$i++){
                    $this->Get_Flag($this->Request_Get(str_replace("\r\n","",str_replace($_SERVER['HTTP_HOST'], $this->ip[$i], $data))));
                    }
                }
                break;
            case 'cookie':
                if(!stristr(file_get_contents($this->dir.$filename),$data)){
                    if(file_exists($this->dir.$filename)){
                        file_put_contents($this->dir.$filename,",".$data,FILE_APPEND);    
                    }else{
                        file_put_contents($this->dir.$filename,$data,FILE_APPEND);
                    }
                }
                break;
            case 'flag':
                if(!stristr(file_get_contents($this->dir.$filename),$data)){
                    file_put_contents($this->dir.$filename,$data,FILE_APPEND);
                }
                break;
        }
    }
}


/*******************************/
/*         调用WAF            */

$waf = new  CTF_WAF();

if(isset($_GET)){
    $waf->Flux($_GET,'get');
}

if(isset($_POST)){
    $waf->Flux($_POST,'post');
}

foreach($_COOKIE as $key=>$value){
    $waf->Flux($value,'cookie');

}