
ServiceNow इंस्टेंस से लीक होने वाले संवेदनशील डेटा का पता लगाएं।
snowpick एक ServiceNow एक्सपोज़र स्कैनर है जो गलत कॉन्फ़िगर किए गए widget ACLs, REST API एक्सेस नियंत्रण और बिना प्रमाणीकरण के डेटा एक्सपोज़र का पता लगाता है।
ServiceNow दो सामान्य सार्वजनिक सतहों के माध्यम से डेटा उजागर करता है: Service Portal widgets और Table REST API। जब किसी भी सतह पर एक्सेस नियंत्रण गलत कॉन्फ़िगर किए जाते हैं, तो बिना प्रमाणीकरण वाले उपयोगकर्ता incident टिकट, उपयोगकर्ता निर्देशिकाएँ, knowledge base लेख और service catalog आइटम जैसे आंतरिक रिकॉर्ड क्वेरी कर सकते हैं। snowpick दोनों सतहों का परीक्षण करता है, row एक्सपोज़र को केवल-गिनती (count-only) साक्ष्य से अलग करता है, और अधिकृत सत्यापन के लिए प्रतिकृति (reproduction) विवरण तैयार करता है।
snowpick बिना किसी क्रेडेंशियल के ServiceNow लॉगिन पृष्ठ से एक सत्र टोकन प्राप्त करता है, फिर उसका उपयोग प्लेटफ़ॉर्म के आंतरिक APIs को क्वेरी करने के लिए करता है। यह दो हमले की सतहों की जाँच करता है:
Widgets छोटे एप्लिकेशन हैं जो ServiceNow Service Portal को संचालित करते हैं। प्रत्येक की अपनी एक्सेस नियंत्रण सेटिंग्स होती हैं। जब वे सेटिंग्स अत्यधिक अनुमतिपूर्ण होती हैं, तो बिना प्रमाणीकरण वाला सत्र widget से डेटा प्राप्त कर सकता है। snowpick पहले instance से संभव होने पर स्थापित widgets की सूची माँगता है, फिर प्रत्येक की जाँच करता है और देखता है कि यह रिकॉर्ड लौटाता है या केवल-गिनती साक्ष्य।
Table API ServiceNow तालिकाओं को सीधे क्वेरी करने के लिए /api/now/table/ पर एक REST इंटरफ़ेस है। इसके widgets से अलग एक्सेस नियंत्रण होते हैं, इसलिए एक लक्ष्य एक सतह पर बंद (locked down) और दूसरी पर खुला हो सकता है। snowpick sys_user, incident, और oauth_entity जैसी उच्च-मूल्य वाली तालिकाओं की जाँच करता है।
Count oracle. कभी-कभी कोई widget या तालिका पुष्टि करता है कि मेल खाते रिकॉर्ड मौजूद हैं, बिना rows लौटाए। snowpick इसे count_oracle के रूप में चिह्नित करता है — न तो पूर्ण एक्सपोज़र, न ही पूरी तरह साफ, क्योंकि फ़िल्टर के साथ गिनती की जाँच करके डेटा का आँख मूँदकर अनुमान लगाया जा सकता है।
❯ go install github.com/BishopFox/snowpick@latest
या स्रोत से बनाएँ:
❯ git clone https://github.com/BishopFox/snowpick.git
❯ cd snowpick
❯ go build -o snowpick .
इसके लिए Go 1.21 या उससे नए संस्करण की आवश्यकता है।
snowpick को किसी ServiceNow instance पर लक्षित करें। किसी क्रेडेंशियल की आवश्यकता नहीं है।
❯ snowpick -target prod.service-now.com
snowpick v1.0.0 | 1 targets | 6 widgets | proxy direct
[!] prod.service-now.com
| ticket-attachments 272 records [internal_operations:inferred]
[*] 1/1 targets complete, 1 with findings
RESULTS
1 targets scanned in 8.2s | 1 reachable | 1 with findings
EXPOSED prod.service-now.com 272 records [internal_operations:inferred]
| ticket-attachments 272 records [internal_operations:inferred]
| ServiceNow Overview and Open House 'How To.... Videos'
| How to - JIRA and Confluence Access Process
| Updating Your Personal Time Zone in ServiceNow
ATTACK SURFACE
ticket-attachments #################### 272 across 1 target
DATA CLASSIFICATION
OPERATIONS 1 finding across 1 target
snowpick स्वचालित रूप से instance पर स्थापित widgets का पता लगाता है और अपने अंतर्निहित डिफ़ॉल्ट के साथ-साथ प्रत्येक की जाँच करता है। निष्कर्ष (findings) गंभीरता के आधार पर क्रमबद्ध होते हैं।
Progress markers (left of each host):
[!] findings [+] clean [-] unreachable or no session [*] progress
Summary buckets:
EXPOSED data or a confirmed count came back CLEAN nothing reachable
SKIP no public session (e.g. SSO-only login) DOWN host unreachable
Counts:
272 records total the instance reports as matching
272 records, 10 sampled total, plus the rows snowpick pulled as evidence
Tags:
[pii:observed] a hint, written as category:basis
basis observed = value seen in returned data
inferred = from a table/field/widget name
category pii, credentials, infrastructure,
internal_operations, review_required
[blind oracle] count confirmed but no rows returned (a count_oracle)
[API] finding came from the Table REST API, not a widget
[stats.do] the /stats.do diagnostic endpoint is publicly reachable
एक फ़ाइल दें जिसमें प्रति पंक्ति एक hostname हो। snowpick उन्हें समानांतर में स्कैन करता है।
❯ snowpick -targets hosts.txt -concurrency 5
snowpick v1.0.0 | 6 targets | 6 widgets | proxy direct
[!] prod.service-now.com
| ticket-attachments 272 records [internal_operations:inferred]
[*] 1/6 targets complete, 1 with findings
[+] staging.service-now.com clean
[*] 2/6 targets complete, 1 with findings
[!] dev.service-now.com [stats.do]
| ticket-attachments 61 records [internal_operations:inferred]
[*] 3/6 targets complete, 2 with findings
[+] sandbox.service-now.com clean
[*] 4/6 targets complete, 2 with findings
[-] internal.service-now.com bootstrap failed: /login.do returned 302
[+] test.service-now.com clean
[*] 6/6 targets complete, 2 with findings
ServiceNow बैकएंड तालिकाओं को सीधे क्वेरी करने के लिए /api/now/table/ पर एक Table REST API भी उजागर करता है। यह widgets से एक अलग एक्सेस नियंत्रण सतह है। दोनों की जाँच करने के लिए -table-api का उपयोग करें।
❯ snowpick -target prod.service-now.com -table-api
snowpick v1.0.0 | 1 targets | 6 widgets | proxy direct
[!] prod.service-now.com
| [API] cmn_department 1,234 records, 10 sampled [infrastructure:inferred]
[*] 1/1 targets complete, 1 with findings
Table API निष्कर्षों के लिए, record_count उजागर किए गए कुल रिकॉर्ड को दर्शाता है जब ServiceNow एक कुल गिनती लौटाता है। sample_count दिखाता है कि snowpick ने सीमित साक्ष्य के रूप में कितने रिकॉर्ड एकत्र किए।
डिफ़ॉल्ट रूप से, snowpick उच्च-मूल्य वाली तालिकाओं (incident टिकट, उपयोगकर्ता रिकॉर्ड, attachments, आदि) के एक चयनित समूह की जाँच करता है। -discover के साथ, यह instance से तालिका नामों की गणना (enumerate) करने का प्रयास करता है और उनकी भी जाँच करता है।
❯ snowpick -target prod.service-now.com -discover -discover-limit 200
लक्ष्य किस ServiceNow रिलीज़ पर चल रहा है, यह पहचानने के लिए -fingerprint का उपयोग करें। इससे यह निर्धारित करने में मदद मिलती है कि कौन से सुरक्षा पैच लागू हैं।
❯ snowpick -target prod.service-now.com -fingerprint
snowpick v1.0.0 | 1 targets | 6 widgets | proxy direct
[!] prod.service-now.com [Zurich (glide-zurich-07-01-2025__patch7-02-19-2026)] [stats.do]
| ticket-attachments 61 records [internal_operations:inferred]
[*] 1/1 targets complete, 1 with findings
ट्रैफ़िक को Burp, ZAP, या SOCKS प्रॉक्सी के माध्यम से भेजें। प्रोडक्शन instances पर अनुरोधों को धीमा (throttle) करने के लिए -rate का उपयोग करें।
❯ snowpick -target prod.service-now.com -proxy socks5://127.0.0.1:1080 -insecure -rate 200ms
-quiet के साथ प्रगति आउटपुट को दबाएँ। JSON डिफ़ॉल्ट रूप से stdout पर जाता है, या -output के साथ किसी फ़ाइल पर। एक्ज़िट कोड 2 का अर्थ है निष्कर्ष मौजूद हैं, 1 का अर्थ है एक या अधिक लक्ष्यों का परीक्षण नहीं किया जा सका, और 0 का अर्थ है स्कैन बिना किसी निष्कर्ष के पूरा हुआ।
❯ snowpick -target prod.service-now.com -quiet -output results.json
❯ echo $?
2
JSON आउटपुट में निष्कर्षों का विवरण होता है, जिसमें प्रभाव संकेत (impact hints), अनुरोध विवरण, rows लौटने पर सीमित नमूना रिकॉर्ड और जहाँ लागू हो प्रतिकृति (reproduction) सामग्री शामिल है।
{
"target": "acme.service-now.com",
"reachable": true,
"token_obtained": true,
"stats_do": false,
"widgets": [
{
"id": "ff26f2b1db12220099f93691f0b8f5ce",
"name": "ticket-attachments",
"status": "exposed",
"record_count": 847,
"sample_count": 10,
"hints": [
{
"category": "pii",
"basis": "observed",
"reason": "email pattern in sample content",
"signals": ["content:[email protected]"]
},
{
"category": "internal_operations",
"basis": "inferred",
"reason": "widget name associated with internal operations",
"signals": ["widget:ticket-attachments"]
}
],
"reproduction": {
"method": "POST",
"url": "https://acme.service-now.com/api/now/sp/widget/ff26f2b1db12220099f93691f0b8f5ce",
"headers": {"X-UserToken": "...", "Cookie": "JSESSIONID=..."},
"body": "{\"payload\":{\"start\":0,\"end\":1}}",
"status_code": 200,
"curl": "curl -i -sS -X 'POST' ..."
}
}
]
}
तालिका गणना निष्कर्ष table_findings के अंतर्गत दिखाई देते हैं, और Table REST API निष्कर्ष table_api_findings के अंतर्गत। वे समान hints संरचना का उपयोग करते हैं। Table API निष्कर्षों में कुल गिनती उपलब्ध होने पर record_count और sample_count दोनों शामिल होते हैं।
सभी लक्ष्यों को निष्कर्षों सहित सूचीबद्ध करें:
❯ jq -r '.findings[] | select(any(.widgets[]?; .status == "exposed" or .status == "count_oracle") or ((.table_findings // []) | length > 0) or ((.table_api_findings // []) | length > 0)) | .target' results.json
prod.service-now.com
dev.service-now.com
एक्सपोज़्ड निष्कर्षों के लिए प्रतिकृति curl कमांड प्राप्त करें (पुनरुत्पादन के लिए कॉपी-पेस्ट करें):
❯ jq -r '.findings[] | (.widgets[]?, .table_findings[]?, .table_api_findings[]?) | select(.status == "exposed") | .reproduction.curl' results.json
curl -i -sS -X 'POST' 'https://acme.service-now.com/api/now/sp/widget/ff26f...' -H 'X-UserToken: MOCK_TOKEN' ...
target, vector, status, count, samples और hint आधार के साथ PII निष्कर्ष दिखाएँ:
❯ jq -r '.findings[] as $f | ($f.widgets[]?, $f.table_findings[]?, $f.table_api_findings[]?) | select(any(.hints[]?; .category=="pii")) | [$f.target, (.name // (.table + (if .field then "." + .field else "" end))), .status, ((.record_count // .count // 0)|tostring), ((.sample_count // 0)|tostring), ([.hints[]? | select(.category=="pii") | .basis] | unique | join(","))] | @tsv' results.json
acme.service-now.com ticket-attachments exposed 847 10 observed
acme.service-now.com sys_user exposed 250 10 inferred
किसी निष्कर्ष के लिए नमूना शीर्षक प्राप्त करें:
❯ jq -r '.findings[] | select(.target == "acme.service-now.com") | .widgets[] | select(.name == "ticket-attachments") | .samples[]?.title' results.json
Synthetic ticket attachment title
Example onboarding guide
उजागर किए गए कुल रिकॉर्ड की गणना करें:
❯ jq '[.findings[] | (.widgets[]? | select(.status == "exposed") | .record_count), (.table_findings[]? | select(.status == "exposed") | .count), (.table_api_findings[]? | select(.status == "exposed") | .record_count)] | add // 0' results.json
12896
TARGETS
-target string Single ServiceNow hostname
-targets string File with one hostname per line
OUTPUT
-output string JSON output file (default: stdout)
-quiet Suppress informational output
-version Print version and exit
CONNECTION
-proxy string Proxy URL (http, https, socks5, socks5h)
-timeout duration HTTP timeout per request (default: 15s)
-insecure Skip TLS certificate verification
-rate duration Minimum interval between requests (default: unlimited)
-vendor string X-Vendor header for engagement tracking
SCANNING
-concurrency int Max parallel targets (default: 3)
-table-concurrency int Max parallel table probes per target (default: 5)
-samples int Sample records per exposed finding (default: 10)
WIDGET PROBING
-widgets string Comma-separated widget IDs (overrides defaults)
-widgets-file string JSON file with additional widget candidates
TABLE ENUMERATION
-tables Enumerate via widget-simple-list (default: true)
-tables-file string JSON file with additional table/field candidates
-table-api Probe /api/now/table/ REST API
DISCOVERY
-discover Discover tables dynamically from the instance
-discover-limit int Max tables from discovery (default: 100)
-discover-widgets-limit int
Max widgets from discovery (default: 50)
-fingerprint Detect ServiceNow version and release
snowpick 6 डिफ़ॉल्ट widgets और 26 डिफ़ॉल्ट table/field जोड़ों के साथ आता है। आप JSON फ़ाइलों के माध्यम से कोड में बदलाव किए बिना और जोड़ सकते हैं:
Widget उम्मीदवार (-widgets-file):
[{"id": "WIDGET_ID", "name": "custom-widget"}]
तालिका उम्मीदवार (-tables-file):
[{"table": "TABLE_NAME", "field": "FIELD_NAME"}]
ये अंतर्निहित डिफ़ॉल्ट के साथ विलय हो जाते हैं। डुप्लिकेट स्वचालित रूप से हटा दिए जाते हैं।
यह उपकरण केवल अधिकृत सुरक्षा परीक्षण और अनुसंधान उद्देश्यों के लिए प्रदान किया गया है। आप यह सुनिश्चित करने के लिए पूर्ण रूप से ज़िम्मेदार हैं कि आपके पास किसी भी ServiceNow instance का परीक्षण करने की स्पष्ट अनुमति है जिसे आप लक्षित करते हैं। कंप्यूटर प्रणालियों तक अनधिकृत पहुँच अवैध है। लेखक दुरुपयोग के लिए उत्तरदायी नहीं हैं।