I. Background of vulnerabilities
On July 13, 2021, The Threat Intelligence Center of Microsoft issued a security bulletin [1], in which it was noted that hackers had successfully attacked a small number of US military sectors using Sev-U 0Day. On the same day, SolarWinds, the parent company of Sev-U, also issued a security bulletin [2] and issued a patch for the latest major version [3].
(Note: the patch is only for the latest 15.2.3 major release, and only paying users can download and install the patch. Non-paying users cannot obtain the effective patch from official channels.)
Based on patch comparisons and Fuzzer, the Serenity Shield security team successfully replicated the remote overflow vulnerability and was able to exploit it in a combat environment.
As of September 10, no technical analysis and POC release of the vulnerability had been found on the Internet, and no further news details had been published.
This vulnerability is the first RCE vulnerability to emerge since sev-U MDTM vulnerability was patched in 2003.
In order to thank our readers for their support, we have prepared the following benefits for you:
[one > get < one]
1. More than 200 e-books of network security series (all of them are available)
2. Complete kit (the most complete Chinese version, whichever you want to use)
3, 100 COPIES of SRC source code technical documents (project learning, real knowledge from practice)
4. Basic introduction to network security, Linux, Web security, video on attack and defense (2021 latest version)
6, network security learning route (bid farewell to the flow of learning)
7, CTF flag capture competition analysis (title analysis actual combat operation)
Ii. Serv-u software Description
The software is a globally popular commercial FTP server software with closed source. Official data shows that there are more than 10 million users of this software worldwide. The software supports FTP (port 21)/ SFTP (port 22) by default. It mainly runs on Windows platform and the new version is X64 program. The default 22-port banner information of this software contains the detailed version number. Zoomeye search shows that the IP volume in recent year is 13,000 (the full volume is more than 6.7W).
1100 PCS were installed in version 15.2.3 and 900 PCS were installed in patch 15.2.3.742. The vulnerability affected serv-U version < 15.2.3HF2 (15.2.3.742). According to the calculation that 13,000 units have been alive in the last year and 900 units have been installed with this vulnerability patch, at least 90% of the entire network is now under the threat of this vulnerability (the parent company of Sev-U should not release patches for a large number of existing old versions for commercial reasons, and upgrading the old version to the latest version needs to pay again).
Banner information
Iii. Vulnerability analysis and utilization description
review
This vulnerability is a remote memory corruption vulnerability (which can stabilize the control of virtual function Pointers). It is an attack against Serv-u SFTP(port 22) for WINDOWS. This vulnerability can be successfully attacked by entering IP and port without any account and password, as long as the version is earlier than 15.2.3.742. Success rate is close to 100% (a single success rate is less than 100%, but can immediately attack again), using the successful access to the SYSTEM permission SHELL.
3.1 Patch Comparison
Download the latest version 742 and the previous version 723
> 15.2.3.723 HF1 5/14/2021 > > Serv-u ignol due to incorrect OpenSSL API Usage > > < serv-u-installdir >\ serv-u.dl > > < serv-u-installdir >\ rhinonet. DLL > > 15.2.3.742 hF2 7/12/2021 > > * Unauthenticated Remote Code Execution in SSH protocol > > * <Serv-U-InstallDir>\Serv-U-RES.dll > > * <Serv-U-InstallDir>\Serv-U-Tray.exe > > * <Serv-U-InstallDir>\Serv-U.dll > > * <Serv-U-InstallDir>\Serv-U.exeCopy the code
It can be seen that four files were mainly modified. Bindiff was used to compare these four files in turn, and finally it was possible to exclude sev-U.xe, Sev-U-tray-exe and sev-U-res.dll, because the changes in these three files were so small that it was almost impossible to have any vulnerabilities.
At the same time, combined with official reports, APT attacks using this vulnerability may report the following errors:
> EXCEPTION: C0000005;
>
> CSUSSHSocket::ProcessReceive();
>
> Type: 30;
>
> puchPayLoad = 0x041ec066;
>
> nPacketLength = 76;
>
> nBytesReceived = 80;
>
> nBytesUncompressed = 156;
>
> uchPaddingLength = 5
Copy the code
Basically, it can be judged that this vulnerability is an SSH-related memory vulnerability. Using BINDIFF and IDA to patch the main DLL is as follows:
The left is the function address that has not been patched, and the right is the function address that has been patched
By analyzing more than ten functions with changes in serv-U.dll one by one and excluding four functions with comparison errors, a total of nine functions have changed. It is found that the patch has added hard-coded judgments and assignments for some functions, such as whether a value 198h is 0, 1, 2, 3, 4 or 5, etc. Or assign 198h to 0, 1, 2, 3, 4, or 5, etc.
At this point, IDA is required to try to understand the meaning of these values by first locating the location where the value is stored. You can see that the value is stored in A1 [0x198].
Then a binary search for 0x198 finds all locations where the value is read or written.
Unfortunately, even with the location and code of the patch, it’s hard to fathom the ultimate intent of the patch. So I took a different approach, and traced the patched functions all the way up, and found that sub_180145070 referred to all patched functions.
RhinoNET! RhinoNET! RhinoNET! RhinoNET! RhinoNET! RhinoNET! RhinoNET! CRhinoSocket: : ProcessReceiveBuffer, by naming can guess is used to process incoming data BUF, under the function entry point is broken:
The call stack of 180145070 is as follows:
RhinoNET! CRhinoSocket::OnReceive+0x170
mfc140u! CWnd::OnWndMsg+0xba9
mfc140u! CWnd::WindowProc+0x3f
mfc140u! AfxCallWndProc+0x123
mfc140u! AfxWndProc+0x54
mfc140u! AfxWndProcBase+0x49
USER32! UserCallWinProcCheckWow+0x1ad
USER32! DispatchMessageWorke+0x3b5
Serv_U_180000000! CUPnPNotifyEvent::SetTimeout+0x30d85
Serv_U_180000000! CUPnPNotifyEvent::SetTimeout+0x30dfd
ucrtbase! crt_at_quick_exit+0x7d
kernel32! BaseThreadInitThunk+0xd
ntdll! RtlUserThreadStart+0x1d
Take a closer look at the structure of the function, an outer loop with an inner switch.. The sub_180145070 function implements a partial or complete SSH handshake protocol.
Through debugging, it can be seen that this function is mainly used to process SSH messages. MSG messages are processed as follows:
> 180145070 > > 20 SSH_MSG_KEXINIT > > 30 SSH_MSG_ECDH key exchange init! CASE 28 > > 21 SSH_MSG_NEWKEYS > > 5 SSH_MSG_SERVICE_REQUEST > > 50 SSH_MSG_USERAUTH_REQUEST > > 90 SSH_MSG_CHANNEL_OPEN > > 98 SSH_MSG_CHANNEL_REQUEST > > 94 SSH_MSG_CHANNEL_DATACopy the code
For example, v21 in switch(V21) is the message code in the SSH protocol and identifies the message type.
This document provides information about SFTP protocol specifications
After the patch, the program mainly repaired three MSGS, 20,30 and 21, EVP_aes_128_ctr,EVP_EncryptInit_ex, EVP_DecryptInit_ex,EVP_EncryptInit_ex, EVP_DecryptInit_ex
At the same time, through debugging, the patched program, the order of MSG sequence has been restricted!
Patches are basic judgment after the vulnerability is an SSH protocol handshake phase logic to handle errors, resulting in memory processing errors, then by comparing the patch can’t find the traditional type of memory patches usually do to COPY length limit, to reconstruct the vulnerability requires Serv -u SSH handshake to the FUZZER.
3.2 FUZZER SSH Handshake Process
Armed with this information, you can write a FUZZ script (continuously generating message codes to test) to FUZZ test serv-U server 15.2.3.723 by simulating the data exchange during the SSH handshake phase.
After running the script for a period of time, we got a crash. By analyzing the crash, we could confirm that we did not send MSG no. 30 after sending message No. 20, but directly sent message No. 21, which was the cause of the crash of Serv-U, and the problem would not occur after the patch was installed. That means we probably found a loophole.
At the same time, this vulnerability is highly likely to be exploited, because SERv-U.delle does not enable ASLR, and we have the ability to control EIP, so we can execute the code remotely with ROP.
In the figure below, you can see that the pointer to the called function is overwritten to AAAAAA… That is, we can override a virtual function pointer with controllable data to control the flow of function execution to execute our ShellCode.
The call stack at crash looks like this:
The final location of the crash is not in serv-U.dll, but in Libeay32.dll, a dynamic link library that is a component of OpenSSL for encryption and decryption. By tracing debugging, handshake data is found AAAAAA… The last 8 bytes of data were mistakenly called by libeay32.dll as function Pointers, triggering a crash.
Locating the packet sent during the crash, it was found that the packet disrupted the normal SSH communication process (the handshake packet was out of order). Therefore, the hard-coded values 0, 1, 2, 3, 4, 5 in the patch were to limit the sending order of packets, that is, MSG 30 can only be sent after MSG 20 is sent, so as to alleviate the vulnerability.
3.3 Vulnerability Exploitation
By analyzing the packet sending process and the SSH communication process of serv-U, it can be found that this vulnerability is caused by the memory uninitialized vulnerability caused by the disorder of the SSH communication process of serv-U. ** Enumerates the triggering principle and process of vulnerabilities through network packets as follows:
- The SSH communication process is as follows
Key exchange initialization (request N bytes of memory, different for each version);
The key negotiation algorithm exchanges parameters, such as ECDH (fill N bytes of memory: fill function addresses in memory blocks).
Encrypt and decrypt data (call N bytes of memory function address)
- The process of triggering vulnerability is
Key exchange initialization (request N bytes of memory);
Encrypt and decrypt data (call N bytes of memory function address);
It can be seen that the step of ECDH key exchange negotiation is omitted in the vulnerability triggering process. And memory is not initialized when N bytes are requested in the first step.
- Exploit process triggered by vulnerability
Sending packets occupy N bytes of memory space in pit layout, and release;
Key exchange initialization (request N bytes of memory, the contents of which have been laid out in advance)
Encryption and decryption data trigger vulnerability ** (missing key negotiation to set the function pointer in the n-byte memory block, so will call the function address in the n-byte memory has been laid out in advance); **
- Principles of Vulnerability patch
The vulnerability patch restricts SSH communication so that function Pointers in memory can no longer be laid out and exploited by an attacker.
By analyzing the collapse, it is determined that the vulnerability is highly likely to be exploited, because sev-U.dll does not open ASLR, which provides us with the necessary conditions for the arrangement of ROP chain. In addition, the location of the above crash is at the CALL instruction, which gives us a high probability of controlling the EIP. When these two capabilities are in place, the program can be controlled to jump to the ROP chain to execute the predefined code.
Although VirtualProtect is not imported in serv-U.ll, it does import another function ShellExecuteExW that can execute code, so the goal is to construct an ROP chain and pass in the specified arguments to execute ShellExecuteExW.
First, use capstone to write a small tool to extract ROP and obtain the address of the required instruction.
These instructions are then concatenated to execute ShellExecuteExW by switching stacks + layout parameters + calling functions.
Switching stacks is the first step, but it’s as simple as modifying the RSP using XCHG, POP, MOV, and LEA instructions. The layout parameter is the most difficult part of the whole process, because ShellExecuteExW has only one parameter, which is a structure pointer, and the string pointer inside the structure is the core of the command execution, so it involves the layout of multi-level Pointers. Since we control the whole stack, it is not difficult to arrange multi-level Pointers, but the steps are tedious and error-prone, so we must be patient and cautious.
After the parameters are set, the EIP is again controlled to jump to the function pointer execution in the import table. Once the ShellExecuteExW function has finished executing, the user-specified command has finished executing, but the main program will crash because the stack is corrupted.
If you do not use ShellExecuteExW, you can also obtain the address of the VirtualProtect function using the code shown below:
(The above address DLL version is 15.2.3.723)
Iv. Description of existing patches
As of September 10, the patches released are as follows:
| | | version released time presence of loopholes | | < 15.2.3.717 there | — – | | | 15.2.3.717 | 2021/04/20 there | | | 15.2.3.723 hf1 | 2021/05/14 there | | | 15.2.3.742 hf2 | 2021/07/12 no (latest version) | |
5. Description of vulnerability exploitation tools
5.1 Affected Software Versions
SSH – 2.0 – Serv – U_15. 1.6.25 to SSH – 2.0 – Serv – U_15. 2.3.723
Note: SSH-2.0-serv-U_15.1.6.25 was released in 2017, and older versions are certainly affected, but the earliest version currently tested is 2017. Ssh-2.0-sev-u_15.2.3.723 is earlier than the latest patch version.
5.2 Restrictions on remote Utilization
Serv-u needs to be started as a service to take advantage of it, but the default installation of serv-u is already started as a service. It cannot be exploited if it is started in non-service mode.
5.3 Demonstration effect and special case description of remote utilization execution
- After successful exploitation, the serv-u.xe program of the target machine will execute our ShellCode and start a PowerShell child process (the parent process is serv-U.xe), and connect back to the IP and port we set through PowerShell script. The obtained SHELL permission is SYSTEM permission.
- The ShellCode starts the program and executes the program commands by modifying the attack script;
- The program commands executed by ShellCode mentioned in Point 2 above are limited in length to 500 bytes.
- If the use is successful, the serv-U.xe program will crash and restart automatically (no pop-up box, because it is started in service mode, it will restart automatically), so it can be used remotely unlimited times;
- If the exploit fails, wait 10 seconds after the execution of the attack script before launching the next attack until it succeeds.
- The success rate of each attack is about 20-50%;
- The size of network packets sent by a single attack is about 2 to 3M. Pay attention to network conditions.
- Each serv-U version needs to have a corresponding ROP sequence, so each individual small serv-U version needs to be customized to develop the corresponding attack code (the program has DEP, but the key DLL does not have ASLR).
- This article is for security technical purposes only and is intended to provide a detailed analysis of this vulnerability for users and security researchers who do not have access to patches, so no POC is provided.