Issue
Assume the following API endpoint controller
enum class AccessMethod {
SSO,
BASIC;
}
internal open class SomeController {
[...]
@PostMapping("{accessMethod}")
open fun trigger(@PathVariable("accessMethod", required = true) accessMethod: AccessMethod) {
logger.info {"Is arbitrary code execution possible here in spring? $accessMethod"}
}
}
I am not well aware of the validation mechanisms of Spring. Does the input get sanitised by default in the enum case a.k.a will Spring throw an error?
Malicious PoC
val malicious_payload = "\"} malicious() logger.info {\"Code Injection Successful"
client.post(endpoint_of_the_function_above + malicious_payload )
Solution
My first thought is that if the input value does not an ENUM value (string representation), it generates an error. So Enum enabled "SSO" and "BASIC" and throws everything else back.
Kotlin (like Java) is not a script language, so you can not use kotlin or java language directly for inject, because it have to build to bytecode and run on JVM. Thus, the operation cannot be manipulated.
Ofc, you can manipulate generate any query language (SQL, NoSQL or send message, etc) by which only travel through the system. Of course, the frameworks mainly handle it, but errors can always occur, right? (Log4Shell was created because Log4J processing enabled external sources, so here it wasn't a case of code manipulated either.) Example: improperly handled identifiers with which SQL queries are created.
I created a small project and used your "vuln" string. Just it use URL so this string converted to URL encoded.
It will say HTTP400 for any URL that is not /SSO
and /BASIC
. By definition, an /asdasd
will also have an HTTP400 result.
\"} malicious() logger.info {\"Code Injection Successful
to %5C%22%7D%20malicious%28%29%20logger.info%20%7B%5C%22Code%20Injection%20Successful
Request:
POST http://localhost:8080/%5C%22%7D%20malicious%28%29%20logger.info%20%7B%5C%22Code%20Injection%20Successful
Response:
{
"timestamp": "2022-08-25T12:51:23.092+00:00",
"path": "/%5C%22%7D%20malicious%28%29%20logger.info%20%7B%5C%22Code%20Injection%20Successful",
"status": 400,
"error": "Bad Request",
"requestId": "c3bf4acf-1"
}
Source (I mainly use the reactive environment, but this is not relevant now.)
package com.example.demo
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Mono
enum class AccessMethod {
SSO,
BASIC;
}
@SpringBootApplication
@RestController
class DemoApplication {
val logger: Logger = LoggerFactory.getLogger(this::class.java)
@PostMapping("{accessMethod}")
fun trigger(@PathVariable("accessMethod", required = true) accessMethod: AccessMethod): Mono<Void> {
logger.info("Is arbitrary code execution possible here in spring? $accessMethod")
return Mono.empty()
}
}
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
Answered By - Numichi
Answer Checked By - Willingham (JavaFixing Volunteer)