qwqg

2005年7月4日 #

FreeBSD下构建安全的Web服务器

(说明:本文已首发在安全焦点,可以参考一下链接http://www.xfocus.net/articles/200506/808.html)

* 作者:heiyeluren
* 创建:2005-04-10 20:38
* 修改:2005-05-14 23:25
* 邮箱:heiyeluren_at_163.com
* 主页:http://www.unixsky.net
* 博客:http://blog.csdn.net/heiyeshuwu


::目录::

序言

一、系统和服务程序的安装
1. 系统安装
2. 服务程序安装

二、系统安全设置
1. 用户控制
2. 文件访问控制
3. 系统服务和端口控制
4. 日志管理和控制
5. 文件指纹检测
6. 系统指纹泄露和防范
7. 系统内核安全
8. 系统安全优化

三、服务程序的安全设置
1. Apache安全设置
2. PHP安全设置
3. Mysql安全设置
4. vsFTPd安全设置
5. SSH的安全设置

四、防火墙的安装和设置
1. 安装ipfw
2. 配置ipfw

五、Unix/Linux上的后门技术和防范
1. 帐号后门
2. shell后门
3. cron服务后门
4. rhosts后门
5. Login后门
6. Bind后门
7. 服务后门
8. rootkit后门
9. 内核后门
10. 其他后门

六、结束语

附录


序言

在我们跑Web服务器的时候,大家可能都会一致认为使用Linux+Mysql+Apache+PHP整个开源的系统是比较好的选择,但是我个人认为这是不合理的,首先要根据你的应用来觉得你使用什么服务。假如你需要跑Oracle等大型应用的话,而且Oracle在Linux下是支持的比较好的,那么使用Linux是个好的选择,因为在FreeBSD下安装Oracle是个非常麻烦的事情。那么如果是跑普通的网站应用的话,我觉得使用FreeBSD+Mysql+Apache+PHP是个好的选择,因为对于一个网站来讲,稳定安全是第一位的,否则你的网站什么时候被人修改了都不知道怎么回事,或者被黑客入侵,把数据修改或者删除,那就糟糕了,毕竟现在什么红客、黑客的一堆,不能不防。当然,不是说Linux不安全,但是在Linux下集成了很多不安全的程序,导致了它的不安全,但如果设置的好,Linux一样可以很安全。在中国网络应急响应中心(http://www.cert.org.cn)这几个月的数据来看,每个月被入侵成功最高的是Linux系统,占百分之六十多,然后过来是Windows系统,占百分之三十多,而FreeBSD的入侵比例是百分之几。

任何系统都可以很安全,也可以很不安全,关键是管理员怎么做的,世界上没有最安全的系统,只有更安全的系统。下面的文章就是
在FreeBSD平台上构建一个比较安全的Web服务器,希望对网管和网络安全爱好者能有一些启发,权当抛砖引玉,希望能够有更好阐述的文章。


一、系统和服务程序的安装


1. 系统安装

为了保证系统的安全,我们系统准备采用最新的FreeBSD版本,首先是安全,系统兼容性也比较好,这个主要是个人习惯和需求,为了简单起见,这里我们选用了最新的FreeBSd5.3版本进行安装。整个安装过程我就不讲了,如果不清楚的朋友可以参考FreeBSD中文手册(http://www.freebsd.org.cn),整个过程不是很复杂,虽然没有Windows/Linux的系统安全简单,但是比起有些Unix的安装来讲是人性许多的。安装中必须把基本包和内核源代码都装上,为了以后编译内核方便,如果另外,如果喜欢使用ports安装软件的话,还要把ports装上,但是尽量一些没有必要的程序不要装。如果要安装Webmin等,还要把perl等包装上。系统文件拷贝完以后,会要求配置一些设置,比如把IP地址、名字服务器等设好,不要打开IPv6,不需要DHCP等服务,不要系统默认的FTP服务,配置 /etc/inetd.conf 时把SSH服务打开,方便我们进行远程管理,如果不想使用inetd这个超级服务来管理的话,可以关闭它,在/etc/rc.conf中添加inetd_enable="NO",然后设置sshd_enable="YES"一样可以打开SSH服务,后面我们会详细谈到SSH的设置。

系统装完后,在 /etc/inetd.conf 中把除了ssh之外的服务全部关闭,特别是telnet和rlogin等服务,一定要慎重,否则很可能每几天系统就被入侵了。安装完系统后,建议对系统进行升级,比如使用 make world 或 cvsup 把系统内核和ports进行升级。这个步骤和Windows装完后打补丁差不多。


2. 服务程序安装

系统装完以后,就开始安装我们的应用软件,我们的方针还是最新的软件是最安全的,比如能够防止一些老版本中的溢出等等。我们基本就是要让我们的系统有数据库,同时能够处理Web服务,同时能够远程对网站进行文件管理的FTP服务。我们基本选择的程序都是比较通常的程序。另外,为了有个可视化的管理工具,我们同时也可以安装一个基于浏览器的管理工具Webmin,方便没有ssh客户端等等的时候进行管理。

首先我们选用的Web服务是Apache httpd 2.0.53,这是目前的最新版本,当然你也可以考虑1.3的版本,主要是看个人习惯。我们网站是PHP程序编写,所以要安装PHP,版本是4.3.11,也是最新的版本,如果你的网站程序需要PHP5的支持,那么可以下载php5.0.4。数据库还是最快速的Mysql,选择的版本是最新的 4.0.23,如果你需要外键、事务、子查询、存储过程等的支持,那么你可以考虑4.1和5.0的版本。最后我们的FTP选择最安全的vsFTPd,因为它是最安全快速的,我在局域网中测试它的最高创数速率能够达到10MB/S,proFTPd只有8MB/S,vsFTPd针对小型FTP服务器支持非常好,毕竟我用户不多,几个更新网站而已,当然,如果你喜欢简单方便,也可以考虑使用FreeBSD自带的FTPd,功能和易用性也是不错的。如果你用户比较多,并且功能要求比较高,建议使用proFTPd、pure-FTPd、wu-FTPd等,但有些FTPd不是非常安全,选择时候一定要慎重考虑。

服务器程序列表:
Apache 2.0.53 下载地址:http://httpd.apache.org
PHP 4.3.11 下载地址:http://www.php.net
Mysql 4.0.23 下载地址:http://dev.mysql.com
vsFTPd 2.0.2 下载地址:http://vsftpd.beasts.org

反正最少的服务+最少的端口+安全的设置 = 最大的安全,尽量能够不需要使用的服务就不要安装,比如telnetd、rlogind等,那么相反会对服务器安全构成威胁。

安装以上程序你可以采用手工编译安装,也可以采用FreeBSD的ports 来进行安装,这看个人爱好,我个人比较喜欢使用手工安装,如果不明白具体安装的朋友可以参考我的Blog上关于安装Apache+PHP+Mysql的方法。



二、系统安全设置


1. 用户控制

尽量少的用户,我们的FTP帐户是和系统帐户绑定在一起的,所以我们添加用户的时候先建立一个目录,然后把新建的用户主目录指向到该目录下。假设我需要一个用户能够管理我的网站,而我网站的目录是在 /usr/www 目录下,那么我们新建立的用户 www_user 的主目录就指向 /usr/www 目录,同时它的shell是没有的:/usr/sbin/nologin ,主要是为了防止它通过ssh登陆到系统。同时FTP的密码也要设置的非常复杂,防止黑客通过暴力破解获得FTP权限。另外还要说道我们的root用户的密码,我想最少应该不要少于10位的数字+字母+字符的密码(我的密码是18位),否则是非常不安全的,如果密码简单,那么黑客通过短时间的暴力破解SSH中的root帐户,不用几天,系统就可能被攻破了,同时也建议最少一个月更改一次root用户的密码。(强烈建议一般帐户不要有登陆系统的权限,就是把shell设为/usr/sbin/nologin)
一般如果要使用root权限建议建立一个属于wheel组的小用户,然后登陆后通过su命令提升为root用户进行管理,如果黑客通过破解了我们普通用户的权限后登陆系统,也不能直接通过root权限进行管理,这是一种安全防范的简单方法。


2. 文件访问控制

有时候被黑客入侵后拿到了小权限用户,比如传了一个WebShell到系统中,那么对方很可能会把 /etc/passwd 等内容直接读取出来,同时查看/etc/master.passwd中对加密后的root用户的密码hash进行破解,最后拿到密码进行登陆系统。那么我们就要控制部分文件只有root能够访问,其他用户无权访问。比如uname,gcc等,如果黑客拿到小权限用户后就会查看系统版本,然后找到该版本系统对应的溢出程序,使用gcc来进行编译,如果我们能够限制黑客访问uname和gcc等程序,能在一定程度上减缓黑客入侵的脚步。
使用chmod来改变某个文件的权限信息,比如我要 /etc/passwd 和 /etc/master.passwd 文件只能允许root访问:
使用八进制数字来设置
# chmod 700 /etc/passwd
# chmod 700 /etc/master.passwd
使用字符标记来进行设置
# chmod u+w+r+x,go-w-r-x /etc/passwd
# chmod u+w+r+x,go-w-r-x /etc/master.passwd
系统中有多个重要文件需要设置控制访问权限,一定要控制好,否则将会构成重要威胁。


3. 系统服务和端口控制

端口开的越多就越给黑客多一个入侵的机会,服务越多,危险越大,因为你不知道那些服务是不是有潜在的漏洞或者又发现了新的漏洞,所以尽量少的服务,比如sendmail默认是打开的,那么些建议你把sendmail关闭,关闭防范是在 /etc/rc.conf中加上:
sendmail_enable = "NONE",如果设为"NO"那么只能够关闭掉pop3服务,不能关闭smtp的服务,所以要设置为"NONE"。
系统中最好除了我们能够看到的Apache、Mysql、vsFTPd、SSH之外不要打开其他任何端口和服务。基本的方式是使用netstat -a 查看打开的端口,然后从对应的端口来找相关的服务,比如我们这里应该只允许开的端口有 21, 22, 80, 3306等,如果有其他端口,那么一定要仔细检查,很可能是黑客的后门或者是会对系统安全构成威胁的服务。同时有些服务不需要监听网络连接的话,只是需要本地的连接,比如Mysql,那么就可以关闭Socket监听,这个将在Mysql安全设置中讲解,另外,可以通过防火墙来控制部分端口访问和连接状况,比如Mysql的3306端口只允许192.168.0.1访问,那么我们就在ipfw里添加规则:
ipfw add 10001 allow tcp from 192.168.0.1 to 10.10.10.1 80 in
这样就能够防止黑客来访问服务器上的Mysql服务。具体防火墙的设置将在下面“防火墙设置”中详细讲解。


4. 日志管理和控制 (未完)


5. 文件指纹检测

文件指纹就是我们文件的基本信息,比如文件权限、文件所属用户/组、文件最后修改日期、文件大小等等,这些都是重要信息,一般黑客入侵后都可能修改文件,那么文件指纹就不一样了。另外,文件的md5校验值也属于文件的指纹的一种。
为了防止黑客篡改系统中的部分核心文件,比如 /etc/passwd, /etc/shadow, /etc/inetd.conf 等等,那么我们就可以考虑把部分重要文件进行备份,同时做一份目前有的文件的一个指纹保留,比如把 /etc,/bin, /usr/bin 目录下的文件进行指纹保留:
# ls -l /etc > /var/back/etc.txt
# ls -l /bin > /var/back/bin.txt
# ls -l /bin > /var/back/usrbin.txt
当然,还有就是给每个重要的文件加上md5校验值,如果觉得不对劲的时候就进行匹配,保证文件的安全。
你可以给你觉得需要做指纹备份的目录进行备份,一般这是为了以后被黑客入侵后的系统检测和系统恢复。比如可以通过文件被修改的时间来确定是不是被入侵,比如可以对比看 /etc/inetc.conf文件和备份的文件有什么不同来确定是不是安装了服务型后门等。


6. 系统指纹泄漏和防范 (未完)

一般黑客为了入侵某个系统,一定会先进行扫描等工作,扫描包括目标系统的端口开放情况和服务器使用服务程序和操作系统情况。比如很简单的手工检测Web服务的指纹:
# telnet target.com 80
那么就很可能返回Apache和PHP的版本信息,那么同时也可能使用扫描工具对Mysql、vsFTPd、SSH等服务的端口进行扫描,获取这些服务的指纹。多暴露一份系统信息,那么系统就多一份危险。那么解决办法就是把服务器上服务程序的Banner全部修改掉,从而能够迷惑黑客。

下面简单的说一些修改那些服务Banner的方法。

* Apache
修改httpd.conf文件,设置以下选项:
ServerSignature Off
ServerTokens Prod
上面的适用apache1***, apache 2.0这些都是默认 , 不过还是有server=Apache字样, 若要完全去掉需重新編译。
彻底地去掉banner, 修改httpd.h:
Include/httpd.h
Define SERVER_BASEVENDOR "Apache Group"
Define SERVER_PRODUCTVENDOR "Apache"
Define SERVER_BASEVERSION "1.3.27"
后从新编译Apache就能够完全去掉了。


* PHP
在php.ini中设置 expose_php = Off ,那么将无法在 http头信息中看到php的版本信息。

* Mysql


* vsFTPd
vsFTPd基本上是无法获取到一些关于vsFTPd的banner信息的,不过因为vsFTPd默认的banner信息是"Welcome to FTP Server!"对于高手来说,还是能够猜测到一点,所以我们要彻底改掉。修改vsFTPd的配置文件 vsftpd.conf 中的下面选项:
Ftpd_banner=xxxxx
把后面的xxxxx改为你想要的banner信息。


* SSH
好象FreeBSD下默认安装的SSH被telnet target.com 22 的时候会显示SSH和FreeBSD的信息,简直是个大祸害,什么都告诉别人了,但是目前为止我还不知道怎么修改,知道的高手请指点。


7. 系统内核安全

FreeBSD有个比较强的功能,就是能够定义系统内核的安全等级,主要是为了防止内核后门专门定制的,能通过不同的等级限制对内核的访问和对防火墙等的修改。我们首先要开启系统的安全等级,然后设定安全等级,我们打开 /etc/rc.conf:
# ee /etc/rc.conf
加入下面的内容:
kern_securelevel_enable="YES"
kern_securelevel="-1"
第一句是打开安全等级,第二句是定义等级。它一共五个等级,下面说说不同之处。
* kern_securelevel -1:这是系统默认级别,没有提供任何内核的保护错误;
* kern_securelevel  0:基本上作用不多,当你的系统刚启动就是0级别的,当进入多用户模式的时候就自动变成1级了。
* kern_securelevel  1:在这个级别上,有如下几个限制:
a. 不能通过kldload或者kldunload加载或者卸载可加载内核模块;
b. 应用程序不能通过/dev/mem或者/dev/kmem直接写内存;
c. 不能直接往已经装在(mounted)的磁盘写东西,也就是不能格式化磁盘,但是可以通过标准的内核接口执行写操作;
d. 不能启动X-windows,同时不能使用chflags来修改文件属性;
* kern_securelevel  2:在 1 级别的基础上还不能写没装载的磁盘,而且不能在1秒之内制造多次警告,这个是防止DoS控制台的;
* kern_securelevel  3:在 2 级别的级别上不允许修改IPFW防火墙的规则。
如果你已经装了防火墙,并且把规则设好了,不轻易改动,那么建议使用3级别,如果你没有装防火墙,而且还准备装防火墙的话,不建议使用。我们这里推荐使用 2 级别,能够避免比较多对内核攻击。


8. 系统安全优化

一般优化系统主要是重新编译内核,去掉一些不要的驱动等等,你可以参考我在我Blog上写的关于编译内核的文章。我们这里对网络和内核一些选项进行优化和安全设置。编辑 /etc/sysctl.conf 文件,在里面加入如下内容:(有注释)

#最大的待发送TCP数据缓冲区空间
net.inet.tcp.sendspace=65536

#最大的接受TCP缓冲区空间
net.inet.tcp.recvspace=65536

#最大的接受UDP缓冲区大小
net.inet.udp.sendspace=65535

#最大的发送UDP数据缓冲区大小
net.inet.udp.maxdgram=65535

#本地套接字连接的数据发送空间
net.local.stream.sendspace=65535

#加快网络性能的协议
net.inet.tcp.rfc1323=1
net.inet.tcp.rfc1644=1
net.inet.tcp.rfc3042=1
net.inet.tcp.rfc3390=1

#最大的套接字缓冲区
kern.ipc.maxsockbuf=2097152

#系统中允许的最多文件数量
kern.maxfiles=65536

#每个进程能够同时打开的最大文件数量
kern.maxfilesperproc=32768

#当一台计算机发起TCP连接请求时,系统会回应ACK应答数据包。该选项设置是否延迟ACK应答数据包,把它和包含数据的数据包一起发送,在高速网络和低负载的情况下会略微提高性能,但在网络连接较差的时候,对方计算机得不到应答会持续发起连接请求,反而会降低性能。
net.inet.tcp.delayed_ack=0

#屏蔽ICMP重定向功能
net.inet.icmp.drop_redirect=1
net.inet.icmp.log_redirect=1
net.inet.ip.redirect=0
net.inet6.ip6.redirect=0

#防止ICMP广播风暴
net.inet.icmp.bmcastecho=0
net.inet.icmp.maskrepl=0

#限制系统发送ICMP速率
net.inet.icmp.icmplim=100

#安全参数,编译内核的时候加了options TCP_DROP_SYNFIN才可以用
net.inet.icmp.icmplim_output=0
net.inet.tcp.drop_synfin=1

#设置为1会帮助系统清除没有正常断开的TCP连接,这增加了一些网络带宽的使用,但是一些死掉的连接最终能被识别并清除。死的TCP连接是被拨号用户存取的系统的一个特别的问题,因为用户经常断开modem而不正确的关闭活动的连接
net.inet.tcp.always_keepalive=1

#若看到net.inet.ip.intr_queue_drops这个在增加,就要调大net.inet.ip.intr_queue_maxlen,为0最好
net.inet.ip.intr_queue_maxlen=1000

#防止DOS攻击,默认为30000
net.inet.tcp.msl=7500

#接收到一个已经关闭的端口发来的所有包,直接drop,如果设置为1则是只针对TCP包
net.inet.tcp.blackhole=2

#接收到一个已经关闭的端口发来的所有UDP包直接drop
net.inet.udp.blackhole=1

#为网络数据连接时提供缓冲
net.inet.tcp.inflight.enable=1

#如果打开的话每个目标地址一次转发成功以后它的数据都将被记录进路由表和arp数据表,节约路由的计算时间,但会需要大量的内核内存空间来保存路由表
net.inet.ip.fastforwarding=0

#kernel编译打开options POLLING功能,高负载情况下使用低负载不推荐SMP不能和polling一起用
#kern.polling.enable=1

#并发连接数,默认为128,推荐在1024-4096之间,数字越大占用内存也越大
kern.ipc.somaxconn=32768

#禁止用户查看其他用户的进程
security.bsd.see_other_uids=0

#设置kernel安全级别
kern.securelevel=0

#记录下任何TCP连接
net.inet.tcp.log_in_vain=1

#记录下任何UDP连接
net.inet.udp.log_in_vain=1

#防止不正确的udp包的攻击
net.inet.udp.checksum=1

#防止DOS攻击
net.inet.tcp.syncookies=1

#仅为线程提供物理内存支持,需要256兆以上内存
kern.ipc.shm_use_phys=1

# 线程可使用的最大共享内存
kern.ipc.shmmax=67108864

# 最大线程数量
kern.ipc.shmall=32768

# 程序崩溃时不记录
kern.coredump=0

# lo本地数据流接收和发送空间
net.local.stream.recvspace=65536
net.local.dgram.maxdgram=16384
net.local.dgram.recvspace=65536

# 数据包数据段大小,ADSL为1452。
net.inet.tcp.mssdflt=1460

# 为网络数据连接时提供缓冲
net.inet.tcp.inflight_enable=1

# 数据包数据段最小值,ADSL为1452
net.inet.tcp.minmss=1460

# 本地数据最大数量
net.inet.raw.maxdgram=65536

# 本地数据流接收空间
net.inet.raw.recvspace=65536

#ipfw防火墙动态规则数量,默认为4096,增大该值可以防止某些病毒发送大量TCP连接,导致不能建立正常连接
net.inet.ip.fw.dyn_max=65535

#设置ipf防火墙TCP连接空闲保留时间,默认8640000(120小时)
net.inet.ipf.fr_tcpidletimeout=864000



三、 服务程序的安全设置

到这里就是本文的重点所在了,我们将花费比较多的文字进行描述,当然,所以描述不一定是非常正确的,也希望能够对你有一些帮助。我们系统默认是运行了包括Apache、Mysql、vsFTPd,SSH等服务,我们以下进行一一讲解。


1. Apache的安全设置

Apache的核心设置就是在 httpd.conf 里面,我们安装的Apache的目录是在 /usr/local/apache2/ 下,那么我们的配置文件就是在 /usr/local/apache2/conf/httpd.conf ,如果你是使用ports等安装的,配置文件应该是在/etc或/usr/local/etc目录下。使用ee或者vi打开配置文件:
# ee /usr/local/apache2/conf/httpd.conf
下面我们就要进行比较多的安全设置了,基本的服务、端口、主目录等等设置就不说了,只讲与安全有关的设置。

(1)指定运行Apache服务的用户和组
这是比较重要的,因为权限是继承的,如果运行Apache服务的用户权限太高,那么很可能使得入侵者通过WebShell等就会对系统构成严重威胁。一般我们运行Apache的是nobody用户和nobody组。在httpd.conf的250-275行之间找到User和Group选项,比如我们默认设置如下(去掉了注释信息):
<IfModule !mpm_winnt.c>
<IfModule !mpm_netware.c>
User nobody
Group #-1
</IfModule>
</IfModule>

(2) Apache的日志文件
Apache的日志文件是非常重要的,可以发现apache的运行状况和访问情况,对于判断入侵等有重要帮助。它的默认选项是:
# 错误日志存放目录,默认是存放在apache安装目录的logs下
ErrorLog logs/error_log
# 日志记录的级别,级别有debug, info, notice, warn, error, crit等,默认是“warn”级别
LogLevel warn
# 访问日志记录的格式,每一种格式都有不同的内容,根据你的需要进行定制,以获取最多访问信息
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
# 使用上面格式的那一种,默认是使用common
CustomLog logs/access_log common

文件格式预定义的格式内容:
%a 远程用户IP
%A 本地httpd服务器的ip
%f 传送的文件名
%h 远程主机
%m 请求方式
%l identd给出的远程名
%p 连接的httpd端口号
%P 请求的httpd进程
%t 时间
%T 服务请求时间
你可以定制自己的日志格式,然后通过CustomLog logs/access_log common来进行调用。

注意,日志文件是由运行Apache的用户进行打开的,要注意该文件的安全,防止被黑客改写或者删除。

(3) Apache服务信息显示控制
在配置文件中有个选项是控制是否显示apache版本信息、主机名称、端口、支持的cgi等信息的:
ServerSignature On
默认为On,那么将显示所有信息:
我故意访问一个不存在的文件:http://www.target.com/404.html
那么就会在给的错误提示中显示如下信息:
Apache/2.0.53 (Unix) PHP/4.3.11 Server at target.com Port 80

所有Apache和PHP的信息暴露无遗,这是很不安全的。当然同时还有Off和EMail选项,Off将不显示任何信息,EMail将显示管理员的邮箱地址,建议设为Off或者EMail,这样能够避免泄漏Apache服务器的信息给黑客。

(4) 目录浏览
在httpd.conf中可以设置apache能够对一些没有索引文件的网页目录进行目录浏览:
<Directory />
   Options Indexes FollowSymLinks
   AllowOverride None
</Directory>
这是不合适也不安全的,建议不需要目录浏览:
<Directory />
   Options FollowSymLinks
   AllowOverride None
</Directory>

(5) 用户主页
设置httpd.conf中的:
UserDir public_html
能够使得每个使用系统的用户在自己的主目录下建立 public_html 目录后就能够把自己的网页放进该目录,然后通过:
http://www.target.com/~用户名/网页 就能够显示自己的网页,这是不安全的,而且对于我们服务器来讲,这没有必要,所以我们直接关闭该功能:
UserDir disabled
或者把该内容改名,改成 一个黑客比较不容易猜到的文件名,比如:
UserDir webserver_public_htmlpath
也可以只允许部分用户具有该功能:
UserDir enabled user1 user2 user3

(6) CGI执行目录
如果你的apache要执行一些perl等cgi程序,那么就要设置一下选项:
ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/"
但是这也给了黑客利用一些不安全的cgi程序来进行破坏,所以如果你不需要cgi的话,建议关闭该选项:
#ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/"

(7) 控制PHP脚本只能访问指定目录
在httpd.conf添加如下内容:
php_admin_value open_basedir /usr/www
后面的路径是你需要PHP脚本能够访问的目录,如果PHP脚本想要访问其他目录将出项错误提示。

(icon_cool.gif 目录访问控制 (未完)
这项内容最复杂,同时涉及的东西也比较多,我只能简单说一下,不清楚请参考其他文章。
比如下面的内容:
<Directory />
   Options FollowSymLinks
   AllowOverride None
</Directory>
就是允许访问每一个目录,里面设置的是允许执行的动作,一般包含的动作有:Options、AllowOverride、Order、Allow、Deny。
Options是只对指定目录及其子目录能够执行的操作,Indexes、Includes、FollowSymLinks、ExecCGI、MultiViews、None、All等操作。
AllowOverride是指定目录访问的权限,当然也可以通过 AccessFileName文件指定的 .htaccess 来控制。它的操作有:None、All、Options、FileInfo、AuthConfit、Limit等。
Order、Allow、Deny三个指令必须配合来控制目录访问权限。Order指定检查次序的规则,比如Order Allow, Deny,表示先按Allow检查,如果不匹配再按Deny进行检查。Order Deny, Allow ,表示先按Deny规则检查,如果不满足条件,再按Allow进行检查。

控制目录访问权限的文件
默认在Unix平台下能够使用 .htaccess 来对目录权限进行规则定义,但是这是不安全的,建议关闭,默认的选项:
AccessFileName .htaccess
建议设成:
#AccessFileName .htaccess
全部目录权限定义使用httpd.conf中的定义,不使用 .htaccess。

(9) 用户访问认证
这个技术非常重要,能够控制一些非法用户访问本内容。假设我们的网站:
http://www.target.com/admin 是我们的后台管理目录,我不允许一些非法用户进行访问,那么我就必须设定对该目录访问是需要验证的。
先在httpd.conf中加入要进行访问认证的目录:
<Directory "/usr/www/admin">
authtype basic
authname "Private"
authuserfile /usr/local/apache/bin/admin.dat
require user login_user
Options Indexes FollowSymlinks MultiViews
AllowOverride None
</Directory>
上面我们就设置了我们的 /usr/www/admin目录是必须进行认证才能访问的,接着我们设置访问密码:
# /usr/local/apahche/bin/htpasswd -c /usr/local/apache/bin/admin.dat login_name
New password: *****
Re-type new password: *****
Adding password for user login_name

那么下次任何用户访问http://www.target.com/admin目录的时候就需要输入用户名login_name和你设置的密码。


2. PHP安全设置

PHP本身再老版本有一些问题,比如在 php4.3.10和php5.0.3以前有一些比较严重的bug,所以推荐使用新版。另外,目前闹的轰轰烈烈的SQL Injection也是在PHP上有很多利用方式,所以要保证安全,PHP代码编写是一方面,PHP的配置更是非常关键。
我们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们最主要就是要配置php.ini中的内容,让我们执行php能够更安全。
整个PHP中的安全设置主要是为了防止phpshell和SQL Injection的攻击,一下我们慢慢探讨。我们先使用任何编辑工具打开/etc/local/apache2/conf/php.ini,如果你是采用其他方式安装,配置文件可能不在该目录。

(1) 打开php的安全模式
php的安全模式是个非常重要的内嵌的安全机制,能够控制一些php中的函数,比如system(),同时把很多文件操作函数进行了权限控制,也不允许对某些关键文件的文件,比如/etc/passwd,但是默认的php.ini是没有打开安全模式的,我们把它打开:
safe_mode = on

(2) 用户组安全
当safe_mode打开时,safe_mode_gid被关闭,那么php脚本能够对文件进行访问,而且相同组的用户也能够对文件进行访问。
建议设置为:
safe_mode_gid = off
如果不进行设置,可能我们无法对我们服务器网站目录下的文件进行操作了,比如我们需要对文件进行操作的时候。

(3) 安全模式下执行程序主目录
如果安全模式打开了,但是却是要执行某些程序的时候,可以指定要执行程序的主目录:
safe_mode_exec_dir = /usr/bin
一般情况下是不需要执行什么程序的,所以推荐不要执行系统程序目录,可以指向一个目录,然后把需要执行的程序拷贝过去,比如:
safe_mode_exec_dir = /tmp/cmd
但是,我更推荐不要执行任何程序,那么就可以指向我们网页目录:
safe_mode_exec_dir = /usr/www

(4) 安全模式下包含文件
如果要在安全模式下包含某些公共文件,那么就修改一下选项:
safe_mode_include_dir = /usr/www/include/
其实一般php脚本中包含文件都是在程序自己已经写好了,这个可以根据具体需要设置。

(5) 控制php脚本能访问的目录
使用open_basedir选项能够控制PHP脚本只能访问指定的目录,这样能够避免PHP脚本访问/etc/passwd等文件,一定程度上限制了phpshell的危害,我们一般可以设置为只能访问网站目录:
open_basedir = /usr/www

(6) 关闭危险函数
如果打开了安全模式,那么函数禁止是可以不需要的,但是我们为了安全还是考虑进去。比如,我们觉得不希望执行包括system()等在那的能够执行命令的php函数,或者能够查看php信息的phpinfo()等函数,那么我们就可以禁止它们:
disable_functions = system,passthru,exec,shell_exec,popen,phpinfo
如果你要禁止任何文件和目录的操作,那么可以关闭很多文件操作
disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir,rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown
以上只是列了部分不叫常用的文件处理函数,你也可以把上面执行命令函数和这个函数结合,就能够抵制大部分的phpshell了。

(7) 关闭PHP版本信息在http头中的泄漏
我们为了防止黑客获取服务器中php版本的信息,可以关闭该信息斜路在http头中:
expose_php = Off
比如黑客在 telnet
www.target.com 80 的时候,那么将无法看到PHP的信息。

(icon_cool.gif 关闭注册全局变量
在PHP中提交的变量,包括使用POST或者GET提交的变量,都将自动注册为全局变量,能够直接访问,这是对服务器非常不安全的,所以我们不能让它注册为全局变量,就把注册全局变量选项关闭:
register_globals = Off
当然,如果这样设置了,那么获取对应变量的时候就要采用合理方式,比如获取GET提交的变量var,那么就要用$_GET['var']来进行获取,这个php程序员要注意。

(9) 打开magic_quotes_gpc来防止SQL注入
SQL注入是非常危险的问题,小则网站后台被入侵,重则整个服务器沦陷,所以一定要小心。php.ini中有一个设置:
magic_quotes_gpc = Off
这个默认是关闭的,如果它打开后将自动把用户提交对sql的查询进行转换,比如把 ' 转为 \'等,这对防止sql注射有重大作用。所以我们推荐设置为:
magic_quotes_gpc = On

(10) 错误信息控制
一般php在没有连接到数据库或者其他情况下会有提示错误,一般错误信息中会包含php脚本当前的路径信息或者查询的SQL语句等信息,这类信息提供给黑客后,是不安全的,所以一般服务器建议禁止错误提示:
display_errors = Off
如果你却是是要显示错误信息,一定要设置显示错误的级别,比如只显示警告以上的信息:
error_reporting = E_WARNING & E_ERROR
当然,我还是建议关闭错误提示。

(11) 错误日志
建议在关闭display_errors后能够把错误信息记录下来,便于查找服务器运行的原因:
log_errors = On
同时也要设置错误日志存放的目录,建议根apache的日志存在一起:
error_log = /usr/local/apache2/logs/php_error.log
注意:给文件必须允许apache用户的和组具有写的权限。


3. Mysql的安全设置

我们把Mysql安装在 /usr/local/mysql目录下,我们必须建立一个用户名为mysql,组为mysql的用户来运行我们的mysql,同时我们把它的配置文件拷贝到 /etc目录下:
# cp suport-files/my-medium.cnf /etc/my.cnf
chown root:sys /etc/my.cnf
chmod 644 /etc/my.cnf

使用用户mysql来启动我们的mysql:
# /usr/local/mysql/bin/mysqld_safe -user=mysql &

(1) 修改root用户的的口令
缺省安装的mysql是没有密码的,所以我们要修改,以防万一。下面采用三种方式来修改root的口令。

*  用mysqladmin命令来改root用户口令
# mysqladmin -uroot password test
这样,MySQL数据库root用户的口令就被改成test了。(test只是举例,我们实际使用的口令一定不能使用这种易猜的弱口令)

*  用set password修改口令:
mysql> set password for root@localhost=password('test');
这时root用户的口令就被改成test了。

*  直接修改user表的root用户口令    
mysql> use mysql;
mysql> update user set password=password('test') where user='root';
mysql> flush privileges;

这样,MySQL数据库root用户的口令也被改成test了。其中最后一句命令flush privileges的意思是强制刷新内存授权表,否则用的还是缓冲中的口令,这时非法用户还可以用root用户及空口令登陆,直到重启MySQL服务器。

(2) 删除默认的数据库和用户
我们的数据库是在本地,并且也只需要本地的php脚本对mysql进行读取,所以很多用户不需要。mysql初始化后会自动生成空用户和test库,这会对数据库构成威胁,我们全部删除。
我们使用mysql客户端程序连接到本地的mysql服务器后出现如下提示:
mysql> drop database test;
mysql> use mysql;
mysql> delete from db;
mysql> delete from user where not(host="localhost" and user="root");
mysql> flush privileges;

(3) 改变默认mysql管理员的名称
这个工作是可以选择的,根据个人习惯,因为默认的mysql的管理员名称是root,所以如果能够修改的话,能够防止一些脚本小子对系统的穷举。我们可以直接修改数据库,把root用户改为"admin"
mysql> use mysql;
mysql> update user set user="admin" where user="root";
mysql> flush privileges;

(4) 提高本地安全性
提高本地安全性,主要是防止mysql对本地文件的存取,比如黑客通过mysql把/etc/passwd获取了,会对系统构成威胁。mysql对本地文件的存取是通过SQL语句来实现,主要是通过Load DATA LOCAL INFILE来实现,我们能够通过禁用该功能来防止黑客通过SQL注射等获取系统核心文件。
禁用该功能必须在 my.cnf 的[mysqld]部分加上一个参数:
set-variable=local-infile=0

(5) 禁止远程连接mysql
因为我们的mysql只需要本地的php脚本进行连接,所以我们无需开socket进行监听,那么我们完全可以关闭监听的功能。
有两个方法实现:
* 配置my.cnf文件,在[mysqld]部分添加 skip-networking 参数
* mysqld服务器中参数中添加 --skip-networking 启动参数来使mysql不监听任何TCP/IP连接,增加安全性。如果要进行mysql的管理的话,可以在服务器本地安装一个phpMyadmin来进行管理。

(6) 控制数据库访问权限
对于使用php脚本来进行交互,最好建立一个用户只针对某个库有 update、select、delete、insert、drop table、create table等权限,这样就很好避免了数据库用户名和密码被黑客查看后最小损失。
比如下面我们创建一个数据库为db1,同时建立一个用户test1能够访问该数据库。
mysql> create database db1;
mysql> grant select,insert,update,delete,create,drop privileges on db1.* to test1@localhost identified by 'admindb';
以上SQL是创建一个数据库db1,同时增加了一个test1用户,口令是admindb,但是它只能从本地连接mysql,对db1库有select,insert,update,delete,create,drop操作权限。

(7) 限制一般用户浏览其他用户数据库
如果有多个数据库,每个数据库有一个用户,那么必须限制用户浏览其他数据库内容,可以在启动MySQL服务器时加--skip-show-database 启动参数就能够达到目的。

(icon_cool.gif 忘记mysql密码的解决办法
如果不慎忘记了MySQL的root密码,我们可以在启动MySQL服务器时加上参数--skip-grant-tables来跳过授权表的验证 (./safe_mysqld --skip-grant-tables &),这样我们就可以直接登陆MySQL服务器,然后再修改root用户的口令,重启MySQL就可以用新口令登陆了。

(9) 数据库文件的安全
我们默认的mysql是安装在/usr/local/mysql目录下的,那么对应的数据库文件就是在/usr/local/mysql/var目录下,那么我们要保证该目录不能让未经授权的用户访问后把数据库打包拷贝走了,所以要限制对该目录的访问。
我们修改该目录的所属用户和组是mysql,同时改变访问权限:
# chown -R mysql.mysql /usr/local/mysql/var
# chmod -R go-rwx /usr/local/mysql/var

(10) 删除历史记录
执行以上的命令会被shell记录在历史文件里,比如bash会写入用户目录的.bash_history文件,如果这些文件不慎被读,那么数据库的密码就会泄漏。用户登陆数据库后执行的SQL命令也会被MySQL记录在用户目录的.mysql_history文件里。如果数据库用户用SQL语句修改了数据库密码,也会因.mysql_history文件而泄漏。所以我们在shell登陆及备份的时候不要在-p后直接加密码,而是在提示后再输入数据库密码。
另外这两个文件我们也应该不让它记录我们的操作,以防万一。
# rm .bash_history .mysql_history
# ln -s /dev/null .bash_history
# ln -s /dev/null .mysql_history

(11) 其他
另外还可以考虑使用chroot等方式来控制mysql的运行目录,更好的控制权限,具体可以参考相关文章。


4. vsFTPd安全设置

vsFTPd是一款非常著名的ftp daemon程序,目前包括Redhat.com在内很多大公司都在使用,它是一款非常安全的程序,因为它的名字就叫:Very Secure FTP Daemon (非常安全的FTP服务器)。
vsftpd设置选项比较多,涉及方方面面,我们下面主要是针对安全方面进行设置。
目前我们的需求就是使用系统帐户同时也作为是我们的FTP帐户来进行我们文件的管理,目前假设我只需要一个帐户来更新我的网站,并且我不希望该帐户能够登陆我们的系统,比如我们的网站的目录是在/usr/www下面,那么我们新建一个用户ftp,它的主目录是/usr/www,并且它的shell是/usr/sbin/nologin,就是没有shell,防止该用户通过ssh等登陆到系统。

下面在进行系统详尽的设置,主要就是针对vsftpd的配置文件vsftpd.conf文件的配置。

(1) 禁止匿名用户访问, 我们不需要什么匿名用户,直接禁止掉:
anonymous_enable=NO

(2) 允许本地用户登陆,因为我们需要使用ftp用户来对我们网站进行管理:
local_enable=YES

(3) 只允许系统中的ftp用户或者某些指定的用户访问ftp,因为系统中帐户众多,不可能让谁都访问。
打开用户文件列表功能:
userlist_enable=YES
只允许用户文件列表中的用户访问ftp:
userlist_deny=NO
用户名文件列表路径:
userlist_file=/etc/vsftpd.user_list

然后在/etc下建立文件 vsftpd.user_list 文件,一行一个,把用户ftp加进去,同时也可以加上你允许访问的系统帐户名。

(4) 禁止某些用户登陆ftp:
pam_service_name=vsftpd
指出VSFTPD进行PAM认证时所使用的PAM配置文件名,默认值是vsftpd,默认PAM配置文件是/etc/pam.d/vsftpd。

/etc/vsftpd.ftpusers
VSFTPD禁止列在此文件中的用户登录FTP服务器,用户名是一行一个。这个机制是在/etc/pam.d/vsftpd中默认设置的。

这个功能和(3)里的功能有点类似,他们俩能结合使用,那样就最好了。

(5) 把本地用户锁定在自己的主目录,防止转到其他目录,比如把/etc/passwd给下载了:
chroot_local_users=NO
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list
然后在/etc下建立vsftpd.chroot_list文件,里面把我们要限制的本地帐户加进去,一行一个,我们加上ftp,防止它登陆到系统。

(6) 隐藏文件真实的所有用户和组信息,防止黑客拿下ftp后查看更多系统用户信息:
hide_ids=YES

(7) 取消ls -R命令,节省资源,因为使用该命令,在文件列表很多的时候将浪费大量系统资源:
ls_recurse_enable=NO

(icon_cool.gif 上传文件的默认权限,设置为022:
local_umask=022
如果要覆盖删除等,还要打开:
write_enable=YES

(9) ftp的banner信息,为了防止黑客获取更多服务器的信息,设置该项:
ftpd_banner=banner string
把后面的banner string设为你需要的banner提示信息,为了安全,建议不要暴露关于vsFTPd的任何信息。
另外,如果你的信息比较多的话,可以设置为提示信息是读取一个文件中的信息:
banner_file=/directory/vsftpd_banner_file

(10) 打开日志功能:
xferlog_enable=YES
同时设置日志的目录:
xferlog_file=/var/log/vsftpd.log
启用详细的日志记录格式:
xferlog_enable=YES

(11) 如果打开虚用户功能等,那么建议关闭本地用户登陆:
local_enable=NO


vsFTPd还有很多安全设置,毕竟人家的名字就是:Very Secure FTP Daemon,反正它的溢出漏洞什么的是很少的,如果要更安全,建议按照自己的需要设置vsftpd,设置的好,它绝对是最安全的。


5. SSH安全设置

SSH是一个基于SSL的安全连接远程管理的服务程序,主要出现就是为了解决telnet、rlogin、rsh等程序在程序交互过程中存在明文传输易被监听的问题而产生的,目前基本上是推荐使用ssh来代替telnet、rlogin、rsh等远程管理服务。
ssh能够直接在windows平台下通过Secure SSH Client等客户端工具进行连接管理,目前最流行的服务器端就是OpenSSH程序,目前最新版本是OpenSSH4.0版,详细可以参考www.openssh.com网站。
OpenSSH在FreeBSD下已经集成安装了,FreeBSD5.3下的OpenSSH版本是3.8.1,建议ports升级到4.0。


主要的安全配置文件是/etc/ssh/sshd_config文件,我们编辑该文件。

(1) 使用protocol 2代替protocol 1,SSH2更加安全,可以防止攻击者通过修改携带的版本banner来劫持(hijacking)启动会话进程并降低到protocol 1。注释掉protocol 2,1 改用下面语句代替:
protocol 2

(2) 合理设置最大连接数量, 防止DOS攻击

  MaxStartups 5:50:10

(3)关闭X11forwording ,防止会话劫持

  X11Forwarding no

(4)建议不使用静态密码,而使用DSA 或RSA KEY,修改如下内容可以关闭使用密码认证:

  PasswordAuthentication no

(5)可以限制某个组或光是单个用户访问shell

  AllowGroups wheel
或者
  AllowUsers heiyeluren

(6) 限制root用户登陆,主要是为了防止暴力破解

   PermitRootLogin no

(7) 不允许口令为空的用户登陆
   
   PermitEmptyPasswords no

(icon_cool.gif使用TCP wrappers来限制一些访问,修改/etc/hosts.allow文件,注释掉"ALL : ALL : allow",增加如下内容:

  sshd:localhost:allow
  sshd:friendlcomputer:allow
  sshd:all : deny

  #相关命令:
  #chsh -s /sbin/nologin user


四、防火墙的安装和设置

FreeBSD自带有一个基于包过滤的防火墙--ipfw,虽然功能没有专业防火墙那么强大,但是应付一个Web站点的安全还是足够的,所以我们决定选用该防火墙来保护我们的Web服务器。


1. 安装ipfw

IPFW 的主要部分是在内核中运行的, 因此会需要在FreeBSD内核配置文件中添加部分选项。(注意,如果你没有安装FreeBSD核心源代码,是无法进入以下目录的,所以运行之前一定要先安装内核源代码)我们先进入内核配置文件:
# cd /sys/i386/conf
# cp GENERIC ./kernel_fw

打开内核配置文件:
# ee ./kernel_fw

添加四个选项,不需要后面的注释信息:
options IPFIREWALL # 将包过滤部分的代码编译进内核。
options IPFIREWALL_VERBOSE
# 启用通过syslogd记录的日志。如果没有指定这个选项,即使您在过滤规则中指定记录包, 也不会真的记录它们
options IPFIREWALL_VERBOSE_LIMIT=10
# 限制通过 syslogd(icon_cool.gif 记录的每项包规则的记录条数。在恶劣的环境中如果您想记录防火墙的活动, 而又不想由于 syslog 洪水一般的记录而导致拒绝服务攻击, 那么这个选项将会很有用。
options IPFIREWALL_DEFAULT_TO_ACCEPT
# 这将把默认的规则动作从 ``deny'' 改为 ``allow''。这可以防止在没有配置防火墙之前使用启用过 IPFIREWALL 支持的内核重启时把自己锁在外面。 另外, 如果您经常使用 ipfw(icon_cool.gif 来解决一些问题时它也非常有用。 尽管如此,在使用时应该小心, 因为这将使防火墙敞开, 并改变它的行为。


编译内核:
# /usr/sbin/config kernel_fw
# cd ../compile/kernel_fw (注意你的版本,如果是低于5.0的版本用../../compile/kernel_fw)
# make depend
# make
# make install

重启系统。注意,我们没有选择options IPFIREWALL_DEFAULT_TO_ACCEPT该选项,就是说默认系统启动后是打开防火墙的,并且防火墙默认是不允许任何连接的(deny from any to any),所以一定要在本地操作,否则你将被“锁在门外”,如果你选择了该选项则可以使用ssh等连接不受影响,不过这相对不安全。


2. 配置ipfw

如果配置普通情况下的规则,使用命令配置的模式:
ipfw的配置命令:ipfw [-N] 命令 [编号] 动作 [log(日志)] 协议 地址 [其它选项]
例如:
# ipfw add allow tcp from any to 10.10.10.1 80 #允许外界访问我的web服务
# ipfw add allow tcp from any to 10.10.10.1 21 #允许外面访问我的ftp服务
# ipfw add allow tcp from any to 10.10.10.1 22 #允许外界访问我的ssh服务

如果使用规则包的形式,那么查看下面内容。
系统启动后,我们还要配置rc.conf文件来运行我们的防火墙:
# ee /etc/rc.conf

加入如下内容:
gateway_enable="YES" # 启动网关
firewall_enable="YES" # 激活firewall防火墙
firewall_script="/etc/rc.firewall" # firewall防火墙的默认脚本
firewall_type="/etc/ipfw.conf" # firewall自定义脚本
firewall_quiet="NO" # 起用脚本时,是否显示规则信息。现在为“NO”假如你的防火墙脚本已经定型,那么就可以把这里设置成“YES”了。
firewall_logging_enable="YES" # 启用firewall的log记录。

设置完成后我们再编辑/etc/syslog.conf文件:
# ee /etc/syslog.conf
加入以下行:
!ipfw
*.*                 /var/log/ipfw.log

现在到了最重要的编辑规则包了:
# ee /etc/ipfw.conf
我们添加一下规则:(注意 10.10.10.1是我们服务器的IP)

######### TCP ##########
add 00001 deny log ip from any to any ipopt rr
add 00002 deny log ip from any to any ipopt ts
add 00003 deny log ip from any to any ipopt ssrr
add 00004 deny log ip from any to any ipopt lsrr
add 00005 deny tcp from any to any in tcpflags syn,fin
# 这5行是过滤各种扫描包

add 10001 allow tcp from any to 10.10.10.1 80 in  # 向整个Internet开放http服务。
add 10002 allow tcp from any to 10.10.10.1 21 in  # 向整个Internet开放ftp服务。
add 10000 allow tcp from 1.2.3.4 to 10.10.10.1 22 in
# 向Internet的xx.xx.xx.xx这个IP开放SSH服务。也就是只信任这个IP的SSH登陆。
# 如果你登陆服务器的IP不固定,那么就要设为:add 10000 allow tcp from any to 10.10.10.1 22 in

add 19997 check-state
add 19998 allow tcp from any to any out keep-state setup
add 19999 allow tcp from any to any out #这三个组合起来是允许内部网络访问出去,如果想服务器自己不和Internet进行tcp连接出去,可以把19997和19998去掉。(不影响Internet对服务器的访问)

########## UDP ##########
add 20001 allow udp from any 53 to 10.10.10.1 # 允许其他DNS服务器的信息进入该服务器,因为自己要进行DNS解析嘛~
add 29999 allow udp from any to any out # 允许自己的UDP包往外发送。

########## ICMP #########
add 30000 allow icmp from any to any icmptypes 3
add 30001 allow icmp from any to any icmptypes 4
add 30002 allow icmp from any to any icmptypes 8 out
add 30003 allow icmp from any to any icmptypes 0 in
add 30004 allow icmp from any to any icmptypes 11 in
#允许自己ping别人的服务器。也允许内部网络用router命令进行路由跟踪。



五、Unix/Linux上的后门技术和防范

对黑客来讲,入侵一个系统只是万里长征的开始,最主要的是长期占有一个肉鸡(傀儡机),所以,后门技术往往非常重要。对于我们来讲,总是处于被动的地位,百密一疏,总有没有做到位的地方,谁都不能保证自己的系统是绝对安全的,所以不能避免我们可能会被入侵。黑客入侵后肯定会留后门,当然,除了那些高手,境界非常高,入侵只是为了测试或者技术挑战,对于一般黑客来讲,入侵之后留个后门是很重要的,我们要防范,当然就要了解常用的后门技术,下面就简单的讲将在Unix/Linux系统中比较常见的后门技术。

1. 帐号后门

最普通和原始的后门技术,一般就是在系统中添加一个管理员帐户。
# echo "heiyeluren:*:0:0::/root:/bin/sh" >> /etc/passwd
# echo "heiyeluren::0:0::0:0::/root:/bin/sh" >> /etc/shadow
给系统增加一个 uid和gid都为0(root)的帐号,无口令。
FreeBSD的密码是存储在 /etc/master.passwd里面的,那么后面的命令就应该改成:
# echo "heiyeluren:::::::::" >> /etc/master.passwd
也可以使用程序来实现:
/* Add super user */
#include "stdio.h"
#define PASSWD_PATH "/etc/passwd"
#define SHADOW_PATH "/etc/master.passwd"
main()
{
FILE *fd;
fd = fopen(PASSWD_PATH, "a+");
fprintf(fd, "heiyeluren:*:0:0::/root:/bin/sh\n");
fclose(fd);
fd = fopen(SHADOW_PATH, "a+");
fprintf(fd, "heiyeluren::0:0::0:0::/root:/bin/sh\n");
fclose(fd);
}
# gcc -o adduser adduser.c
# ./adduser
这种方法比较傻,一般比较容易发现,特别是系统帐户不多的时候。也有的用户名起的比较迷惑人,比如起个r00t的用户名,uid和gid都是0,这样如果不注意,可能就会被蒙混过关了。

* 防范方法:
这种方法虽然比较容易发现,但是我们还是要防范,要多注意观察系统的帐户情况,本来我们系统帐户就不多,检查起来比较方便,另外也要注意那些比较少使用的帐户是不是被更改过,比如默认的帐户有bind,它的shell是 /usr/sbin/nologin,就是不能登陆的,但是黑客入侵后把它改了,比如改为/bin/csh,那么对方就能登陆了,但是你确不知道。所以最好办法是把/etc/passwd另外备份一份,不定期的检查,同时把/etc/passwd和/etc/master.passwd设为只有root才能查看。


2. shell后门

这个比较常用,也比较流行。一般就是把root执行的shell程序通过setuid的形式把shell程序拷贝到其他能够执行的地方,然后只要用小权限用户执行该shell就能够直接获取root权限。
比如:
# cp /bin/sh /tmp/.backdoor
# chown root:root /tmp/.backdoor
# chmod +s /tmp/.backdoor
这样只是把sh复制了,如果你喜欢其他shell,比如ksh、csh也可以,具体你看各个不同的操作系统而定。你就可以把那个加了s标记的shell程序放到任何目录,最好是深一点,不容易被人发现的地方,比如/usr/local/share/man之类的目录,然后你使用小权限用户登陆后执行该shell就可以了,比如我们上面复制的shell,我们只要用小权限用户登陆后执行:
$ /tmp/.backdoor
#
就可以了,当然,如何获得小权限用户,你可以使用暴力破解一些帐户,或者自己创建一个小权限的帐户。

* 防范方法:
首先给各个主要目录加上我们上面说的文件指纹校验,知道某个目录下有什么文件,如果多出了可疑文件可以仔细检查。还有使用find命令来查找有没有危险的root suid程序:
find / -type f (-perm -4000 -o -perm -2000 ) -print


3. Crontab服务后门

crontab命令就相当于windows下的at命令,定期执行某些任务。对黑客来讲,比如定期建立一个帐户,然后过多久就删除,这样管理员永远看不到系统中有后门,这样是非常保险的。。

* 防范方法:
cron的服务默认是存储在 /var/spool/crontab/root目录下,定期检查cron服务,看是否有异常的任务在执行,或者如果你不使用cron的话,直接关闭掉它。


4. rhosts后门

Rhosts文件常常被黑客利用来制作后门,如果系统开了rlogin、rexec等r的服务,因为象rlogin这样的服务是基于rhosts文件里的主机名使用简单的认证方法,所以黑客只要将.rhosts文件设置成"++",那么就允许任何人从任何地方使用该用户名,无须口令登陆513端口的rlogin服务就行。而且r之类的服务没有日志能力,不容易被发现。
实现方法:
# echo "++" > /usr/heiyeluren/.rhosts
# rlogin -l heiyeluren localhost
这样就不需要任何密码,直接输入用户名heiyeluren就登陆到了系统。

* 防范办法:
不要使用rlogin等服务,同时也不推荐使用telnet等服务,因为telnetd等守护进程溢出漏洞一堆,而且在数据传输过程中是没有加密的,很容易被嗅探,建议使用ssh等经过安全加密的服务来替代。


5. Login后门

login程序通常用来对telnet来的用户进行口令验证. 入侵者获取login的原代码并修改使它在比较输入口令与存储口令时先检查后门口令. 如果用户敲入后门口令,它将忽视管理员设置的口令让你长驱直入。

* 防范方法:
一般针对这类后门,一般都是使用"string"命令搜索login程序中是否有中是否有密码等字符串来进行检查。如果密码经过加密,那么就对login文件进行指纹记录和MD5值的记录,觉得异常时进行检测。


6. Bind后门

就是通过常用的网络连接协议 TCP/UDP/ICMP 来建立连接的后门,这个在Windows下可是轰轰烈烈。
比较普遍的有TCP协议的后门都是写一段程序开一个指定的端口进行监听,然后从客户端进行连接后登陆系统。也有黑客为了隐蔽使用UDP协议来连接。icmp后门也常见,一般是。有时候可能bind后门跟服务后门结合,黑客通过自己写的bind后门来替换inetd中的服务。

* 防范方法:
经常使用netstat命令检查有没有非法的端口打开,最好直接用防火墙屏蔽除了正常访问的端口之外的端口。对于ping后门的话,直接在防火墙上禁止ping服务器


7. 服务后门

一般是替换或者添加服务来实现后门。比如在 /etc/inetd.conf 中添加或者替换某个服务来运行自己的后门程序,或者在某些服务中加入自己的后门代码。如果是替换服务的话,该服务必须不被使用,而且不容易发现。如果是自己添加的服务,那么必须在/etc/services中设置对应的服务和端口才能使用。

* 防范方法:
经常检查服务,最好备份 /etc/inetd.conf 、/etc/services等文件,同时在FreeBSD下也要时常检查 /usr/loca/etc/rc.d 下面的脚本是否是合法的并且是否那些脚本里面有没有启动非法程序。如果是在服务程序中添加自己的代码,那么就要对文件的指纹进行校验,比如md5值看是否匹配。


8. rootkit后门

rootkit后门一般是替换管理员使用的工具,比如ls、ps、netstat、who等常用文件,把那些程序替换成被黑客加了特殊代码的程序,那样就能达到控制的效果。而且现在已经有很多现成能下载使用的rootkit。

* 防范方法:
按照我们前面的方法,给每个文件建立系统指纹档案和md5校验值,如果觉得不对劲的时候查看文件指纹是否匹配,有没有别修改过,就知道是否着了rootkit的道。


9. 内核后门

通过加载内核模块的方式来加载后门,比较复杂。一般内核后门都是针对操作系统而言的,不同的操作系统内核模块设置编写方法都不一样,一般不通用。内核后门一般无法通过md5校验等来判断,所有基本比较难发现,目前针对内核后门比较多的是Linux和Solaris下。

* 防范方法:
FreeBSD下通过我们上面讲的设置内核安全等级来控制加载内核模块。


10. 其他后门
还有包括.forward等其他各类后门,另外很多后门可能是结合多种技术,比如把rootkit和内核后门结合在一起,实际过程中,黑克是会更难对付的。当然还有许多我们没有发现高手独门秘诀,这需要灵活检查,不过只要勤劳一点,安全会提升很多。



六、结束语

安全是一个整体,即使那么服务你设置的非常安全,但是不能保证永远安全,安全是动态的,必须不断的充实自己的知识,发现新漏洞、新技术。如果你需要更安全的系统,一定要自己有时常能够手工作入侵检测或者使用部分工具帮助你进行入侵检测。同时推荐你安装一些网络入侵检测系统(NIDS),比如Snort。
我想这个题目真的有点大了,开始写的时候没有那种感觉,越做到后来越觉得想要说的很多,最后只能泛泛而谈了一下,虽然如此,也希望能够给在使用FreeBSD的网管和网络安全爱好者一点点的帮助,那就足够了。

感谢所有致力于开源世界安全研究和管理并且愿意共享自己学习心得的朋友!

最后谢谢你能够耐心阅读本文。


(声明:本人也是初学者,文章不当之处,敬请指出,同时本文参考了很多高手的文章,有些不能一一注明,敬请谅解。)


附录(本文参考资料)

* 《黑客防线》2004年6月 《细心构造安全的PHP系统》(作者:单长虹)
* 《黑客防线》2004年5月 《一步一步加强Mysql的安全》(作者:单长虹)
* 《黑客防线》2004年5月 《文件系统安全巧设置》(作者:小华健)
* 《黑客防线》2004年1月 《知己知彼,方能百战不殆-Apache安全设定面面观》(作者:老牛)
* 《黑客防线》2003年11月《打造免费的分布式入侵检测系统》(作者:王雪冰)
* 《安全焦点》文档精华  《利用FreeBSD组建安全的网关》(作者:iceblood)
* 《安全焦点》文档精华  《MySQL数据库安全配置》(作者:san)
* 《安全焦点》文档精华  《PHP安全配置》(作者:san)
* 《安全焦点》文档精华  《一些FreeBSD相关的安全问题》(作者:xundi)
* 《安全焦点》文档精华  《FreeBSD系统优化部分内核参数调整中文注释》(作者:iceblood)
* 《FreeBSD系统安装及安全调整》(作者:xundi)
* 《详谈 vsftpd 的设置 》(作者:未知)
* 《Linux系统中OpenSSH的安装和配置》(LinuxAid.com.cn网站技术文档)
* 《如何创建后门》(作者:未知)

posted @ 2005-07-04 16:47 qwqg 阅读(210) | 评论 (0)编辑 收藏

FreeBSD的技巧

查看服务器的80端口的连接数
netstat -nat|grep -i "80"|wc -l

用下面命令察看哪些服务在运行
netstat -na --ip
netstat -na |grep LIST
lsof -i:端口

查看软件安装的位置
 pkg_info –L *** | less

查看这个软件的具体信息
 pkg_info ***

安装lsof程序时需要
install  /quark/qwqg/lsof_4.59/lsof /usr/sbin/lsof
source /root/.cshrc

将man 命令的输入结果导入到TXT文件中
man | col -b > file.txt

在bge0网卡上增加ip别名:
ifconfig bge0 add alias 192.168.64.80  netmask 255.255.255.255 up 

在bge0网卡上删除ip别名:
ifconfig bge0 -alias 192.168.64.80

说明:这里掩码的设定是这样的,同一个网段的第一个ip掩码按照真实的掩码设置。在这个网段下面再增加ip时,掩码就是255.255.255.255了

查看多少个独立IP访问网站
netstat -an |grep tcp |awk '{print $5}' |awk -F: '{print $1}' |sort |uniq |wc -l

下面命令可以分别计算当前目录下的文件和目录个数:
ll * |grep "^-"|wc -l ----- to count files
ll * |grep "^d"|wc -l ----- to count dir

只列子目录
ll -F | grep /$

在当前目录下搜索文件内带system的关键字
grep -r system *

在vi中替换字符的命令:
:g/abc/s//def/

如何从一个大tgz包中解压出某个文件
gunzip -dc file.tar.gz | tar tf -
可以看包里面的文件
然后用
gunzip -dc file.tar.gz | tar xf - file1 file2
其中file1 file2是你要解出来的文件。这个方法因为用的是stdout和pipe, 不需要占用多少的临时磁盘空间。

在系统上查看用户php程序执行时间长短;正常执行时间为0.1s
date ; php -f index.php date

posted @ 2005-07-04 12:52 qwqg 阅读(250) | 评论 (0)编辑 收藏

2005年7月1日 #

FreeBSD数据迁移

相信一些朋友也曾经想过如何快捷安全迁移数据,迁移数据可能有多种原因,一种是想增加一块硬盘,把原来一些空间不够的分区迁移过来;另一种是硬盘复制,旧的硬盘容量可能太小了,又或者已经出现了问题,想用新的硬盘代替。葱头就分别举例说明怎样迁移数据,具体方法可能和你的硬盘的实际情况有所不同,这里只是作一个指引。


无论是那种方法,都必须先将新硬盘装上并让系统正确识别。为了不用设硬盘跳线(硬盘缺省为Master),这里举例安装一个新的IDE硬盘到IDE1接口,即与旧硬盘使用不同的数据线,系统识别为ad2;如果你想和旧硬盘接在同一数据线线上,即IDE0接口,则必须将跳线设为client,系统识别为ad1。
1、关机,将新硬盘装上,重新开机。
2、开机后查看是否系统是否已经识别到新硬盘了:

hpserver# dmesg | grep ad2
成功的话会显示
ad2: 9765MB [19841/16/63] at ata1-master UDMA33
等信息,否则你要检查是否接错线,或者硬件兼容问题。

新硬盘已经安装成功,下面举例说一下两种数据迁移的方法。

一、增加一个硬盘,将原来硬盘/var数据转移到新硬盘

在系统已经建立之后,FreeBSD不能像PQMagic那样自由调整分区空间而不破坏分区数据,所以,如果/var空间已经不够,需要增加一块硬盘增加空间,原来的数据也必须迁移过来。
2、对新硬盘进行分区
可以使用sysinstall或者命令行方式分区。虽然fdisk有更多灵活性,但我建议还是采用sysinstall较好。分区完之后再用sysinstall里面的Label建立文件系统相关文件系统。
3、将文件系统挂载到/mnt

hpserver# mount /dev/ad1s1e /mnt
4、将数据迁移,这里也有两种方法,一种是使用tar,另一种是使用dump,我分别介绍,大家可以根据需要而选择备份方式。
(1) 使用tar备份并还原数据。
hpserver# cd /var
hpserver# tar cf - * | (cd /mnt; tar xf -)

(2) 使用dump备份并用restore还原数据。就我个人而言,我推荐使用这种方法,因为我曾经试过用tar备份var目录的时候,出现了错误并自动停止,我分析了一下原因,一些正在使用的文件或者临时文件可能不能备份,但dump不是以文件为单位,而是而block为单位的,应该不存在这样的情况,所以这是我推荐使用dump和restore的原因。

hpserver# cd /mnt
hpserver# dump -f- /var | restore -f- -r
在过程中和结束会出现类似以下信息:
DUMP: Date of this level 0 dump: Wed Jan 14 23:44:35 2004
DUMP: Date of last level 0 dump: the epoch
DUMP: Dumping /dev/ad0s1e (/var) to standard output
DUMP: mapping (Pass I) [regular files]
DUMP: mapping (Pass II) [directories]
DUMP: estimated 305 tape blocks.
DUMP: dumping (Pass III) [directories]
DUMP: dumping (Pass IV) [regular files]
DUMP: DUMP: 361 tape blocks
DUMP: finished in less than a second
DUMP: DUMP IS DONE

5、有一点提醒的是,你要确保备份后没有数据写入原来的/var,否则,这些数据没有备份到新分区中。结束后别忘了检查一下结果,并卸载/mnt。

hpserver# ls /mnt
hpserver# umount /mnt
6、编辑/etc/fstab文件,将原来指向/var的文件系统改为/dev/ad1s1e,重新启动就可生效。

二、硬盘复制

如果旧的系统盘出现了一些毛病,或者容量不够,你想更换一个新硬盘,那可以把旧硬盘数据复制到新硬盘,然后把旧硬盘摘下。按照上面的步骤,我们假定已经将硬盘安装好。
这里有一个小tips,就是先记下旧硬盘文件系统所对应的mount点,新硬盘分区次序按照旧的一样,这样免去我们下面容易混淆的步骤,我们查看/etc/fstab对照就知道了。不然搞了几下,自己都忘记了ad2s1e到底是用来挂载那个目录的。
1、使用sysinstall把新硬盘分区,设置好MBR,并一一对照原来的次序创建文件系统,假设原来的文件系统/dev/ad0s1g 对应/usr,那你新硬盘/dev/ad2s1g就用来做/usr,原来的文件系统/dev/ad0s1e 对应/var,那你新硬盘/dev/ad2s1e就用来做/var。按M分别清空所有文件系统的mount点,因为我们还没有建立临时的mount的目录,不清空会和系统原来的mount冲突的。

2、创建临时的目录用来作临时mount点并挂载这些文件系统。

hpserver# cd /mnt
hpserver# mkdir root
hpserver# mkdir usr
hpserver# mkdir var
用cat /etc/fstab查看原来的文件系统的对应关系,我们只要看最后面的一个字母就可以了,这样避免我们忘记了什么对应什么,这就是我刚才为什么让新硬盘的文件系统的名称对应以前的原因。
hpserver# mount /dev/ad2s1a /mnt/root
hpserver# mount /dev/ad2s1g /mnt/usr
hpserver# mount /dev/ad2s1e /mnt/var

3、复制硬盘最好用dump,尽量不用tar,因为你备份根分区的时候,如果不加参数排除一些目录,它会把全部东西备份到你新的分区的,这肯定不是我们想看到的。

hpserver# cd /mnt/root
hpserver# dump -f- / | restore -f- -r
hpserver# cd /mnt/var
hpserver# dump -f- /var | restore -f- -r
hpserver# cd /mnt/usr
hpserver# dump -f- /usr | restore -f- -r

4、到这里为止,数据备份和还原已经结束,检查一下有没有错漏,然后分别umount这些分区。

hpserver# umount /mnt/root
hpserver# umount /mnt/usr
hpserver# umount /mnt/var

5、最后,关机,摘掉原来的硬盘,把新硬盘挂到旧硬盘原来的位置,这步不要省略了,如果你不换位置,系统还是认为新硬盘是ad2,由于你的/etc/fstab里面是对应ad0的,所以启动会找不到/usr和/var等文件系统。启动看看,如果没有什么异常,那恭喜你,数据迁移已经成功,否则,请再看看有什么操作错误或者忘记做哪一步了。无论怎样,都别那么着急把旧硬盘内容清空,最好让新的系统运行几天观察有什么异常再动手。

切记,数据迁移的是一件比较危险的事情,操作过程中不能有差错,否则可能导致你原来的数据丢失,所以必须非常谨慎。

:任何转载或摘抄请保留作者信息和注明文章出处(中文FreeBSD用户组 http://www.cnfug.org)

posted @ 2005-07-01 16:53 qwqg 阅读(242) | 评论 (0)编辑 收藏

仅列出标题