Summary
A use-after-free vulnerability exists in ProFTPD. Successful exploitation of this vulnerability could allow a remote attacker to execute arbitrary code on the affected system.
Product
ProFTPD
Tested Version
Development version - master branch (Jan 22, 2020)
Details
Use-after-free vulnerability in memory pool allocator (CVE-2020-9273)
It is possible to corrupt the ProFTPd memory pool by interrupting current data transfer (PoC Exploit Demo Video.webm). This can be done for example, by sending an interrupt order to the command channel while a transfer is active in the data channel.
In our PoC, the program crashes on the alloc_pool
function (pool.c
) when executing first_avail = blok->h.first_avail
.
As you can see, the right side operand of the assignment in pool.c:569
is p->last
(See Image 1). However, the problem is that p
is a corrupted pool (See Image 2).
The source of the problem comes from the pcalloc
call in netio.c:1066
(See Image 3). This function calls the alloc_pool
function again which in turn calls new_block
to obtain a new freed memory block (See Image 4). But the memory block returned by new_block
is still referenced by the p
pool.
The problem is that new_block
function is not concurrently-secure, and under certain circumstances, the new_block
function can return as a free block a block already present in the pool, causing the corruption of the pool list.
So, in short, p
is a dangling pointer due to an use-after-free vulnerability.
It’s important to note that our tests show that this vulnerability can also lead to other primitives such as OOB writes, which increases the severity of the vulnerability.
ProFTPD ASAN build instructions
CC="clang" CXX="clang++" CFLAGS="-fsanitize=address,undefined -g" CXXFLAGS="-fsanitize=address,undefined -g" LDFLAGS="-fsanitize=address,undefined" ./configure
LDFLAGS="-fsanitize=address,undefined" make -j4
Steps to reproduce:
- Create a new user
fuzzing
with passwordfuzzing
and extractCompressed_Dir.tar.gz
dir in their home folder. - Compile ProFTPD using ASAN as mentioned above.
- Run ProFTPD as root with the basic configuration and and following options:
ASAN_OPTIONS=verbosity=3,detect_leaks=0,abort_on_error=1,debug=true,check_initialization_order=true,detect_stack_use_after_return=true,strict_string_checks=true,detect_invalid_pointer_pairs=2 ./proftpd -n -c basic.conf -d 10 -X
- Run a netcat listener on port 1055 (PORT 127,0,0,1,4,31 in our PoC).
- Send the PoC trigger to the running ProFTPD server using telnet (assuming that it is running on port 21/TCP):
telnet 127.0.0.1 21 < test.txt
- ProFTPD should crash showing the relevant ASAN trace
Impact
This issue may lead to Post-Auth RCE.
Remediation
The issue has been fixed here https://github.com/proftpd/proftpd/commit/929d6c5a107ad92705555a87c386abd8bdce5d0d
Coordinated Disclosure Timeline
This report is subject to our coordinated disclosure policy.
- 01/22/2020: Report sent to Vendor
- 01/25/2020: Vendor acknowledged report
- 02/16/2020: Vendor proposed fixes
- 02/17/2020: Fixes reviewed and verified
- 02/18/2020: Report published to public
Supporting Resources
Credit
This issue was discovered and reported by GHSL team member @antonio-morales (Antonio Morales).
Contact
You can contact the GHSL team at securitylab@github.com
, please include the GHSL-2020-009
in any communication regarding this issue.