introduction
The SSH protocol supports three major categories of remote server activities: a) command execution (including login shell), b) network forwarding and operation, and c) file transfer.
OpenSSH maintainers have determined that sftp and scp have no legal purpose for port forwarding (via the -L and -R options). During file transfer using these utilities, a flag that explicitly disables these features is passed unconditionally to the child SSH executable.
Some users may indeed need these features. An obvious subset is the penetration testers whose task is to verify that this feature is explicitly disabled on a public SFTP server.
Here are two techniques to enable these suppressed features by modifying the string of the sftp binary itself, or redirecting through a shell that can easily edit the command line. Depending on the platform's functionality, either technology may be required to achieve this goal.
Suppress details
First, it is important to find the running process of interest. The shell function below will display the PID that matches the shell pattern (note that this is not a regular expression). This runs under Debian dash (and most other common shells) and relies on the ps option of BSD:
<code>pps () { local a= b= c= IFS=$'\r'; ps ax | while read -ra do [ "$b" ] || c=1; for b; do case "$a" in *"$b"*) c=1;; esac; done; [ "$c" ] && printf '%s\n' "$a" && c=; done; }</code>
Start a traditional SFTP session to check the processes associated with it:
<code>$ id uid=1001(aturing) gid=1001(aturing) groups=1001(aturing)... $ sftp aturing@sftp.victimandum.com aturing@sftp.victimandum.com's password: Connected to sftp.victimandum.com. sftp></code>
We assume that the local UNIX user above has the same username account on the remote SFTP server.
After the session is run, a local process search for the user name will display the child SSH process generated by SFTP:
<code>$ pps aturing PID TTY STAT TIME COMMAND 9666 pts/0 S 0:00 sftp aturing@sftp.victimandum.com 9667 pts/0 S 0:00 /usr/bin/ssh -oForwardX11 no -oPermitLocalCommand no -oClearAllForwardings yes -oForwardAgent no -l aturing -s -- sftp.victimandum.com sftp</code>
The ClearAllForwardings yes parameter above will suppress any forwarding attempt without taking any action to break it.
The -L and -R port forwarding flags do not exist as valid options for the SFTP command line, but we can use the -S option to explicitly trigger them to specify a custom SSH handler, in this case the mail server:
<code>$ cat portssh #!/bin/sh exec ssh -L2525:smtp.victimandum.com:25 "$@"</code>
If forwarding suppression is not in place, this SFTP call is sufficient to establish a forwarding connection:
<code>$ sftp -S ./portssh -oClearAllForwardings\ no aturing@sftp.victimandum.com aturing@sftp.victimandum.com's password: Connected to sftp.victimandum.com. sftp></code>
Now you can see forwarding attempts in the child SSH process:
<code>$ pps aturing PID TTY STAT TIME COMMAND 9897 pts/0 S 0:00 sftp -S ./portssh -oClearAllForwardings no aturing@sftp.victimandum.com 9898 pts/0 S 0:00 ssh -L2525:smtp.victimandum.com:25 -oForwardX11 no -oPermitLocalCommand no -oClearAllForwardings yes -o ClearAllForwardings no -oForwardAgent no -l aturing -s -- sftp.victimandum.com sftp</code>
However, attempting to contact the remote mail server through the local forwarding port is unsuccessful due to explicit override:
<code>$ nc localhost 2525 $</code>
This unconditional suppression is visible in the source code:
<code>$ sed -n /X11/,/Forwardings/p openssh-8.7p1/sftp.c addargs(&args, "-oForwardX11 no"); addargs(&args, "-oPermitLocalCommand no"); addargs(&args, "-oClearAllForwardings yes");</code>
These static strings are also visible in compiled binary files:
<code>$ strings /usr/bin/sftp | grep [-]o[CFP] -oForwardX11 no -oPermitLocalCommand no -oClearAllForwardings yes -oForwardAgent no -oPort %d</code>
Finally, the documentation clearly states that this suppression is intentional and gives reasonable reasons:
<code>$ man ssh_config | sed -n /ClearAllForwardings/,/default/p ClearAllForwardings Specifies that all local, remote, and dynamic port forwardings specified in the configuration files or on the command line be cleared. This option is primarily useful when used from the ssh(1) command line to clear port forwardings set in configura‐ tion files, and is automatically set by scp(1) and sftp(1). The argument must be yes or no (the default).</code>
Change compiled strings
For those who want to disable the default ClearAllForwardings yes configuration, one option is to use sed to edit the strings in the SFTP binary directly (assuming the platform's sed is binary-safe):
<code>$ sed 's/AllForwardings yes/AllForwardings no /' sftp.noclearforward</code>
This direct modification is much easier than compiling new binary files.
We can confirm that the string has been modified successfully:
<code>$ strings ./sftp.noclearforward | grep [-]o[CFP] -oForwardX11 no -oPermitLocalCommand no -oClearAllForwardings no -oForwardAgent no -oPort %d</code>
Although the content and checksum of the modified SFTP will be different, any existing Linux BuildID sha1 will remain the same (but do not submit support tickets when using edited SFTP):
<code>$ file /usr/bin/sftp ./sftp.noclearforward /usr/bin/sftp: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d7e77e24d5fac0fdc89e62a4c9c656091f2c4a33, for GNU/Linux 3.2.0, stripped ./sftp.noclearforward: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d7e77e24d5fac0fdc89e62a4c9c656091f2c4a33, for GNU/Linux 3.2.0, stripped $ sha1sum /usr/bin/sftp ./sftp.noclearforward d8bdaf0b4642b9c324f9c2e0aeee2d9578fbe383 /usr/bin/sftp b12dda8ecfd7bd2847919b5531aea7c03364c123 ./sftp.noclearforward $ sha256sum /usr/bin/sftp ./sftp.noclearforward 986eecdfc654c9b3ff3fd0dce59690d47cf56be96a4b98a04a3682aef95d3f52 /usr/bin/sftp c8f99ce33fc129250c11dc6dbb8a01112e01124e470a92d0acefb955fd17d670 ./sftp.noclearforward</code>
You can call the modified SFTP binary to enable port forwarding:
<code>$ chmod 755 sftp.noclearforward $ ./sftp.noclearforward -S ./portssh aturing@sftp.victimandum.com aturing@sftp.victimandum.com's password: Connected to sftp.victimandum.com. sftp></code>
Now you can see the modified settings in the child process:
<code>$ pps aturing PID TTY STAT TIME COMMAND 9991 pts/0 S 0:00 ./sftp.noclearforward -S ./portssh aturing@sftp.victimandum.com 9992 pts/0 S 0:00 ssh -L2525:smtp.victimandum.com:25 -oForwardX11 no -oPermitLocalCommand no -oClearAllForwardings no -oForwardAgent no -l aturing -s -- sftp.victimandum.com sftp</code>
This feature is enabled and run on a remote server and can verify connections in a separate shell:
<code>$ nc localhost 2525 220 smtp.victimandum.com Microsoft ESMTP MAIL Service, Version: 1.2.3456.78901 ready at Sun, 1 Jan 2023 01:23:45 -0100 ^C</code>
When forwarding is disabled on the server, the client will receive a notification indicating this status when the connection attempts:
<code>channel 3: open failed: administratively prohibited: open failed</code>
The SFTP administrator assigned an untrusted account should be likely to verify that the server configuration explicitly disables forwarding and command execution.
Beyond POSIX Shell
While the dash and POSIX standards provide set -- as a way to reset command line parameters, more advanced features are provided in bash and ksh93:
<code>$ cat ynargs #!/bin/bash echo "${@//yes/no}"</code>
Quick test confirms successful editing:
<code>$ ./ynargs -oForwardX11 no -oPermitLocalCommand yes -oClearAllForwardings yes -oForwardAgent no -oForwardX11 no -oPermitLocalCommand no -oClearAllForwardings no -oForwardAgent no</code>
Note that the above ${@//.../...} is not a valid POSIX and cannot run in dash or any shell (mksh, oksh) derived from pdksh. Many platforms do not bundle shells with this feature (such as Android and OpenBSD, although there are ways to add them); for restricted platforms, binary editing techniques may be more direct than installing alternative shells.
To take advantage of this feature with a powerful shell, we create a directory and then create an SSH wrapper in it to clear the problem settings:
<code>$ cat ~/switcharoo/ssh #!/bin/bash exec /usr/bin/ssh "${@//yes/no}"</code>
Then set the directory before system SSH in $PATH:
<code>$ export PATH=~/switcharoo:$PATH $ which ssh ~/switcharoo/ssh</code>
Then, we call system SFTP in this modified environment:
<code>$ /usr/bin/sftp -S ./portssh aturing@sftp.victimandum.com aturing@sftp.victimandum.com's password: Connected to sftp.victimandum.com. sftp></code>
We observed that the shell resets the problem parameters:
<code>$ pps aturing PID TTY STAT TIME COMMAND 10058 pts/0 S 0:00 /usr/bin/sftp -S ./portssh aturing@sftp.victimandum.com 10059 pts/0 S 0:00 /usr/bin/ssh -L2525:smtp.victimandum.com:25 -oForwardX11 no -oPermitLocalCommand no -oClearAllForwardings no -oForwardAgent no -l aturing -s -- sftp.victimandum.com sftp</code>
Reconfirmed the local connection to the forwarding port:
<code>$ nc localhost 2525 220 smtp.victimandum.com Microsoft ESMTP MAIL Service, Version: 1.2.3456.78901 ready at Sun, 1 Jan 2023 01:23:45 -0100 ^C</code>
As a final demonstration, a complete SMTP exchange can be performed using the following script:
<code>$ cat awkmail #!/bin/gawk -f BEGIN { smtp="/inet/tcp/0/localhost/2525"; ORS="\r\n"; r=ARGV[1]; s=ARGV[2]; sbj=ARGV[3]; # /bin/awkmail to from subj 0) print |& smtp print "." |& smtp; smtp |& getline j; print j print "quit" |& smtp; smtp |& getline j; print j close(smtp) } # /inet/protocol/local-port/remote-host/remote-port</code>
We can use this script to send our own mail to a remote recipient that the target SMTP server can access:
<code>$ ./awkmail jatanasoff@victimandum.com aturning@localhost awkmail Queued mail for delivery</code>
In highly controlled environments, the presence of these functions is not optimal.
Server Restrictions
It is understandable that SFTP administrators do not want to allow their users to make arbitrary TCP connections with the help of the server, which can put sensitive networks at risk. Limiting this activity is a cautious security setting.
A common restrictive configuration is to add untrusted SFTP users to a group and then constrain the activity of this group in sshd_config:
<code>Match Group sftponly ChrootDirectory %h ForceCommand internal-sftp AllowTcpForwarding no</code>
This recommended configuration is usually sufficient to prevent all forwarding attempts.
It is recommended to add DisableForwarding yes:
<code>$ man sshd_config | sed -n /DisableForwarding/,/configurations/p DisableForwarding Disables all forwarding features, including X11, ssh-agent(1), TCP and StreamLocal. This option overrides all other forwarding- related options and may simplify restricted configurations.</code>
This is left to the administrator for practice.
in conclusion
Too strict SFTP client settings can lead to some degree of server management blindness. SFTP client restrictions are easily circumvented through a variety of methods.
For SFTP server administrators, it is important to know where they are restricted and where they are restricted, and do not rely on clients to protect the server from arbitrary TCP control. The client is controlled by the user, and if the configuration is wrong, it is difficult to implement TCP commands to the server. Any test should be done without extensive forwarding in user ssh_config, pay attention to the warnings in the document.
While this feature may have a conceivable legal purpose, abuse will be rare.
These issues are not new, as variants of site exec have been present in plaintext FTP for decades. SFTP is not a simple alternative to plaintext file transfer, it also has many easy-to-use features.
Hopefully administrators can use these methods to verify the security of their servers so as not to be caught off guard.
The above is the detailed content of SFTP Port Forwarding: Enabling Suppressed Functionality. For more information, please follow other related articles on the PHP Chinese website!