|
|
发布日期:2001-11-27
; d: N5 V9 A) w; A. B2 e文章内容:
& g, q$ _5 H' s9 y) q--------------------------------------------------------------------------------+ j, a+ N% E" F, Q
' b/ W: E8 w1 ^3 l4 L: O- {1 S
作者:san(小许) san@nsfocus.com
3 S. w4 W" \4 c
* w( b) O* E* x+ W--------------------------------------------------------------------------------
" x/ w1 P% _2 G P' t1 z" q. v3 A; ?3 e5 l+ {! O, _7 w
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以' H* T; E; Q4 _7 N' C9 E
及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配' o7 Y! j. a" W; S! O l$ Q
置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的
" d* h% B n2 J3 }: [% o- ]1 b! N1 s过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的
$ h1 W: B. ~ Y5 u3 T0 c( w8 s' f, tphpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现
* c$ k: B+ Q1 p# }在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题
2 m) i" f" p* N) X1 O4 z了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 - a. y- k" o- I! m+ h3 U! e
' p6 V1 x8 l( w3 y0 `- O
* t0 n4 i7 F' B5 g8 z* h
1、编译的时候注意补上已知的漏洞
# w$ O- P8 x( o! S6 y: S8 V% s+ ^; H& B2 ?* T7 `
从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突
K% @4 T+ l9 G( F/ }2 i: v# d破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源1 H2 s9 y9 X) Z2 ^
码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件
* m# W6 D& C. }) E1 }& K的第152行,也就是下面这行:
Y0 L" C' F) N9 n# u/ X6 B
1 y7 I2 k8 v( P u" Z% pif (extra_cmd != NULL) {
+ p6 v; E( f' |- I0 z# R. i, w
9 [# |8 q, k. d后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php ! @. Y1 w: t" m, I: L' b
那么我们就修补了这个漏洞。 # w9 g: K# _+ c' Y% k, h% ~
8 w. F5 |; T, ^: F* y
. y% ?4 P% L+ [
2、修改php.ini配置文件
" H0 e6 n5 K; c; f2 c' Z( \* o/ b
1 g$ J' I9 h) Z, M以php发行版的php.ini-dist为蓝本进行修改。 ( f A0 _2 q# m5 K5 p) d
( {+ E( {& w1 }
1)Error handling and logging ' \* h/ s j1 }* \* _
在Error handling and logging部分可以做一些设定。先找到:
' w) k$ `- G6 f7 q4 w7 {8 }4 Sdisplay_errors = On + L7 h( e3 D# j/ v/ H* P
! C7 d# T6 M6 Q3 u4 g \8 zphp缺省是打开错误信息显示的,我们把它改为: + F1 W: r% \* a0 x# t0 I
- ?- c/ _1 s& a$ x; ydisplay_errors = Off
) T v# Z6 x* f" Z) `
# H% x" v6 r% n9 Y `关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻
[4 y2 [1 J# E击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造
: ?* X5 i$ f1 N6 v+ b; t成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以9 X* M% v" u0 J( Z: K2 ~, I
下: ( @% K) ~: N+ \" o- h, W- ?
$ P1 G4 W( q0 }
log_errors = Off
2 w" m$ R G9 y4 \5 y y+ z( |( W- p8 P( I8 T7 S
改为: 1 a$ f. R. i% N0 g( Q) C& _
log_errors = On
$ I, [* c6 }6 T: ?3 R9 _
4 t2 e5 n6 c5 {3 \5 C& L# F以及指定文件,找到下面这行:
2 s. `" {9 k2 }" t, S5 w; L/ d/ E1 `3 R: o
;error_log = filename 0 p9 W) R' N3 \$ K5 L: h
2 f( } f& s/ K+ G4 R' l: ^去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
( F) H5 V- a$ e: x+ e( K& b
( y5 k3 g% o+ m' Z$ cerror_log = /usr/local/apache/logs/php_error.log
* w u- l. C; \ N$ A( s% U, f* S/ \0 p6 i
这样所有的错误都会写到php_error.log文件里。
% j2 [: u5 ]& S1 B! m- e9 h9 `; i" f8 ~+ _; }4 V
2)Safe Mode
$ r/ ]+ S1 m* U8 e. q$ m" ]/ Q
php的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在; a3 O) @7 b( W( |( t3 r
Safe Mode部分找到: * `( @1 C6 Q7 N6 G9 U+ Y# a6 u
# R: Y! ~' u& i. O) K
safe_mode = Off $ e5 }( ~* ]7 j3 P
8 B* v# f8 s+ D! i t
改为: ' T) h" p- a- J8 J
, d- r7 C! M" b, V1 e/ g( Ksafe_mode = On 7 p! v3 s; C; t! X2 L2 Q
3 ^ L$ M7 ^+ {6 o这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它+ v- D& t+ x8 U! o, X, P
的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行
" s2 P$ M: f; u, U9 i, |: F# Wsafe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下: ) L3 m% j/ W2 y' l6 V' Q6 b
' W+ g1 f) y6 k" L G( R
safe_mode_exec_dir =
( x3 p+ s# o) q M% s; m" G: h* X
1 J- X/ P4 v1 {3 w指定要执行的程序的路径,如: $ i# E$ s" u6 b; C
3 p0 j8 V: P$ k* f! A; Z1 _
safe_mode_exec_dir = /usr/local/php/exec % ?. E0 I: y9 V9 f
# y7 F& p" _$ q: S; c
然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行
+ k$ o$ d9 j9 \! }. s9 ]4 P4 ^该目录里的程序。 8 `6 @1 e; }9 k- M- n! g& j
; `1 ]- n1 [0 Q# u
关于安全模式下受限函数的详细信息请查看php主站的说明:
; l. y5 t# D' a3 ~ v: z Bhttp://www.php.net/manual/en/features.safe-mode.php % T: u$ o r2 L; E5 }# \
" B# a7 D; E* j3 P1 n
3)disable_functions
5 O" |, l. ?% M0 d! M
) U/ A4 w9 I3 a/ o1 I7 n, n如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这
' c) M1 G/ J' T' X: W# q6 J/ a行: 4 ~8 H2 c0 i E& U2 l5 _/ R0 s
% m2 @* a( F& Z" Ydisable_functions = 5 n) t4 @5 g5 Y9 T3 N o
3 j/ e ], }0 r! ?% p& h
在”=“后面加上要禁止的函数,多个函数用”,“隔开。 + H! s& L# `! }% H& q" A
4 Y' Q; _1 g' N$ c9 ?5 a2 f/ m H; L) w S
3、修改httpd.conf
& Y5 u$ t2 i. q+ v* [. p6 f
6 Q$ l- T2 @% G+ c1 r( s如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作/ k# R8 m/ G' h5 ?! Z9 \' D
路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行:
# v J, d/ w6 v
) V5 ~' L. ?) h4 ]<Directory /usr/local/apache/htdocs>
6 i+ B* _' T6 _5 jphp_admin_value open_basedir /usr/local/apache/htdocs
4 z- l# k7 i5 f2 P# N- Y. L</Directory>
! v& h: v" g, F, ~6 m3 L/ V! f
7 w3 Z6 w$ g- }这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打
8 a% x' P+ N. V( c X7 P2 W开的话会提示这样的错误:
+ o0 h& Y+ ^9 b
: F0 f ^1 T6 @7 t2 G0 a2 g( ]* V- G' gWarning: open_basedir restriction in effect. File is in wrong directory in
3 e% V+ n; G' K/ Q$ ~5 p, k/usr/local/apache/htdocs/open.php on line 4
7 z/ w+ B% a/ @- U' g8 `* B4 h3 G4 j7 E
等等。 & w6 l& Z7 O) {* ~5 W
5 _7 F' g, z$ }1 H1 Q
( S2 |6 h" t. j G4、对php代码进行编译
* [9 ]: y+ E' N! M# o' l) m% s7 v- p( x% x
Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和
+ }8 W% D5 X6 i- D& u5 p( I! Y: PZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就
% G/ q. k4 l; E可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统
/ c8 [! I k6 ~9 @) J4 U; f% p4 b# l: " B$ u6 O; e4 y! p. L. L: ]# N
& M- j; j u% O- v3 zZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz
3 Q6 c5 X& j1 P' T7 `ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz ' z7 U5 K% n- ~% }2 A# ?! z, Q
ZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz
. }" q* m v: ^) LZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip 6 A# g- D/ t9 d. I$ v: t) v7 r8 S8 n
. w p2 }! P) U& u3 o% ]" z
优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里$ D% v) F' L( V
的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句
! i9 X' P9 K1 j! e% |:
% |/ A2 @0 u9 f, B4 l/ r% A$ Z; n! }' D+ e( T7 F
zend_optimizer.optimization_level=15
, M! N8 @# {" U9 |- k! i/ V" p# @# Ezend_extension="/usr/local/lib/ZendOptimizer.so" & Q5 Q( w) T) {6 G; _
1 x- v+ Q- _3 y F1 K7 ?8 h
就可以了。用phpinfo()看到Zend图标左边有下面文字:
8 ]/ p; m z0 u: V7 M3 ]+ S) O( u. S+ T" v# q( I7 }3 B+ P
with Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies
) |2 f; A7 x; b' Y+ e8 J7 O% F! T! V% R
那么,优化器已经挂接成功了。 $ @) H- w' Y! o, _1 _
7 M' k/ @; K* |9 m& l
但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设/ E4 @4 ^0 F* P, M. v
计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。
; v: u1 E8 d2 Z2 f5 k2 ^: y, o1 e* H4 E; l% u
php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进# w7 s3 o- V8 K0 ~3 I' E
一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如
" C" \9 S% q5 p- g( [: a# ?mysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。 - I, {) b5 P$ l( f c. u8 |( R
. u& F# E3 g( c" f
6 f6 _: t+ s. q {& U6 B5、文件及目录的权限设置 ! Y! t1 \2 C* |0 ^0 c9 A. G! R
5 D3 I X* s5 y" t$ q M
web目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,
6 w$ R9 |5 |* G. h攻击者可以修改主页文件,所以web目录的权限一定要设置好。
) H* T. v# f2 p9 r- c8 p7 @/ | d1 Q
还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属
1 o1 `/ t: u( x ?# ^, ^主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的! s) D) H3 ?' R0 `* r' v/ z
错误:
6 K: j/ D [ v6 u8 o* V* H+ v" X8 i4 J; ?4 ~% Y$ n3 w, j$ u3 x
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not - U/ O7 e9 ]) b
allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
- ^5 a1 X# u: f& k% x6 ]on line 3
5 j+ F& r9 I Z# S8 k+ ^" T
@0 ^6 W5 b' [% q" L# G; c, y9 w这样我们能防止许多系统文件被读,比如:/etc/passwd等。
2 I5 f7 b7 }3 w上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。 2 P% `6 N4 ^& ? o6 I. W8 ^! m
' `, M# ]/ S# `( x5 A. o, i. V7 m3 k+ U: C- ]5 X
6、mysql的启动权限设置
2 [9 U8 w8 }% C$ [. `7 j
$ B7 g/ e% c2 v+ k0 k" zmysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等
* @. Z: D4 _ Y0 {3 x$ h( _系统启动脚本里加上一句:
7 p8 [" k$ j& A8 c. [& A) K `- u3 I. ^
su mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start" , j& A8 R, c; {3 O! Z' u1 |% I3 p
! \: L8 H) [' Z( z3 `# Y: s这样系统重启后,也会自动用mysqladmin用户启动mysql进程。 " Y: g8 l. F6 @+ _
$ @% |8 D0 `! z' J8 v+ t/ X
) ~7 h: C; Q6 x: O5 t7、日志文件及上传目录的审核及
/ ]5 N5 K* Q$ C& a( A5 B& y9 x3 C
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且 y$ q0 I- F& x8 Z/ o
也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非
3 s4 h0 y* z) F- k% g1 `法的文件,比如执行脚本等。 / K0 T% ^9 P/ m6 h' u2 g; K/ t8 @, V& G
, Z$ v0 T, r7 }; B5 k8 v: P$ y4 f4 A: u3 L, g! a1 \6 Z. m
8、操作系统自身的补丁 1 ?5 B, C# @, ~. F
5 u6 }! x# E6 p; E
一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。
) T7 S! D# G" ~' T. }: N. q; U. ^' ~
+ m* A. P, C* ?( f4 C
经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦, ~" f( d0 L _' F
即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。
6 u5 c U5 A9 N1 C% Y+ Y( ]如果您还有更古怪,更变态的配置方法,希望能一起分享分享;) 0 w3 D7 j# U; X+ {2 R
( B! f# |; E& v& L' t4 i$ W1 q* b
% {# v. \6 }1 Z/ s2 x参考资料: - F+ g& Q$ H2 X2 G% r$ Z) s5 c
PHP Manual ) n1 Z+ _; U, ~* \( K7 Y; D2 F
http://www.zend.com |
|