利用Python进行Web渗透测试(七):用Python编写一个资源暴力探测工具(转载)
本篇将会涉及:
- 资源探测
- 一个有用的字典资源
- 第一个暴力探测器
资源探测
资源探测在渗透测试中还是属于资源的映射和信息的收集阶段。
主要有以下三个类型:
- 字典攻击
- 暴力破解
- 模糊测试
字典攻击,在破解密码或密钥的时候,通过自定义的字典文件,有针对性地尝试字典文件内所有的字典组合。
暴力破解,也叫做穷举法,按照特定的组合,进行枚举所有的组合。简单来说就是将密码进行逐个推算直到找出真正的密码为止。
模糊测试,指通过向目标系统提供非预期性的输入并监视其发生的异常结果来发现目标系统的漏洞。
资源探测的作用
通过资源探测,我们可以在目标系统中发现文件、目录、活动、服务还有相关的参数,为下一步的行动提供信息参考。
一个开源的模糊测试数据库
https://github.com/fuzzdb-project/fuzzdb是一个开源的漏洞注入和资源发现的原语字典。其提供了攻击、资源发现和响应分析的资源。
![](http://upload-images.jianshu.io/upload_images/38544-324c0c2963df70ec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
第一个暴力探测器
在之前的章节,我们了解了使用Python进行HTTP请求的方法,在本章,我们了解的资源探测的作用的用途。接下面我们就利用Python编写一个资源探测器,用来对Web网站进行资源探测。
我们将上面介绍的开源模糊测试数据库FUZZDB从github上克隆或下载下来:
![](http://upload-images.jianshu.io/upload_images/38544-c784b7f5e34afa1d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
这个数据库会作为我们的资源探测器的字典,来对web站点进行针对性的探测。
新建一个Python文件,开始我们的暴力探测器的编写。
首先,引入相关的模块:
# coding:utf-8
import requests
from threading import Thread
import sys
import getopt
- requests用于请求目标站点;
- threading用于启用多线程;
- sys用于解析命令行参数;
- getopt用于处理命令行参数;
然后,定义一个程序的横幅:
# 程序标识
def banner():
print("\n********************")
name = '''
______ _ _
|___ / (_) | |
/ / _ __ ___ _ ___| |_ ___ _ __
/ / | '_ ` _ \| / __| __/ _ \ '__|
/ /__| | | | | | \__ \ || __/ |
/_____|_| |_| |_|_|___/\__\___|_|
'''
print(name)
print("州的先生-暴力发掘器 v0.1")
print("***********************")
这个横幅用于在程序启动的时候显示出来,除了让程序个性一点之外,也没啥用。
再定义一个函数,用来显示程序的用法:
# 程序用法
def usage():
print("用法:")
print(" -w:网址 (http://wensite.com/FUZZ)")
print(" -t:线程数")
print(" -f:字典文件")
print("例子:bruteforcer.py -w http://bxu2713810459.my3w.com/FUZZ -t 5 -f commom.txt")
我们的程序因为是在命令行下运行的,所以需要设置一些参数,在这里,我们用:
- -w来指定网址
- -t 来指定线程数
- -f来指定字典文件
这三个参数缺一不可。
这两个函数创建好后,运行程序便会出现如下界面:
![](http://upload-images.jianshu.io/upload_images/38544-f2bbcc2d97ee06dc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
看上去是不是有那么点意思。
接着,我们创建一个继承于Thread的类request_performer(),用于创建线程并向目标站点发起请求以及获取响应:
class request_performer(Thread):
def __init__(self,word,url):
Thread.__init__(self)
try:
self.word = word.split("\n")[0]
self.urly = url.replace('FUZZ',self.word)
self.url = self.urly
except Exception as e:
print(e)
def run(self):
try:
r = requests.get(self.url)
print(self.url,"-",str(r.status_code))
i[0] = i[0] -1
except Exception as e:
print(e)
在request_performer()类的run()方法里面,我们利用requests对URL进行请求并将响应的状态码打印出来。而这,就是我们这个探测器的最主要功能了。
再创建一个启动request_performer()类的函数launcher_thread(),用于遍历字典文件中的关键字组合成URL并生成新的线程。
def launcher_thread(names,th,url):
global i
i = []
resultlist = []
i.append(0)
while len(names):
try:
if i[0] < th:
n = names.pop(0)
i[0] = i[0]+1
thread = request_performer(n,url)
thread.start()
except KeyboardInterrupt:
print("用户停止了程序运行。完成探测")
sys.exit()
return True
继续创建一个函数start(),用于接收命令行中的参数将其传递给launcher_thread()函数:
def start(argv):
banner()
if len(sys.argv) < 5:
usage()
sys.exit()
try:
opts,args = getopt.getopt(sys.argv[1:],"w:t:f:")
except getopt.GetoptError:
print("错误的参数")
sys.exit()
for opt,arg in opts:
if opt == '-w':
url = arg
elif opt == '-f':
dicts = arg
elif opt == '-t':
threads = int(arg)
try:
f = open(dicts,'r')
words = f.readlines()
except Exception as e:
print("打开文件错误:",dicts,"\n")
print(e)
sys.exit()
launcher_thread(words,threads,url)
最后,当然是在主程序中运行了:
if __name__ == '__main__':
try:
start(sys.argv[1:])
except KeyboardInterrupt:
print("用户停止了程序运行。完成探测")
咱们这个程序到底有什么用呢?
在这里,我们不得不再提一下上面提及过的FUZZDB数据库。fuzzdb是一个用于模糊测试的数据库,类似于一个庞大的字典。而这些字典的内容呢,都是安全大神们维护的、在实践中发现很有可能会是攻击点的目录或路径。
我们可以打开数据库中的一个txt文件看看:
![](http://upload-images.jianshu.io/upload_images/38544-e7219155fdbed6e6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
这是一个针对wordpress博客系统插件的一个字典,这里面都是插件的路径和目录。
测试暴力探测器
还记得在渗透测试环境搭建那篇文章介绍的虚拟机环境吗?
里面有一个充满漏洞的Web应用http://www.scruffybank.com/,我们可以使用我们刚刚编写好的暴力探测器对这个网站进行一下探测。
字典文件我们先采用一个简单的字典:
![](http://upload-images.jianshu.io/upload_images/38544-fd8697c6f14e00b0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
我们在命令行运行命令:
python3 brutediscovery.py -w http://www.scruffybank.com/FUZZ -t 5 -f common.txt
得到结果:
![](http://upload-images.jianshu.io/upload_images/38544-b38c11828ea5ae5e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
common.txt字典中有三个是成功的响应,我们打开其中一个http://www.scruffybank.com/robots.txt看看:
![](http://upload-images.jianshu.io/upload_images/38544-436cec91eeee7648.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
包含了三个禁止搜索引擎爬取的链接,看字面意思,其中一个还是后台地址admin,但是在结果页我们知道/admin是404错误,但是有一个/Admin,我们打开看看:
![](http://upload-images.jianshu.io/upload_images/38544-ea49e92c45e610f2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
弹出了认证登录框,但是我们没有用户名和密码,目前来说只能作罢。
我们再使用FUZZDB数据库里的字典测试一下。选择fuzzdb-master/discovery/predictable-filepaths/php目录下的PHP.fuzz.txt:
![](http://upload-images.jianshu.io/upload_images/38544-d4a75ac3a61f05a6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
同样在终端命令行运行命令:
python3 brutediscovery.py -w http://www.scruffybank.com/FUZZ -t 5 -f PHP.fuzz.txt
得到结果:
![](http://upload-images.jianshu.io/upload_images/38544-cfdef7c68141acaa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
虽然有很多404,但是我们还是发现了一些成功的响应:
比如info.php,打开原来是PHP的info界面:
![](http://upload-images.jianshu.io/upload_images/38544-276774889999ced8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
login.php为登录页面:
![](http://upload-images.jianshu.io/upload_images/38544-e8883433bfe71e5a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
phpmyadmin是mysql数据库的web管理入口:
![](http://upload-images.jianshu.io/upload_images/38544-cfb9f99505d5b5fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在数据探测收集阶段,我们通过我们自己编写的暴力探测器,获得了这些页面的信息,对分析服务器和web应用的漏洞并进行针对性的渗透有很大的帮助。
在接下来的文章里,我们将丰富和完善我们编写的渗透测试工具的功能。
敬请期待!
文章版权所有:州的先生博客,转载必须保留出处及原文链接
原文地址:https://zmister.com/archives/180.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# coding:utf-8 import requests from threading import Thread import sys import getopt # 程序标识 def banner(): print("\n********************") name = ''' ______ _ _ |___ / (_) | | / / _ __ ___ _ ___| |_ ___ _ __ / / | '_ ` _ \| / __| __/ _ \ '__| / /__| | | | | | \__ \ || __/ | /_____|_| |_| |_|_|___/\__\___|_| ''' print(name) print("州的先生-暴力发掘器 v0.1") print("***********************") # 程序用法 def usage(): print("用法:") print(" -w:网址 (http://wensite.com/FUZZ)") print(" -t:线程数") print(" -f:字典文件") print("例子:bruteforcer.py -w http://bxu2713810459.my3w.com/FUZZ -t 5 -f commom.txt") class request_performer(Thread): def __init__(self, word, url): Thread.__init__(self) try: self.word = word.split("\n")[0] self.urly = url.replace('FUZZ', self.word) self.url = self.urly except Exception as e: print(e) def run(self): try: r = requests.get(self.url) print(self.url, "-", str(r.status_code)) i[0] = i[0] - 1 except Exception as e: print(e) def launcher_thread(names, th, url): global i i = [] resultlist = [] i.append(0) while len(names): try: # if i[0] > th: n = names.pop(0) i[0] = i[0] + 1 thread = request_performer(n, url) thread.start() except KeyboardInterrupt: print("用户停止了程序运行。完成探测") sys.exit() return True def start(argv): banner() if len(sys.argv)>5: usage() #sys.exit() try: opts, args = getopt.getopt(sys.argv[1:], "w:t:f:") except getopt.GetoptError: print("错误的参数") sys.exit() for opt, arg in opts: if opt == '-w': url = arg elif opt == '-f': dicts = arg elif opt == '-t': threads = int(arg) try: f = open(dicts, 'r') words = f.readlines() print(words) except Exception as e: print("打开文件错误:", dicts, "\n") print(e) sys.exit() launcher_thread(words, threads, url) if __name__ == '__main__': try: start(sys.argv[1:]) except KeyboardInterrupt: print("用户停止了程序运行。完成探测")