/Webpass

Web弱密码爆破工具, 驱动浏览器进行弱密码爆破, 支持所有Web系统. 协程练手项目

Primary LanguagePythonGNU General Public License v3.0GPL-3.0

场景说明

账号密码是信息安全的第一道屏障, 在攻防中, 弱密码拥有与高危漏洞同样的重视程度, 除了传统协议(ftp, mysql, ssh等) 的弱密码检测外, http(s) 层面的关键系统越来越多, 例如VPN系统、 SDP系统等,如果能快速对http(s)业务系统的弱密码进行探测, 相当于多了一条渗透路径.

但是http(s) 层面有验证码密码加密等灵活的防御机制, 且经常配置错误次数限制,一个账号短时间错误次数太多, 直接禁止登陆. 这种情况下, 万能的burpsuite也显得有些无力.

Webpass工具通过驱动浏览器,模拟真实登录场景,形成通用的弱密码检测系统,可以支持http(s) 协议的web登录弱密码检测,也支持针对不同的网络设备定制不同的字典,从而更容易检测到弱密码;

有哪些解决的问题

密码加密传输


填写表单后, 页面代码对填写内容进行加密, 加密后发送到服务器后台, 如图看起来像base64实际上不是, 那么就因为不知道他怎么加密的, 从而无法直接发包爆破.
这种情况可以驱动浏览器来进行爆破, 让系统自己的代码进行加密转化, 最为简单直接通用.

async def create_browser_loop(sema  = None, ap = None):
    try:
        process = get_value('process', 8)
        glob.ocr = ddddocr.DdddOcr(old=True, show_ad=False)
        # 创建指定数量的浏览器页面
        browser = await ap.chromium.launch(headless=not get_value('debug', False), timeout=10 * 1000)

        context = await browser.new_context(ignore_https_errors=True)
        for _ in range(process):
            page = await context.new_page()
            await glob.pQu.put(page)
        logger.debug(f"浏览器已创建页面总数:{glob.pQu.qsize()}")

    except KeyboardInterrupt: kill_myself(1)
    except Exception:
        err_msg = get_err_msg()
        logger.error(err_msg)
        return err_msg

上述代码会打开指定数量的页面, 自动填写配置好的用户名密码, 效果图如下:

验证码和Token验证


验证码是很常见的, 当然单纯的验证码, 发包模式也可以解决. 但是有的时候, 页面会带有隐藏表单, 进行token提交, 服务器会对token进行验证.

对于token验证不符合的请求, 直接丢弃, 这个类似于密码加密传输, 不知道生成算法, 直接发包也扑街.

错误次数限制


这种情况也很常见, 当然发包的方式也可以解决这个问题, 本程序主要是密码优先, 枚举用户.

username_list = await aread_file(glob.cfg.pass_dict[key]['user_info'][1])
password_list = await aread_file(glob.cfg.pass_dict[key]['pass_info'][1])

user_pass = [[username_list[i], password_list[i]] for i in range(min(len(username_list), len(password_list)))]  # 先写一一对应的

for _pass in password_list:     # 再添加剩余的, 密码枚举用户
    for _user in username_list:
        if [_user, _pass] not in user_pass:
            user_pass.append([_user, _pass])

单个目标枚举3次之后, 测试下一个目标, 这个目标切换为等待状态:

另外, webpass最初想法是爆破一些常见的网络设备, 这样常见网络设备的默认密码自然是最高优先级, 比通用弱密码更优先, 上述代码也有体现. 在配置中, 可以配置每类产品独立的字典:

代码配置如上图, 字典文件如下图:

用户名密码表单名灵活多变


Web页面的用户名密码表单, 一般习惯是写username, password但是也有很多情况不是这两个名称, 那么在程序填写用户名密码时, 往往也需要配置或者智能识别, 目前考虑的方案是:

  1. 列举出所有的input, 类型为password的肯定是password
  2. 计算表单name与user关键字的相似度, 超过一定值考虑为username字段
  3. 计算表单name与pass关键字的相似度, 超过一定值考虑为password字段
  4. 补充一些用户配置字典.

对于未识别的系统, 可以使用通用字典来进行自动化爆破

多目标批量

单个web目标的爆破, burpsuite很灵活有效, 但是多个目标, 就比较麻烦了. 新出的国产挑战者Yakit可以支持, 但是在请求次数过多也会程序卡死


实测最新版本8k个请求也会让UI卡死, 可能需要继续等待官方修复.
自己来写程序实现驱动浏览器进行弱密码爆破, 就能解决这个问题:

可以在文件中一行一个目标, 自动识别系统, 调用指定的字典, 未识别的使用通用字典

使用方法

INFO: Showing help with the command 'webpass_call.py -- --help'.

NAME
    webpass_call.py - -u: url -f: file -g: 配置模式 -w: 单目标等待时间, 分钟 -j: 只探测识别到的目标

SYNOPSIS
    webpass_call.py <flags>

DESCRIPTION
    -u: url -f: file -g: 配置模式 -w: 单目标等待时间, 分钟 -j: 只探测识别到的目标

FLAGS
    --u=U
        Default: ''
    --f=F
        Default: ''
    --debug=DEBUG
        Default: False
    --gen=GEN
        Default: False
    --wait=WAIT
        Default: 3
    --process=PROCESS
        Default: 8
    --just_discern=JUST_DISCERN
        Default: True
python webpass_call.py -u http://1.2.3.4 
python webpass_call.py -f /etc/target.txt python webpass_call.py -u http://1.2.3.4 -f /etc/target.txt
python webpass_call.py -g http://baidu.com

基本用法

-u : 探测单个或者多个目标弱密码, 含有url的字符串即可, 会自动解析url
-f : 探测文件中所有的url, 带有url的文件即可, 会自动解析url
上述两个开关可以都配置, 目标相加
注意: url需要带入协议类型如http, https等, 如果不带, 可能导致url无法识别.

配置模式

当然, 在实际使用中, 默认密码的情况比较多见, 所以尽量还是经过配置后使用, 而不是直接通用字典.
-g : 配置模式, 默认以webkit浏览器打开

比较方便于生成配置.

其他开关

-w : 配置单目标等待时长, 默认单目标尝试3次后等待3分钟
-p : 浏览器最大页面数, 即理解成多少个线程, 实际上是协程的程序
-j : 配置True则只爆破已识别的目标, 不进行通用爆破, 是just_discern的首字母
-d : 调试开关, 配置为True, 多很多步骤打印, 浏览器也会显示出来

配置文件说明


配置文件基本结构如上图, 是一个大字典, 每类产品一个小字典, 字典内部是key:list结构.

  • keywords:列表类型,识别产品的关键词,各个关键词之间与关系,即登录页html中某些关键词,支持base64编码;留空则直接用“key”作为关键词判断,如果没有找到则归为未识别
  • user_info:是包含username 字段名和字典目录的列表,pass_info类似
  • button:按钮名称,列表类型,一般用webpass_call.py -g url 获取按钮名称
  • CAPTCHA: 长度一般为2,位置0位填充,位置1为截图,如果长度为0,则代表没有验证码
  • suc:登录成功后html中内容关键字,支持base64,根据logic计算整体真假
  • fail:登录失败后html中内容关键字,支持base64,根据logic计算整体真假

考虑到配置的便捷性,可以使用-g参数激活浏览器自动获取关键字段,便于填写, 如果suc, fail都为空, 则直接根据登陆前后页面相似度进行正确性判断

安装

STEP1. 官方网站下载Python3.7+环境。

STEP2. 安装调用库PlayWright,Fire,loguru 等

  • pip install playwright ddddocr fire loguru chardet aiofiles
  • python -m playwright install

可能有一些未列举的, 后续提供requirements.txt
装完库就可以运行.

代码结构

代码主要使用Python3, 尽量使用Python3.9及以上的版本

文件结构

  • 0-errlog.txt # 报错信息
  • 1-unknown_devices.txt # 未知设备
  • 2-success.txt # 成功的目标
  • 3-fail.txt # 失败的目标
  • 4-check.txt # 需要检查的目标
  • webpass_call.py # 主程序
  • webpass_config.py # 主配置
  • webpass_func.py # 功能库
  • webpass_report.py # 上报ES, 未完成

整体结构

target_dict数据结构

{
    'target_dict':{
        'http://1.2.2.2':{
            'status':'init',
            'title':'',
            'content':'',
            'key':'下一代防火墙',
            'last_time':datetime 对象,
            'user_pass':aQueue,
        }
    }
}

status状态

  • init
  • identify, unknown, timeout
  • tasking, wait
  • done, success

后续计划

计划

  • go开发实现, 便于编译成exe在目标内网执行
  • 支持通用爆破
  • 减少配置量, 例如通过已有指纹库识别资产, 结合通用爆破调用指定字典

已实现

  • 文档上述内容, 除了计划之外, 均已实现