
ngxray — nginx कॉन्फ़िग सुरक्षा स्कैनर
nginx कॉन्फ़िगरेशन के लिए स्थैतिक भेद्यता स्कैनर। nginx के स्वयं के टोकनाइज़र से कॉन्फ़िग पार्स करता है और rewrite/script engine डायरेक्टिव पैटर्न में ज्ञात CVE का पता लगाने के लिए घोषणात्मक JSON नियमों से मिलान करता है।
cd ngxray
git submodule update --init
make
python3 scan.py /etc/nginx/nginx.conf
नियम rules/ में JSON फ़ाइलों के रूप में परिभाषित किए गए हैं। स्कैनर इनके साथ आता है:
| नियम | CVE | पैटर्न |
|---|
rewrite-is-args | CVE-2026-42945 | rewrite … /path?args + set $var $1 |
rewrite-is-args-if | CVE-2026-42945 | rewrite … /path?args + if (… $1 …) |
nested-capture-redirect | CVE-2026-9256 | rewrite ^/((…))$ … redirect ओवरलैपिंग $N के साथ |
is_args स्टेल फ़्लैग ओवरफ़्लोप्रभावित: NGINX 0.6.27 – 1.30.0, NGINX Plus R32 – R36. फिक्स्ड: 1.31.0 / 1.30.1.
एक rewrite प्रतिस्थापन जिसमें ? होता है, script engine में e->is_args=1 सेट करता है। यह फ़्लैग बाद के set या if डायरेक्टिव्स में बना रहता है, जिससे copy pass कैप्चर डेटा को raw बाइट्स के लिए आकार दिए गए बफ़र में URI-escape (3x विस्तार) कर देता है।
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1; # $1 evaluated with stale is_args=1
}
प्रभावित: NGINX 1.31.0 तक। फिक्स्ड: 1.31.1 / 1.30.2।
नेस्टेड कैप्चर ग्रुप फ़ास्ट-पाथ escape बजट को कम आंकने का कारण बनते हैं — समान URI बाइट्स को प्रत्येक ओवरलैपिंग $N संदर्भ के लिए एक बार escape किया जाता है।
rewrite ^/((.*))$ http://backend/$1$2 redirect;
# Single file
python3 scan.py /etc/nginx/nginx.conf
# Directory (recursive, all *.conf files)
python3 scan.py /etc/nginx/
# Filenames from stdin
find /etc/nginx -name '*.conf' | python3 scan.py -
# Pre-parsed JSONL (faster for large batches)
find /etc/nginx -name '*.conf' | ./build/nginx_conf_parse - | python3 scan.py --jsonl -
# JSON output
python3 scan.py --json /etc/nginx/nginx.conf
# Custom rules directory
python3 scan.py --rules ./my-rules/ /etc/nginx/nginx.conf
corpus_tools/ पैकेज GitHub Code Search से सार्वजनिक nginx कॉन्फ़िगरेशन सामग्री एकत्र कर सकता है
और wrapper प्रारूपों से nginx स्निपेट निकाल सकता है।
python3 corpus_tools/collect_github_nginx_corpus.py \
--output-dir corpus_out/nginx-rift \
--query-file corpus_tools/queries/nginx-rift.txt
python3 corpus_tools/extract_nginx_configs.py \
--input-dir corpus_out/nginx-rift/raw \
--output-dir corpus_out/nginx-rift/extracted
python3 scan.py corpus_out/nginx-rift/extracted
पूर्ण वर्कफ़्लो और प्रलेखित Rift-केंद्रित संग्रह विधि के लिए corpus_tools/README.md और corpus_tools/docs/ देखें।
rules/ में एक JSON फ़ाइल डालें। इंजन स्टार्टअप पर rules डायरेक्टरी से सभी *.json फ़ाइलें लोड करता है।
{
"id": "rule-name",
"cve": "CVE-YYYY-NNNNN",
"severity": "CRITICAL",
"message": "short description shown in output",
"affected": "nginx version range",
"fixed": "fixed versions",
"ref": "https://link-to-advisory",
"match": [ ... ],
"tests": {
"vulnerable": ["server { ... }"],
"safe": ["server { ... }"]
}
}
प्रत्येक नियम में vulnerable (जो ट्रिगर होना चाहिए) और safe (जो ट्रिगर नहीं होना चाहिए) कॉन्फ़िग स्निपेट के साथ tests शामिल हो सकते हैं। सभी नियमों को मान्य करने के लिए python3 scan.py --test चलाएँ।
match डायरेक्टिव शर्तों की एक सूची है। यदि एक शर्त है, तो इंजन किसी भी मेल खाते डायरेक्टिव के लिए पूरे कॉन्फ़िग ट्री को खोजता है। यदि कई हैं, तो सभी शर्तों को एक ही ब्लॉक में सिबलिंग डायरेक्टिव्स से मेल खाना चाहिए।
प्रत्येक शर्त:
{
"directive": "rewrite",
"args": {
"0": { "contains": "?" },
"1": { "regex": "\\$[1-9]" }
},
"any_arg": { "regex": "\\$[1-9]" },
"or": [
{ "args": { "1": { "contains": "?" } } },
{ "any_arg_from": 2, "any_of": ["redirect", "permanent"] }
]
}
args — स्थिति (स्ट्रिंग के रूप में) द्वारा कुंजीबद्ध। प्रत्येक मान एक शर्त ऑब्जेक्ट है।max_args — यदि डायरेक्टिव में N से अधिक args हैं तो अस्वीकार करें।overlapping_refs — सत्यापित करें कि args[1] में $N संदर्भ args[0] में कैप्चर ग्रुप से मेल खाते हैं जो भौतिक रूप से एक-दूसरे को समाहित करते हैं।any_arg — शर्त को किसी भी स्थिति में कम से कम एक arg से मेल खाना चाहिए।or — कम से कम एक शाखा का मेल होना चाहिए। शाखाएँ args या any_arg_from + any_of जाँच सकती हैं।| कुंजी | प्रकार | कब मेल खाता है |
|---|---|---|
contains | स्ट्रिंग | Arg में सबस्ट्रिंग शामिल है |
regex | स्ट्रिंग | Arg regex से मेल खाता है |
not_regex | स्ट्रिंग | Arg regex से मेल नहीं खाता है |
any_of | [स्ट्रिंग] | Arg किसी एक मान के बराबर है |
extract | स्ट्रिंग | कैप्चर ग्रुप वाला regex — गिनती के लिए सभी मैच निकालता है |
min_unique | पूर्णांक | (extract के साथ प्रयुक्त) कम से कम N अलग-अलग मैच मिले |
extract + min_unique किसी arg में पैटर्न गिनने का सामान्य तंत्र है। उदाहरण के लिए, कम से कम 2 अलग-अलग कैप्चर संदर्भ ($1–$9) की आवश्यकता के लिए:
{ "extract": "\\$([1-9])", "min_unique": 2 }
{
"id": "proxy-buffer-overflow",
"cve": "CVE-2099-99999",
"severity": "CRITICAL",
"message": "proxy_pass with oversized buffer — heap overflow",
"ref": "https://example.com/advisory",
"match": [
{
"directive": "proxy_pass",
"args": { "0": { "regex": "https?://" } }
},
{
"directive": "proxy_buffer_size",
"args": { "0": { "regex": "^(6[5-9]|[7-9]\\d|\\d{3,})k$" } }
}
],
"tests": {
"vulnerable": [
"server { location / { proxy_pass http://backend; proxy_buffer_size 128k; } }"
],
"safe": [
"server { location / { proxy_pass http://backend; proxy_buffer_size 8k; } }"
]
}
}
parser/ डायरेक्टरी में एक स्टैंडअलोन C प्रोग्राम है जो कॉन्फ़िग फ़ाइलों को JSON AST में पार्स करने के लिए nginx के स्वयं के टोकनाइज़र (src/core/ngx_conf_file.c से ngx_conf_read_token और ngx_conf_parse) का उपयोग करता है। यह वही लेक्सर है जो nginx स्टार्टअप पर उपयोग करता है — कोई पुनः कार्यान्वयन नहीं।
मुख्य संशोधन: ngx_conf_handler() (जो डायरेक्टिव्स को संकलित मॉड्यूल में भेजता है) को conf_handler() से बदल दिया गया है, जो नाम की परवाह किए बिना हर डायरेक्टिव को एक ट्री में दर्ज करता है। यह पार्सर को मॉड्यूल सिस्टम के बिना किसी भी मान्य कॉन्फ़िग को संभालने देता है। संशोधन बिल्ड समय पर एक पैच के रूप में लागू किया जाता है — इस रिपॉजिटरी में कोई nginx स्रोत फ़ाइल कॉपी नहीं की जाती।
शेष nginx स्रोत फ़ाइलें (पूल आवंटक, स्ट्रिंग फ़ंक्शन, लॉगिंग, आदि) सीधे सबमॉड्यूल से संकलित की जाती हैं।
scan.py rules/ से JSON नियम लोड करता है, nginx_conf_parse के माध्यम से कॉन्फ़िग पार्स करता है, और AST के विरुद्ध प्रत्येक नियम का मूल्यांकन करता है। सभी पता लगाने की विशिष्टताएँ JSON नियम फ़ाइलों में रहती हैं।
C कंपाइलर और Python 3 की आवश्यकता है। nginx स्रोत एक git सबमॉड्यूल के रूप में शामिल है।
git submodule update --init
make
make test
यह रिपॉजिटरी Copybara के माध्यम से केवल-पठनीय रूप में github.com/califio/ngxray पर मिरर की जाती है। COPYBARA.md देखें।