|
|
发布日期:2001-11-274 }6 j( C* d7 i* ~! o
文章内容:
/ l" h1 }+ ~" t' B--------------------------------------------------------------------------------- t" ~2 C/ m' {. y
9 S. M7 L: D7 x作者:san(小许) san@nsfocus.com $ o. e; U4 M/ o- l! x& q
/ V. r9 ^/ F- a( M$ _. t7 v0 W
--------------------------------------------------------------------------------0 D, I2 C4 y5 f7 {
: T3 ?" Y* k. i" M* d
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以
6 o: }. `4 C$ k$ F( K及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配
# w& v' G1 O K' j置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的; [ b7 b R, h
过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的
1 c7 V( N6 i6 [; P8 Y/ q7 Z' {. Bphpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现& f0 K/ G8 O; |' I& S
在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题+ z5 S: D1 h) r2 F& g& D7 y' [
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 6 Z8 O* e- E: ] N( W
: \4 b( [ l) D3 f$ _# X5 n& s- w; X; ^* K" K) K5 g6 p
1、编译的时候注意补上已知的漏洞 / s' I; G* ? N& a1 k/ t' o
1 w5 k8 J4 D2 j: D% m从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突$ |0 ], p. ^& R' e! \- V
破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源
y5 B+ a; N* r( D+ }& u- q* f码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件" {% `% Y/ ^- ?( S1 E9 a, U
的第152行,也就是下面这行:
2 W- Y: ~1 L3 ]4 i( ?( b. m. T3 e( K2 h
if (extra_cmd != NULL) {
8 z) D$ S$ L9 Z" P, j: U% H# W) t
6 \, ]- ?- q/ H; [2 P, P2 d7 {后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php
4 s8 h' U+ K4 x那么我们就修补了这个漏洞。
, p9 @. P" Z0 }* \2 Q3 d, D6 G B/ n) q. ^# c: I/ B! C4 P
/ r, h# `* H* b& d/ ~& [
2、修改php.ini配置文件
@4 f x- Y2 G. Z0 W! i. b% R4 m
U" `! ^. j/ R% Q1 ] N. S9 G以php发行版的php.ini-dist为蓝本进行修改。
: H' w+ v4 F; a1 S' C5 J7 u
! X5 N4 V$ k; C/ Q K# s5 f# P: ~" d1)Error handling and logging
) K& L6 ^6 P V/ a' ~在Error handling and logging部分可以做一些设定。先找到:
! L. G- u% V# Gdisplay_errors = On
. u1 M: ~/ J% z+ V/ E8 C8 A& i8 y1 f5 B& h
php缺省是打开错误信息显示的,我们把它改为:
) L. z% U3 k' E* t' q# u6 }' X+ p( l5 S
display_errors = Off
7 C) q5 M" Q1 x$ [' t& I3 e, [0 q8 u5 v
关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻6 ^1 R q& \. Z
击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造+ p1 O( l* \6 B( B+ D; N# v
成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以: D7 j8 K6 C: v- `0 H% {8 B! r
下:
: ~. @. e7 F }. W* \7 L
5 K. d( G- ~% O6 { ]log_errors = Off
" [- y! M- }- ]. y4 l
: t2 V+ N8 ^7 N- w6 B* d% _: @改为:
4 N7 g8 P# ?" ^$ q" V. tlog_errors = On . H" m5 t* ~: L
/ e- E6 n6 \* `6 ^
以及指定文件,找到下面这行: + g N- Y& E/ N( I, x+ R8 y8 _
' c& u$ |. L$ \$ k+ |;error_log = filename
, U' \3 U" R9 k2 e! c' H& D$ G: Z' ^8 C) {7 I+ p
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
' I& o2 x' {7 U' C* [. ~: G% h1 L2 Y1 H$ b# Y/ a
error_log = /usr/local/apache/logs/php_error.log 1 S/ d: G E6 F0 j [
' C: F5 c$ ~ f* c% H& b+ ?这样所有的错误都会写到php_error.log文件里。
6 g8 W* P8 {" R7 a6 ]% K: r* U4 ]( G) Z- F; s+ u1 i' a. C6 ]/ a
2)Safe Mode
0 p$ F2 x Z9 i3 B9 a* k9 q4 |
9 W) a4 t9 G; L1 jphp的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在
6 [3 b8 v7 b; ]5 m- u. O \Safe Mode部分找到:
9 W; M3 ^. k0 p
7 O' K( i; N. {# O0 asafe_mode = Off ! {) M9 b' ^: K# b7 k+ V
; b# ]: C' S d5 t
改为:
& W+ }) M% J) r: ^. E* P, a
Z* \& t7 ?" [) X& A* [; H$ R2 Hsafe_mode = On
& J& B; h& N) y6 s1 l T
' @8 x' |3 e y/ c. d8 Q这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它" K+ X8 Q, I( y( @. t, q
的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行; N% T) r* }" x: t; R0 T. U. K
safe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下: % C; R, k. Q2 \4 j! E ~/ V$ b
% S4 B" m: U6 ~3 z' r* r2 e5 V8 d
safe_mode_exec_dir = ! ?1 F) q8 ? E* K
* W+ }; \9 _2 X& A& }5 L
指定要执行的程序的路径,如:
) G! l& u2 a2 D" y v1 J2 S8 ?$ r! H: l; K7 j5 B! O$ P I: ~
safe_mode_exec_dir = /usr/local/php/exec b4 E/ t4 f$ K; h5 k& `
, p- H0 r/ [; O O3 f- Q然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行
7 Y# ~1 s' ~' X+ I+ H该目录里的程序。 % B2 _' N6 W( Z. E9 a
: r: y% R* T3 B+ Z
关于安全模式下受限函数的详细信息请查看php主站的说明: 6 R" |9 {* E& X, U+ b4 H, ~/ i& E. Z
http://www.php.net/manual/en/features.safe-mode.php % F; R" p8 K% w ?: I j
$ P5 n; d: D- Q( Q1 Z$ n3)disable_functions ' m' z+ ]& e# b( Z1 J9 b1 e+ t2 x. L" z
6 Z& D6 f8 {$ Z# U: X- Z$ S如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这: o( F3 `- e' @. {
行:
% j2 U0 r3 H/ w7 ~0 U! k( D$ t. _
% X# Y8 c( E7 ]; n' T" Idisable_functions =
$ ?( x, q" m, ^7 Z! ^) n# t8 e1 o) y: M# o( e7 [2 ?' k8 P; t; P L
在”=“后面加上要禁止的函数,多个函数用”,“隔开。 ; p8 v( U) `# z) a6 d' a. N
, K0 Y' [( {7 Y& n8 [% j
) ?! e( U0 f+ R" o. e) M3、修改httpd.conf
1 D& h! i8 Q3 x8 [7 T N4 h9 u! T$ g8 S; ^* X" S
如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作
- l* e/ E- g4 J路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行: # y. D7 M, M" n \/ O9 t2 G
' r: k4 Z) @7 ^+ r4 @$ S
<Directory /usr/local/apache/htdocs>
" l' I' O, w! @1 ~1 @$ lphp_admin_value open_basedir /usr/local/apache/htdocs
; Y0 v5 N, T3 Z) x O" F9 {3 f4 v</Directory>
* G6 K! E: C& v5 G% v, \- v/ a( P4 A' l( X
这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打8 V# `+ [7 p# k
开的话会提示这样的错误: 0 m1 z( P4 M) F6 U
0 F8 x$ S# k* |
Warning: open_basedir restriction in effect. File is in wrong directory in 9 S& O% G' Z4 i; g% H
/usr/local/apache/htdocs/open.php on line 4
2 V% V3 k, L+ e% a" P/ L* d |2 z$ |% [: t. }' o4 c& v
等等。
* M8 c/ s& t8 q' b
q- P" ?1 M5 S% |) q) x* r* Z# j" D
4、对php代码进行编译 ) M2 S- Q( ^5 v4 L5 K/ J4 B
7 f2 V% s$ R5 Y" m4 K: x& N5 zZend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和) z! @5 n9 P# C, U$ H
ZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就: U; D0 r" M |0 V3 S$ b$ {" L( T
可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统 ]) T: i$ b/ `0 T1 x
:
0 A9 _5 e! P* W& ^9 Z+ V" X/ \
8 q# K* Q$ N% W4 T2 i9 @ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz # F) ~" o, Z4 Q8 z. B+ H
ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz ' T$ O3 f. D* e6 J. P( j
ZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz
0 S! f( O6 F" s+ h1 ]3 YZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip
- F. T; d* s8 p9 c
0 ^4 o5 C6 T$ E% W/ t0 l# g优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里
' G6 p n2 v" _1 S的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句
, G) K. S1 g( p# h: 6 {* `1 Q: Q( s- {' t+ k1 s
# Z0 M% ^$ w5 d& ~7 ]
zend_optimizer.optimization_level=15 % D5 `# m' ]! |
zend_extension="/usr/local/lib/ZendOptimizer.so"
g' ^! `5 w3 D& D8 p
; ~" ?; P! u( F/ G就可以了。用phpinfo()看到Zend图标左边有下面文字:
, W ~0 T# r) i3 i: B f! Q
5 P3 e" J# s7 r" _1 mwith Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies U/ X. R: w8 c% H' _5 y) `, S
$ ~! r9 Q: D% L' X3 Z% p
那么,优化器已经挂接成功了。
5 g; \; _6 z5 r8 h
s" H' V, n8 P8 H9 W8 h但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设
& t/ }0 \, L* T计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。
" U4 W* [8 v# X/ [4 X5 R/ ` A9 J% z# }7 u3 x$ L8 {' j+ R
php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进% C+ K# o. q+ o9 g$ P; r% O. Y' S
一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如
: P7 E+ A. F9 [. D8 Mmysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。 ' u# a% u7 b% E6 W3 Z
. Q5 P) Q! Q. _2 c
% K! h+ _2 ]4 ^+ R! C0 f4 @5、文件及目录的权限设置
) d( I8 v" ~- g
* y) y% g. F& `9 |" J9 P7 `web目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,* C( Y0 Q S% A$ i6 z
攻击者可以修改主页文件,所以web目录的权限一定要设置好。 7 W L* u" w! m* r
; W% v- u+ l2 s+ F还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属
1 l- n! a, q! X' E! ?主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的
7 R9 Z5 D2 c6 C错误:
7 G$ B- v& a( y8 c% W/ s9 Y1 K" h
3 |" ~8 p2 ^$ N4 M; d& T* uWarning: SAFE MODE Restriction in effect. The script whose uid is 500 is not 7 i' o( ?6 J3 Q% t
allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
. ` P# x: _" j# F& Uon line 3 ' b5 @# r* g) x. a6 h
* V( l" X9 h( f. D7 l/ _ s* K6 u6 r这样我们能防止许多系统文件被读,比如:/etc/passwd等。 2 l8 T0 w; F8 L' U0 j; c3 d
上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。 5 g* }; Q4 E4 b: C6 @
]3 i; @8 M8 {* L/ a: @
4 ]2 {& z3 S+ `4 D# V' p6、mysql的启动权限设置
* ?! }, a0 g1 ~* X ^1 ]* r3 I( j4 f* C1 c' K- d i
mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等
$ Y, \/ l, t7 F! w5 |7 ~+ O系统启动脚本里加上一句:
2 a9 |3 M/ m: B8 U4 V
- \& r2 d' p6 U" s. m* E! Hsu mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start" 2 L# Q1 M4 ~) g
% _( X- E4 k8 W0 S5 ^3 O' V$ c' V. L
这样系统重启后,也会自动用mysqladmin用户启动mysql进程。 $ P( H2 G8 v' t" C( k
0 r4 r7 J1 k5 z/ N& ]2 c& L0 T, r$ N
. ] g3 ~" H; g- z/ k+ m" `- ~' A
7、日志文件及上传目录的审核及 7 n: R) s; G4 D6 Z6 Y2 Z6 {
- } i& Z' S# }: ~# E; _$ Z( L" j
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且
* L& G1 e1 ~; D' C4 G- |, z& G: k也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非
& u! ~4 h2 F5 T1 ~法的文件,比如执行脚本等。 6 d# N. b% Y/ t+ t+ c7 G( I
8 \" Y, s: U/ k) R( A0 T- u
$ K/ j2 j/ h6 J8、操作系统自身的补丁
- s0 x! ^0 x7 {( x: y
9 M$ W& D+ ?; M! Z* K6 f- O) S一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。 ) i x1 T2 m& N1 @7 [
- G! g7 p" A# }6 }* L# l
* X) U9 R7 u0 z6 y
经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,
, d# g' }* T- g+ O1 R: \% E即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。 / L4 }! G5 G) e8 _8 ]4 H
如果您还有更古怪,更变态的配置方法,希望能一起分享分享;)
" L4 \& t) e3 s, R0 l+ T+ b9 X+ u& c. S$ ~1 \, n0 T
8 |( s& u% ^ T, n
参考资料: * B% ~4 Z7 f: G+ F1 T
PHP Manual % J: \, F; B$ \0 d6 ]8 Z$ B3 a3 u
http://www.zend.com |
|