|
|
发布日期:2001-11-274 I4 S+ `: n; V; o7 x, q, t
文章内容:
& u- O" M9 o4 U--------------------------------------------------------------------------------+ O7 f: a" r: E' A6 e
+ t/ T: r' ]6 G5 O0 J作者:san(小许) san@nsfocus.com
, q0 P/ A- }8 F* g9 X4 \0 \1 J% Y5 ]! F( j3 l" D5 O# W! w" D
--------------------------------------------------------------------------------4 P9 C2 b* c# F5 I4 z) B
( `$ w" E1 c' t" m l" U
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以+ U4 J1 L+ r- j2 o( `) q
及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配
. d$ o) s6 i7 O/ x! ?, Y5 t置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的
0 j7 S- z: p; Z2 Q9 T/ q, `7 r) ]! A过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的
% L+ k$ U r# f' z0 N! nphpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现
1 r" a6 k; G4 O0 C在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题
& H# } ^7 V6 r" D$ y9 k了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 5 [3 s. ~) Z$ t" T" y
; W$ z9 A5 f8 W+ L- ~
6 ]1 z ]* e0 o
1、编译的时候注意补上已知的漏洞
$ n1 M/ Y5 A- K/ Z
, I' s3 C s% e6 Z, m9 j( Y从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突8 r. s( V) |8 ^, Z
破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源/ e7 b2 F( |4 w0 h2 u9 f$ Z
码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件$ z; S9 u+ r+ F) Y4 |, ?9 F
的第152行,也就是下面这行:
- V" h" z2 c+ k: @" _8 k) B. A6 \+ R$ D& t
if (extra_cmd != NULL) { 9 m) i. H2 w% `. J- T) L
2 e! K. {4 D8 ^! A/ i/ G3 U
后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php 5 P* g' h/ |& t- `( s% V7 \4 |+ _
那么我们就修补了这个漏洞。 5 {! l9 [% J; v: W0 ^- b" O
/ R! g- J' l+ Z1 B6 P; o- I" H0 E: u5 \4 b' F/ d8 y( S% H& H
2、修改php.ini配置文件 5 U* K9 g% y$ o+ x! M+ E2 b/ V. G
- t/ p/ Z) i' x& U! {9 b& C以php发行版的php.ini-dist为蓝本进行修改。 ( e% X. ]0 d: l* a+ Q2 |
- R1 E1 Z9 }, U8 U: {( R1)Error handling and logging : [& C; ^" R. N+ }+ R% ?2 x
在Error handling and logging部分可以做一些设定。先找到:
6 m5 C9 G8 h' x( j/ \$ j7 Ndisplay_errors = On
" q* {0 E. B# D4 Z
" P$ @6 h# P. [7 H& e" J) l Bphp缺省是打开错误信息显示的,我们把它改为:
]! n2 U' X" _* q" [
" Z; G, l$ l2 mdisplay_errors = Off
# Z% N# j( R4 n7 o! @- v" c0 f0 r$ X2 \+ F5 L/ ]
关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻
+ Q* g2 K/ N% Y击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造. K; e+ a9 T( w2 i7 N
成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以$ `7 F- j1 o& ]% a5 |
下: " p$ O; B) t! |! G2 @% ?" U# I
4 u! _( q" A2 o" m! j) m$ n( ilog_errors = Off
+ n7 z$ w7 w$ ~1 [% F+ r6 e* i! [/ t2 ^8 S6 c/ O: _/ l' L, R0 K0 u% M
改为:
4 F% Q9 n, n* ^* R ^9 Olog_errors = On
: Q, z) S4 ~7 q9 z( d& X/ [: U+ \0 I) f# D
以及指定文件,找到下面这行: , X# N6 y) R5 o, z, e h- `0 ?+ h4 e
2 R0 V9 w. P6 |
;error_log = filename
* y: t7 I- A C6 V+ V" ?* J" e7 z8 l% g2 s
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log ( |! Z. |6 L6 A; w* }
! s+ y3 g+ N- xerror_log = /usr/local/apache/logs/php_error.log / B( [/ j& ~. ]; E7 @9 y" p& ?4 s
0 r- P6 ^2 T. n' Z, P) o
这样所有的错误都会写到php_error.log文件里。 ! n* X& q Y" V3 p; o$ l
! D% s: l2 ?! C) i
2)Safe Mode & _6 m8 P5 I/ s& W: o
5 k' D, W+ B0 k: d' d& ~! Bphp的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在
$ U* f$ `8 N6 ]9 Z; @! l$ w$ eSafe Mode部分找到:
0 ^, W0 o% K# ^. v; e% j( ~8 _9 Y! e7 o, h) Z8 t' g+ Q" ]1 Q
safe_mode = Off 2 U" B) Z- v8 g3 ]% a
/ I# a) @& @( z* f e
改为: ( H) l% w Z1 E: ]
7 T/ h: x, ]" x( |safe_mode = On 6 g- F* V* `* V
" p* s' K. p2 \) `( p" X
这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它) K6 {& x) ~) I7 f& R
的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行
, L2 O' W% s, s+ t0 ~: Zsafe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下: " j% \ E! `4 z* Y5 p$ _% q9 j* F: e
( r/ ?% K$ [3 |. R, Nsafe_mode_exec_dir =
! f- R5 c# v& U, A; S; p2 [2 b9 o- V* y; v' U
指定要执行的程序的路径,如:
. [ Y2 I5 ?7 l; ] x+ R" l0 L
* P* o9 X+ t- Csafe_mode_exec_dir = /usr/local/php/exec
! ?+ G0 E) E: h E9 W) R+ _2 q$ P q/ I4 r
然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行
/ Q4 o* w6 ~7 o& U) u6 C该目录里的程序。 . A' }1 z( x: i Z
& M. j" e+ ?) g! D e: W+ j关于安全模式下受限函数的详细信息请查看php主站的说明: 0 y2 q% l, B8 H, g
http://www.php.net/manual/en/features.safe-mode.php
: ^7 w- d/ d6 L6 G# Q1 w+ l S- `1 K
3)disable_functions
3 Y" d- K/ _ M( h) \, M$ f8 H+ {" b2 S! N6 P, r
如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这, V- f6 Q6 s- Z) F& j1 H! J1 V/ C
行:
% @8 k6 q) x1 @; o2 s5 c
9 n' U# ~$ C" ydisable_functions = : z: y' u% `* D; m8 W6 i+ u, ^
7 y( u- i. I8 V5 w) S' L
在”=“后面加上要禁止的函数,多个函数用”,“隔开。
8 ~- ]5 z6 M- P7 `
+ r0 O7 L% E) K# W$ W4 \8 X" }5 N* g. T ?+ X
3、修改httpd.conf 2 Z9 c) g% q3 s1 t0 a4 P! o: x/ q h
- ~# N. a" e5 v4 _+ Y
如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作
% r+ y- p' r% _7 I+ o路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行: ; |" J2 w' U$ B' L
3 I- A: m( b) N4 ]0 ?
<Directory /usr/local/apache/htdocs> + F# m7 X: L! g. i: t2 S
php_admin_value open_basedir /usr/local/apache/htdocs
- F) l5 j7 A0 c% A6 |& z) m' y a</Directory> ) g2 j ^/ M, ?; P4 h+ B
0 B6 r: l7 N+ r$ u% {0 s U这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打; g- P% S( r- J) v1 P5 l
开的话会提示这样的错误:
1 B& V0 ~+ J# E! D" k; d7 s+ m7 D) o/ o" Y. _$ F2 ^% f& c
Warning: open_basedir restriction in effect. File is in wrong directory in 4 U& r; y5 Q& \9 g D
/usr/local/apache/htdocs/open.php on line 4
2 @0 h. U" e, t( d" t5 ]) U6 v" f% ]9 ~! `) n$ L
等等。
6 C6 B+ @' E8 ^
0 R) F; J2 ]) [
- w1 b- X+ D+ ^1 i4、对php代码进行编译 8 D1 {0 k+ G F4 E5 G' ^# n
9 M3 ^, f. b% c, Z5 x/ I
Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和
! p4 f1 r+ m( K* H) ZZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就; N1 E8 ~, t2 D0 s
可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统+ _# o- j) U7 v/ Y0 D; @
:
7 i( Y/ q) L0 ^# w! y! @# |
* ~. ?2 E3 m. T% }ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz
x$ D% z; Q2 |' X, [ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz
/ B- d; [! J2 i% f! WZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz 0 \( _' h; Y4 V4 }. C
ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip 8 u7 }' |5 t) L: d, P
) J6 g4 p. S: g. H& N# f- u优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里" ~, h( v# x( ?8 r# U/ F5 W; f" q
的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句
, A/ s6 x. A) S4 ]:
8 W" m" F* v$ ?- o' j: G$ [8 A j8 ~ e
zend_optimizer.optimization_level=15 ) X) c, C! o9 m) d
zend_extension="/usr/local/lib/ZendOptimizer.so" % W9 Y9 ?3 q u/ p1 m6 m$ d
# J. U* r2 H+ r( z6 M; v; e, c
就可以了。用phpinfo()看到Zend图标左边有下面文字:
/ J9 E7 S) {3 ]! O$ Q5 x1 Z" P1 I, f* X& _
with Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies 9 c4 i3 H/ B% i9 F# [
. N4 D8 Y6 [4 @& k& ?( _那么,优化器已经挂接成功了。
5 E, @+ |: U- d' i) d$ b* [. E
# A, R" p3 {, I( f/ E+ F/ }( N但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设- J. |5 E y* z8 S2 O& F
计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。 : ?* N6 a' ^" I5 k; c9 t" g: \
8 {, L2 c1 O( A. A9 O ephp脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进( s3 U1 {9 H. m4 }: C& b
一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如
6 m" A+ y( N0 @+ I% kmysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。 % g/ C, B! b: i% N! ^5 Q
3 H o- ?+ o/ Y" @. {
# |) U7 r4 J9 Q9 n: r5、文件及目录的权限设置
( J( a, n/ A- Y' Q# Z7 ]. {% `& v; C* E/ c6 b
web目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,3 {% H$ u) `) O% q
攻击者可以修改主页文件,所以web目录的权限一定要设置好。
- {% K& e( l( v8 o: J3 r$ T9 M% b v1 F
还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属: B/ J) t# {. ~0 l4 H
主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的% P4 l. K9 t0 e' m
错误:
& C1 C+ ~! g% l$ j# A. v1 {; p, w4 ?" [/ W& ~
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not
5 G$ I" I# K7 P0 @allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
2 @; u$ E# P9 P: p1 Qon line 3 + }. c5 `/ o7 [/ G: c# U0 @4 O
. D' e4 d) V5 b4 q* n" Z: B这样我们能防止许多系统文件被读,比如:/etc/passwd等。 7 f: A' k! w! n6 \
上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。 4 C; L2 L6 u y8 x# S% C5 z
0 _ H9 g0 Z2 _7 }3 v
y: S' |# w; K$ P$ f5 P6、mysql的启动权限设置 * b) _) M" w* R+ D( u
9 K: _+ J' P% z' n# M- l- n
mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等$ C- |. r0 @0 r/ L2 a
系统启动脚本里加上一句:
0 b* K3 m& c" [+ Z0 ~) C
* p7 o1 c) k3 E7 u i5 b- Z2 gsu mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start"
6 D4 A2 u, p0 Z0 P4 R* V: K1 Q+ P) D6 @, E2 J
这样系统重启后,也会自动用mysqladmin用户启动mysql进程。
|1 ^- i! g# M/ J5 E( e
8 r2 Q% V1 t/ S, f# ]( A' c/ |
5 p6 C1 c0 h6 V3 z6 q6 b7、日志文件及上传目录的审核及 8 Y! p& G: u) S0 w
/ P0 r* A- T$ P3 b$ b" D5 Z6 ?+ O
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且
. G O, _5 B* e0 P也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非
+ u9 {8 L! C7 K5 h0 b法的文件,比如执行脚本等。
e# B# X$ M! ~
6 R3 W( `. ~4 w1 [ h7 G9 i7 T, F) x
) r+ i7 |8 b) {' ?8 R9 P: I8、操作系统自身的补丁 9 ^( y8 d+ T6 t5 Z8 b
8 e6 ^6 j) p1 A, `# E一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。
# R6 [$ k X* |' y5 }% r5 S- W
" Q' {8 l' D0 ~# f o* x' R1 E, b, |% _5 o$ m j
经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,# R8 w: m a& H
即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。 + A' u# N( Q4 s* Q! k
如果您还有更古怪,更变态的配置方法,希望能一起分享分享;) 5 u7 R1 m; k5 Z& ~* D; ]8 r
: w8 x% N* b1 H
^9 f2 w- w* N6 Z! b; j6 l' `
参考资料:
) r3 o4 ~1 f9 R" k) P: a- x- u1 ePHP Manual
" j" x, b) F. ?+ |http://www.zend.com |
|