
Struts2 और PowerShell का उपयोग करके CVE-2017-5638 OGNL इंजेक्शन भेद्यता को पुनः बनाना।
यह रिपॉजिटरी SC3010 कंप्यूटर सुरक्षा पाठ्यक्रम परियोजना का हिस्सा है।
यह CVE-2017-5638 का पुनर्निर्माण करता है, जो Apache Struts 2 (संस्करण 2.3.5–2.3.31 और 2.5–2.5.10) में एक गंभीर रिमोट कोड निष्पादन भेद्यता है, जिसका कुख्यात रूप से 2017 Equifax डेटा उल्लंघन में लगभग 147 मिलियन लोगों के व्यक्तिगत रिकॉर्ड चुराने के लिए शोषण किया गया था।
यह भेद्यता एक ही डिज़ाइन दोष से उत्पन्न होती है: जब Apache Struts multipart/form-data अपलोड अनुरोध को पार्स करने में विफल होता है, तो यह कच्चे Content-Type हेडर को — बिना स्वच्छता के — एक स्ट्रिंग में एम्बेड करके एक त्रुटि संदेश बनाता है, जिसे फिर OGNL अभिव्यक्ति मूल्यांकनकर्ता के माध्यम से पारित किया जाता है। इसलिए एक हमलावर जो Content-Type हेडर के अंदर एक OGNL अभिव्यक्ति डालता है, उसे Tomcat प्रक्रिया उपयोगकर्ता के रूप में सर्वर-साइड पर निष्पादित करवा लेता है।
इस रिपॉजिटरी में शामिल हैं:
SC3010-Computer-Security/
├── simulation/
│ ├── backend/ # Vulnerable Apache Struts2 2.3.28 server (Java/Maven)
│ └── attack-script/ # Exploit script for CVE-2017-5638
│ └── exploit_cve_2017_5638.ps1 # PowerShell (cross-platform)
├── struts-src-code/ # Apache Struts2 reference source + legal notices
│ ├── licenses/ # LICENSE, NOTICE, and component licenses
│ └── src/
│ ├── struts2-core/ # Request pipeline classes + vulnerable JakartaMultiPartRequest
│ ├── xwork2/ # ActionContext.java, OgnlUtil.java
│ └── ognl/ # OgnlContext.java
├── diagrams/ # State-machine + sequence diagrams, annotated OGNL payload
└── _notes/ # Background reading
नीचे दिया गया आरेख Struts2 अनुरोध पाइपलाइन में प्रत्येक निर्णय शाखा दिखाता है। लाल पथ वह है जिसे हमलावर मजबूर करता है; ग्रे → ... शाखाएं सुरक्षित पथ हैं जो शोषण के दौरान लागू नहीं होती हैं।
flowchart TD
Start([Attacker sends HTTP POST /upload.action<br/>Content-Type: %{OGNL_PAYLOAD}.multipart/form-data])
Start --> PIPE
PIPE["<b>Struts2 filter → wrap → parse pipeline</b><br/>doFilter() → PrepareOperations.wrapRequest()<br/>→ Dispatcher.wrapRequest() → new MultiPartRequestWrapper()"]
PIPE --> D_CT{"Content-Type contains<br/>"multipart/form-data"?"}
D_CT -- "No → normal request ..." --> OUT_NORM([non-upload path ...])
D_CT -- "Yes (attacker appends<br/>.multipart/form-data to payload)" --> PARSE
PARSE[/"<b>JakartaMultiPartRequest.parse()</b><br/>→ Commons FileUpload.parseRequest()"/]
PARSE --> D_VALID{"FileUpload can parse<br/>Content-Type?"}
D_VALID -- "Yes → normal file upload ..." --> OUT_OK([files extracted, action executes ...])
D_VALID -- "No — malformed Content-Type<br/>throws InvalidContentTypeException<br/>(message = raw Content-Type string)" --> CATCH
CATCH["parse() catch block<br/>calls buildErrorMessage(e, {})"]
CATCH --> FIND
FIND[/"<b>buildErrorMessage()</b><br/>→ LocalizedTextUtil.findText(class, errorKey, locale, e.getMessage(), args)"/]
FIND --> D_KEY{"Resource bundle has key<br/>struts.messages.upload.error.*?"}
D_KEY -- "Yes → safe localised message ..." --> OUT_SAFE([error displayed safely ...])
D_KEY -- "No — falls back to<br/>e.getMessage() as the default<br/>(attacker's raw Content-Type)" --> TRANSLATE
TRANSLATE["TextParseUtil.translateVariables()<br/>scans string for %{...} expressions"]
TRANSLATE --> D_OGNL{"String contains<br/>%{...} OGNL expression?"}
D_OGNL -- "No → plain error string ..." --> OUT_PLAIN([safe error message ...])
D_OGNL -- "Yes — evaluates OGNL<br/>inside attacker content" --> SANDBOX
SANDBOX[/"<b>OGNL sandbox bypass</b><br/>#ognlUtil.getExcludedClasses().clear()<br/>#ognlUtil.getExcludedPackageNames().clear()"/]
SANDBOX --> ACCESS
ACCESS[/"<b>Unrestricted reflection</b><br/>#context.setMemberAccess(DEFAULT_MEMBER_ACCESS)"/]
ACCESS --> RCE
RCE[/"<b>RCE</b><br/>Runtime.getRuntime().exec(cmd)"/]
RCE --> Done([Command executed as Tomcat process user])
style Start fill:#d32f2f,color:#fff
style Done fill:#d32f2f,color:#fff
style OUT_NORM fill:#9e9e9e,color:#fff
style OUT_OK fill:#9e9e9e,color:#fff
style OUT_SAFE fill:#9e9e9e,color:#fff
style OUT_PLAIN fill:#9e9e9e,color:#fff
style SANDBOX fill:#b71c1c,color:#fff
style ACCESS fill:#b71c1c,color:#fff
style RCE fill:#b71c1c,color:#fff
style CATCH fill:#e65100,color:#fff
style TRANSLATE fill:#e65100,color:#fffशाखा स्पष्टीकरण के साथ पूर्ण स्टेट-मशीन के लिए, diagrams/cve-2017-5638-state-machine.md देखें।
अनुक्रम आरेख दृश्य और एनोटेटेड OGNL पेलोड विवरण के लिए, diagrams/cve-2017-5638-attack-chain.md देखें।
यह रिपॉजिटरी शैक्षणिक सुरक्षा अनुसंधान उद्देश्यों के लिए Apache Struts 2.3.28 स्रोत कोड के अंशों का पुनरुत्पादन करती है।
Apache Struts कॉपीराइट © 2000–2016 द Apache Software Foundation।
Apache लाइसेंस, संस्करण 2.0 के तहत लाइसेंस प्राप्त है।
लाइसेंस की एक प्रतिstruts-src-code/licenses/LICENSE.txtपर उपलब्ध है।
Apache लाइसेंस द्वारा आवश्यक पूर्ण एट्रिब्यूशन नोटिसstruts-src-code/licenses/NOTICE.txtमें है।
Apache Struts 2 अतिरिक्त तृतीय-पक्ष घटकों को बंडल करता है, प्रत्येक अपने स्वयं के लाइसेंस द्वारा शासित है:
| घटक | लाइसेंस फ़ाइल |
|---|---|
| OGNL (ऑब्जेक्ट-ग्राफ नेविगेशन लाइब्रेरी) | struts-src-code/licenses/OGNL-LICENSE.txt |
| XWork | struts-src-code/licenses/XWORK-LICENSE.txt |
| FreeMarker | struts-src-code/licenses/FREEMARKER-LICENSE.txt |