1.前言
在公众号的前几篇文章中,笔者分享了绕过图片验证码校验、密码错误次数校验等校验机制的文章。在评论区有师傅问了一个和密码爆破、喷洒有关的问题
看到这个问题,其实我心里是感慨万千的。因为在我刚入坑网安的时候,一度非常看不起弱口令这种攻击手法,真男人就应该硬挖洞,用弱口令也太没技术含量了。后面经验慢慢丰富一点了,案例看得多了,才发现弱口令无论在哪个时期都是yyds。这时候我也是尝试去找各种用户名和密码的字典,github上有很多相关的项目,用户名和密码字典也是眼花缭乱的多,这种时候我选择困难症就上来了,这么多字典,大家都说自己是最好用的,我该怎么选择呢?而且这些字典一般都会分大小,比如500条 1k条 1w条甚至更多,我在爆破与喷洒的时候,用多大的字典,什么样的流程会比较合适呢?
本文主要就是分享笔者是如何解决这些问题的,实际上,当我们拼凑出一个好用的用户名和密码字典,并且有一套好用的爆破与喷洒流程,你会发现弱口令远比想象中多得多得多,笔者无论是在护网还是在各家企业SRC的挖掘中,都挖到过特别多弱口令问题。
本文会先介绍如何构造好用的用户名和密码字典,再介绍平时常用的一些流程。下面进入正题。
2.如何构造一个好用的用户名字典
这里我们其实可以回顾一下读者师傅反馈的情况。这位师傅使用几千量级的用户名字典和几千量级的密码字典去交叉爆破,这实际上是用“短板”组合“短板”,因为显然的,几千量级的用户名并不能保证尽量覆盖所有常见的用户名,也不能保证覆盖常见密码。最后就导致这样成功率不算太高的同时,效率还不高。这位师傅后面也发现了,应该要确保用户名尽量多,密码要尽量精。
事实上,在我遇见的各种案例中,喷洒确实非常重要,这个我们后续再细说。还是回到正题。我们主要要打造一个好用的用户名字典,但是量级也不能太夸张,不然会拖累效率。我们首先基于前人的各种字典项目,打造一个字典的“基础”。这里我举一些例子,包括但不限于如下:
https://github.com/danielmiessler/SecLists
https://github.com/TheKingOfDuck/fuzzDicts
https://github.com/insightglacier/Dictionary-Of-Pentesting
https://github.com/a3vilc0de/PentesterSpecialDict
https://github.com/CrackerCat/SuperWordlist
https://github.com/cpkkcb/fuzzDicts
https://github.com/huyuanzhi2/password_brute_dictionary
实际上还有挺多的,微信公众号或者其它搜索引擎搜索“渗透 字典”这样的关键词,还能找到很多。这里不一一列举了。我们下载回来之后,找到用户名相关的字典。一般能看到多种长度的,从几百条的小型字典,到十几万条的超大型字典。
我们接下来要做的事就是把所有比较小的字典做一个合并去重。比如几百条,几千条,小几万条的那种用户名字典,我们给它统统做一个合并去重。注意千万不要选择那种大几万条甚至十几万条的大字典也进行合并去重,否则我们最后的字典会究极臃肿。
这样做完合并之后,我们就打造好了一个字典的“基础”,这时候已经可以用了,但是我们下面要做一些针对性补充,添加一些数据,让它变得更好用。
第一个补充措施是,我们要往里添加两位英文字符排列组合(aa-zz)+三位英文字符排列组合(aaa-zzz)相关的字符串
这样排列组合的字符串很好生成,可以让GPT帮你写一个脚本去生成,最后生成出来的数量级大概接近2w条。
这么做的目的是什么呢?这个主要是符合国内用户的一个经典习惯。比如我的名字叫张伟,那我的用户名很可能就写成zw,我叫张谋仁,可能用户名就写成zmr。可以看到,最常见的二字或三字姓名,在这种规则下就会被缩写成两位英文字母的组合或三位英文字母的组合。因此我们只要排列组合出所有的可能性,就能完全覆盖这种规则下的用户名。
第二个补充措施是,我们可以尽可能多收集国内常见的姓名的拼音形式,比如上面提到的张伟,用户名可能就是zhangwei,很好理解。这个各种字典项目里应该也有,也很容易找到
还可以搜集常见的中文人名,然后用python的pypinyin之类的库把中文人名转化为拼音,问GPT就完事
除了根据现有的这些项目去搜集,还可以根据公安部的一些姓名调查报告去进一步完善:
将常见姓和名转化成拼音,进行排列组合。这样补充数据是为了覆盖用户名是拼音的情况,当然汉字博大精深,我们这样收集到的也只是比较小的一部分,够用就行。
这种情况还有一个变种,那就是我们可以搜集五百个或者一千个左右的常见中文名(更多点也无所谓,能找到就行),注意是中文名不是拼音,然后对其进行url编码
这是为了对抗使用中文名作为用户名的情况。我发现一些比较老的系统真就挺喜欢用中文名作为用户名的。
第三个补充措施和英文用户名、英文单词有关,我们可以搜集一些常见的英文单词(尤其是名词)添加到字典里,上面的各种字典项目里应该也有一些常见英文用户名,添加进我们的字典里即可。
第四个补充措施和测试手机号有关,
https://github.com/TheKingOfDuck/fuzzDicts
这个项目里有一个test-phone字典,里面都是一些常见测试手机号,比如13888888888等等,很多系统的用户需要填手机号,并且可以把手机号作为用户名去登录,你会发现很多管理员和测试用户的手机号一般都是13888888888这种
第五个补充措施是一些用户id和简单的编号,这个不需要太多,比如001、0001、111111这类
主要是1和0的位置去排列组合。这个是应付一些数字编号(比如工号)、用户id作为用户名的场景。
第六个补充措施是对一些常见用户名进行拓展,什么意思呢,比方说admin、test用户,实际上常见的不只是admin、test,还有
admin1、test1
admin01、test01
admin001、test001
对上面的字典进行排列组合即可。
这个可以从top500之类的字典作为基础,往每一行字符后面拼接1 01 001 123之类的数字,很ez的。
第七个补充措施是加一些payload,比如最经典的注入payload:
admin'--
admin' or ''=''--
admin' or 1=1--
'or 1=1--
不过,这种payload就算要加,也是集中加到字典的最后,因为有waf的情况下跑这些payload毫无疑问是要被拦截的,有风险的东西还是放到最后来跑。
这里还有一些奇思妙想,上述字典的规则主要是针对我国,然而每个国家的人肯定都有自己独有的一些用户名命名习惯,比如我国就很常见用自己姓名拼音作为用户名,那其他国家呢?或许可以想办法联系其他国家的网安从业者,从他们手里要一些符合他们国家特色的用户名字典?
再者,历史上泄露的用户名密码等数据不在少数,或许有大数据大手子可以尝试搜集这些数据,然后统计一下高频用户名和密码?
总之,通过上述步骤,我实测可以做出一个比较强大的字典,去重后最终应该会在4w-6w条用户名,效率比较高的同时也能覆盖大量用户名,就很平衡。
3.如何构造一个好用的密码字典
首先还是按照上述步骤,从各个字典项目里找小型一点的密码字典,合并去重作为基础。然后我们还得补充一些东西。
第一个要补充的东西就很有点复杂,简单来说是键盘顺序排列组合的一些密码。比如
QWER1234
QAZWSX123
也可能是九宫格位置相关的一些密码,比如笔者就见过
456852
159753
乍一看这种不像是常规弱口令。但实际上还真是,456852是数字九宫格中间的十字,159753则是九宫格斜线交叉。
这种就有点抽象而且很考验想象力了,QWER1234这种一般的字典里应该有,但是再复杂一点的键盘顺序就不一定有了。只能想办法调教GPT生成了。
第二个要补充的东西也是一种常见的密码规律。大概是关键用户名+数字(年份),或者关键用户名+特殊字符+数字(年份)。典型例子有
Admin@123
admin@2024
Admin!@#123
Test123
Test!@2024
等等。这个用一些字典生成器倒是很好生成出来
这样生成的字典可就不好说多大了,得自己控制一下,我最后整出来大概是6w多条密码。
以上我们就讲完了怎么去构造比较好用的用户名或密码字典。不过关于字典还有一些可以说的,我们放到后续的爆破以及喷洒流程来介绍。
4.常规喷洒-爆破流程
进入喷洒与爆破的正题了。我个人是喜欢先喷洒,再爆破。喷洒很好理解,我们固定密码为123456、111111或者admin(一般123456就够了),然后导入用户名字典,比方说对所有用户喷洒123456这个密码,如果目标安全做的拉跨,一般这一步就能爆出目标的部分用户凭据了。即使不行,我们一般也可以通过状态码、返回包长度确定哪些用户存在。
比如最常见的通过长度和返回内容进行判断,这里我们假设第一轮用123456去进行喷洒:
总之,大部分情况下密码正确、密码错误但用户名正确、密码和用户名都错误,三种情况会分别对应不同的返回长度或者不同的响应内容(有时候也会对应不同的响应码),多注意即可。
这里值得重点说明的一种情况就是,假设返回长度、状态码都一样或者很类似,但是响应内容不同,我们喷洒了几万个用户名,总不能一个个点开去看结果吧?这种情况我们要怎么去筛选存活用户呢?例如下面这样:
这种情况可以借助Grep -Extract功能,我们注意到代表用户是否存在的响应内容是放在<h1>标签内的,可以借助这个功能做匹配
然后我们的结果会多出一列,这一列就是根据我们自定义的规则在响应信息里匹配的结果:
虽然中文结果会乱码,但是点一下排序,就可以把不同结果的排到上面来,我们就可以快速确认哪些用户存在了
当然这里是只有一个登录接口做演示,实战环境里不只能用登录接口去判断用户的存在情况,还有一些比较常见的例如注册用户接口、修改密码接口,判断用户存在基本一找一个准。很多时候登录接口做了处理,返回“用户名或密码错误”,且无法通过返回长度、响应码进行判断的时候,可以另寻别的接口尝试对用户的存在情况进行判断。本文就不演示了。
总之一般来说,固定密码为123456进行喷洒,大概率能直接找到一些弱口令用户。就算找不到,也有可能找到存活用户,比如上面找到了admin、root、test三个用户,后续对找到的存活用户进行密码爆破即可。
5.不知道存活用户的喷洒-爆破流程
经典情况,无论是用户名不存在,还是用户名存在但密码错误,统一返回“用户名或密码错误”
这种情况又要怎么办呢?如果没有其他接口配合,我们是很难确定存活用户了,我们也不可能用5w的用户名和6w的密码字典去交叉爆破,量级达到30亿了都。这种情况下,我们首先可以挑一些常见的高价值用户名进行爆破测试,例如admin、root、test等等,这种没什么好说的。
在这种情况下,也可以多试几种常见的弱口令进行喷洒,不止123456,比如还可以试试上面提到的111111、admin、888888等等。
关于这种情况,还有一种我觉得很重要的流程需要补充,可以让喷洒出货概率提高很多。简单来说,我们上面的喷洒大概是这样:
用户名 密码
admin 123456
root 123456
test 123456
zhangwei 123456
我们想办法构造:
用户名 密码
admin admin123
root root123
test test123
zhangwei zhangwei123
也即,我们的密码字典其实就是用户名字典后面补一个123,我们没必要专门做一个这样的密码字典,用burp实现上述效果即可
Burp使用pitchfork模式,标记两个地方,在password参数后面加一个123
然后设置payload的时候,两个位置都选择我们的用户名字典即可
效果大概是下面这样:
之所以有这一步,是我发现实战中有些站点生成用户后,喜欢把用户的密码设置成用户名拼音+123,有时候还会设置成密码就是用户名,还有很多用户在设置自己密码的时候就是很喜欢用户名拼音+123的规则,所以我在实战中多加这么一步真的出过不少洞。而且也不只是拼接123,还可以试试下面这些密码规律结合用户名字典去做喷洒:
用户名+@123
用户名+@年份
用户名首字母大写+@123
可以让喷洒成功率提高很多。
6.特殊情况之手机号作为用户名
也是非常常见的一种情况,就是一些登录口可能只让我们用手机号+密码去登录。这种情况其实用前文提到的测试手机号字典去喷洒爆破就行,一般都能找出一些测试手机号(测试用户)。如果你不满足于此,也可以通过爱企查或者其他类似的网站去找目标相关的手机号,例如:
目标各种网站如果有“联系我们”之类的界面,也可以找到一些手机号
可以搜集这些手机号进一步喷洒爆破。
7.特殊情况之邮箱作为用户名
这种情况就更有意思了。这种情况我喜欢先确定目标公司的企业邮箱是什么,一般都和他们的主域名有关。比如某知名视频网站bixxbixx.com,企业邮箱大概率是@bixxbixx.com,这些爱企查都很好查的。我们在针对使用邮箱作为用户名的情况时,实际上可以在我们用户名字典的基础上直接拼接一下目标的企业邮箱后缀,比如:
这样基本也能去找到很多邮箱用户名,因为大部分企业邮箱的规律也就是 员工姓名拼音+邮箱后缀。
如果你并不满足于此,实际上还有一些网站可以找目标相关的邮箱,例如
https://phonebook.cz
www.skymem.info
https://hunter.io/
等等
同理啊,目标的“联系我们”相关界面也是有可能有邮箱相关信息的
或许可以整一些爬虫,从目标的各个资产批量提取这些信息?
8.特殊情况之密码强度限制
这种情况也很好懂,比如“至少一个字母 一个数字 一个特殊符号的六位数密码”。遇到这种我们也有专门的字典。
但是这里需要注意一个细节,就是这个密码长度限制到底是在前端还是在后端。为什么要在意这个呢?如果这个限制存在前端,那么未必所有的用户都真的遵循这个规则,早期的一些测试用户可能用的还是弱口令,因为这些用户的密码可能是直接导入到数据库里的,或者管理员在后台生成配置的,和你前端的注册、登录之类的功能就没啥关系。所以如果这个限制仅存在于前端,抓包请求发现没有相关限制,那我们还是可以用我们自己的密码字典去找找机会。不过如果这个限制是在后端登录接口写死的,就是你登录的时候后端接口返回信息,告诉你密码不符合规则,那只能老老实实用上面满足条件的字典了。
9.针对目标专门设计密码字典去进行爆破
这个主要是针对密码爆破的,建议把上面的常规流程走完,再来搞这个。简单来说,当我们上面的流程没什么收获,但是我们又要对高价值用户进行密码爆破(如admin、root等用户)的时候,可以考虑这个流程。
可以通过目标公司名或域名关键词、年份、数字、特殊字符去生成目标专属的密码字典,还是以某视频网站Bixxbixx为例:
也属于是碰运气的操作,如果目标并不是那么重要,实际上也不一定要走这一步。
10.总结
综上笔者就简单分享了个人的一些见解,包括如何构造一个用得顺手的用户名和密码字典,以及如何去进行爆破与喷洒流程。总的来说,我们还是以喷洒起手,既有概率一把梭,也可以帮我们拿到很多信息,喷洒没结果再对找到的存活用户进行单点密码爆破。这样就可以很大程度上避免短板效应,把我们用户名字典和密码字典都利用到极致,同时结合之前提到过的对抗验证码、错误次数的姿势,以及JS信息搜集的一些姿势,应该就可以构造起一个比较完善的密码喷洒与爆破体系了。当然应该还有一些笔者没想到的好用的流程和姿势,也欢迎读者朋友补充。
11.粉丝福利
关注"HW专项行动小组"公众号,后台回复"字典666"领取独家字典