|
发布日期:2001-11-27
" z L& q$ a/ u4 B: U; K8 r文章内容:/ [+ f! R; h4 k* y( S* w: Y
--------------------------------------------------------------------------------
) p1 j( |# v$ S5 \2 o! r
! `; g: V- A) |$ I2 a* e' j7 Y/ h作者:san(小许) san@nsfocus.com
# v4 |# o8 [( H. V: g: y
; V5 S: y" k$ ~* [. L$ w--------------------------------------------------------------------------------
2 \" f, `; Z0 f0 [. \+ e0 T) `( w- u
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以& E2 `) Z3 X/ f: ~1 [ m1 S
及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配
+ I H7 H1 f; l& B置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的2 ?, T8 |! Z' j1 A7 C- k2 Y& {
过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的# ^3 E+ L5 V5 v' ^
phpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现
+ d1 I+ L( N4 ~; @, ^0 c! l7 L- B在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题1 [. U4 y/ @1 F* y. A* I5 g
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 8 k) j/ z& o' ~% }3 b- }
) s x3 c- o' Z9 I0 [
+ g S& ^& H. R* |6 r- Z6 s& M2 e1、编译的时候注意补上已知的漏洞
, e Q& q/ Y' |& u9 q; A9 c
2 o5 G$ }$ G/ Z1 Z从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突: Z/ H: R1 ^$ _1 f
破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源
; C+ x3 B6 j* h8 F: h8 f" Z码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件
' y5 ^' _; y: {& c6 `. D& F7 A) p1 f6 O的第152行,也就是下面这行:
8 J/ n2 \$ Q D1 l
+ ~5 A) O. D' u) @: J: q7 O0 |) fif (extra_cmd != NULL) {
7 d* D4 ^% t5 b$ I# {1 B
, w2 B( c W2 Y9 e后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php ' Z7 x" j' ^% y( d
那么我们就修补了这个漏洞。 # U7 N, L( a6 e
. w/ ?% S/ @* L, T
5 e& E* [$ V. p x: ^. ] g6 K& N2、修改php.ini配置文件
3 p4 U- } t" Z1 f0 E$ G( l7 @, e+ l
以php发行版的php.ini-dist为蓝本进行修改。 ) z5 V5 s0 C8 j8 a; X
5 X- T; d1 ?; i1)Error handling and logging ) |" d+ T- m4 x
在Error handling and logging部分可以做一些设定。先找到: ! v" W$ `$ s0 y' U% C1 H
display_errors = On
% ?( T) h/ P7 m* }. m0 C6 \4 v7 F& E
php缺省是打开错误信息显示的,我们把它改为:
" G. v0 h7 i7 p2 A0 D/ E, L3 d% l3 j+ L
display_errors = Off
+ c9 M. v- K: D9 P& V% O
# H/ e; A" B+ \9 h7 [% Y2 X" X关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻$ I! j, O1 o* j+ W. W
击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造6 B y$ S p% E5 `& r9 U4 A7 ]
成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以
+ _- K# c: |6 g$ C下:
% v. ~- O- x. n, h1 U1 C6 r2 j
: f4 ?, n; }5 J9 jlog_errors = Off 6 L7 k2 v! H, f$ T4 {( E- w8 P
3 E* V( H4 \% J5 k1 N- d' _8 |6 L
改为: ( T- m7 ?# U+ P
log_errors = On
0 i M4 {2 l. n/ v2 K! U: E% a$ g; j% }6 s( u5 l8 u
以及指定文件,找到下面这行: 2 Z2 ?& F- x% T2 x
# J9 y% y$ m+ s- v" `3 ~7 p! O: c
;error_log = filename
( O+ N2 C9 X) {- ~3 k2 a. z5 u2 C9 r7 f0 z
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
* K+ p& X7 ^! z, A8 l" `9 m& g0 G# n9 r
error_log = /usr/local/apache/logs/php_error.log
4 \! ^, B& J9 | s$ T8 o2 ]
1 ]! t- B8 D+ q' ]) y1 f$ l: j% O这样所有的错误都会写到php_error.log文件里。
3 k- ?( ~2 E% H0 i
2 ?+ @( o3 w: _1 K* ~2)Safe Mode n/ [: @/ N# t! x% y2 }3 C* }1 A
7 w3 N9 o7 e- Q$ f0 u- h" h
php的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在) q" U/ {7 w7 f1 ?" w, `
Safe Mode部分找到: # b1 y7 \* s v1 g7 E
5 r, W/ n1 _0 b3 A/ @
safe_mode = Off
* Z3 k# J) Y* ~0 d6 ^( ~$ t+ S* j3 q" w% O4 M* P2 g4 e
改为: 2 ]6 I. p1 O9 P3 [8 n
& G3 N+ Y8 |2 I0 P) h$ Q+ j! L
safe_mode = On
! f h! f4 j4 K+ v0 y( i# G# V" v: Z0 F9 t8 {, ~: W
这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它' W+ D6 Z) N. L5 X# j* G n$ _( W
的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行
V ]* q' o! o: j6 z" T# dsafe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下:
" [( T1 I) d9 R- G0 T3 O# {& d( W4 D" v/ [. J- Z2 I
safe_mode_exec_dir =
* u" K$ x, P% w: p! P" s5 ~6 Q+ L* u! o8 O5 {
指定要执行的程序的路径,如: & n8 D+ R' S. u
( _2 n) Q! f, v5 M; a+ G% `+ d
safe_mode_exec_dir = /usr/local/php/exec
- V6 [4 K( }4 x# l0 f- v* }
, Z9 g7 P0 p% w6 V然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行
0 v' X) h2 _: T9 L" P# Y7 T( I该目录里的程序。
3 T+ d P! ~5 E, D5 D" W$ G
/ @; O& C, m- d/ t0 ]关于安全模式下受限函数的详细信息请查看php主站的说明: ( m7 W+ a: N6 z# r, {- {0 q
http://www.php.net/manual/en/features.safe-mode.php 5 l% ~& `2 m( Y0 h- D; p
- X7 F; a/ y" {" v% X' O+ P" A
3)disable_functions
3 T$ }% M) q4 u z+ n5 O- _
2 k% c1 y1 g; E9 c. N如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这
! Y" f1 k8 I1 {/ K* M行: # ]* F3 x( j. r/ L
* B6 v6 b* Y2 ~7 J( ~! H
disable_functions = , k' R& V2 R) T8 B
8 n( K, U" o: I; o5 `: H
在”=“后面加上要禁止的函数,多个函数用”,“隔开。
( h) d9 j9 u P2 V5 f
0 y9 h, ]3 `( B( p& |8 N- o, h, n& ~, k: n
3、修改httpd.conf
5 H; z* S; @' x5 H! D$ A
+ I7 J0 t; g1 A, H如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作5 {+ u+ ]" \% g% s; H# |
路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行:
0 A; y0 f. c7 j" g& T) p/ |0 U
" D! U/ q, [ C<Directory /usr/local/apache/htdocs> ! v# D& l$ X9 P
php_admin_value open_basedir /usr/local/apache/htdocs $ O; r- i& G( }2 d5 `
</Directory> ' j& U+ z d( w; f
0 K2 m, D3 N! l. u: W& M9 M这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打
6 K. T B7 |$ Q: c5 b开的话会提示这样的错误: - b0 E* e# O8 G2 }' M6 f" e
9 l: W3 h% [* N4 R' B: j' i2 R
Warning: open_basedir restriction in effect. File is in wrong directory in
( |( B/ L/ }; Z$ G$ d% ~: {/usr/local/apache/htdocs/open.php on line 4
/ e2 t, N4 s! s! k% ~$ [: E; _% o4 J$ [! ? H2 n
等等。
7 |* b$ ]+ C: m' v7 b6 [& S1 L, `! g
3 R- `( U9 T; b; h' b
4、对php代码进行编译
/ s0 Q+ W; U9 M& \" {2 H! @* u3 t( B! [
Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和$ O$ x1 ^* @' B/ X% P2 g8 m7 R
ZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就
: N0 j% h7 z0 Z5 o5 @0 g可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统
% D2 ?% H) I$ S+ ^# j& P) b: & a5 q" d4 `9 @- {5 ?
2 m) ?- ?( d# G
ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz 4 L2 X/ o" A' E# I/ z/ U9 C
ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz
3 h$ h8 H2 Y9 ]8 r6 i; PZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz ; _ f- _( T& i0 ~1 _
ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip 5 |0 D' ?% F* i* h4 {( ?+ E/ w
. Q, }! F7 T; f! n* P1 n优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里
2 n7 n0 b3 |, l" h2 i的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句: h! T' Z6 Z# q8 \
: " M- Z$ b* H/ O4 P% b: N9 S
: Y% u: Y- h" O0 `5 v8 hzend_optimizer.optimization_level=15 E: o2 S& C- W5 W T: I# [4 n
zend_extension="/usr/local/lib/ZendOptimizer.so" / S7 H6 X9 b+ r$ T& ?+ N( j$ n" x6 U: F
7 g" w4 H2 W" s0 n9 ^3 U/ G就可以了。用phpinfo()看到Zend图标左边有下面文字: / `6 `. ~! i: q* i3 g8 Z$ Z W
! Q2 n8 E2 r# F: [8 H) D
with Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies 5 [* p0 [3 y, g& `) a
+ ^( @, `+ M* X$ v
那么,优化器已经挂接成功了。 / S! t' p I: a+ Q; r, s
3 s& `0 [1 A3 v9 D- W
但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设9 l; q: l5 i' A2 N5 J4 X7 O" `
计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。 8 i) ]1 L% \; o
2 a5 y+ s+ `1 p8 m0 i- v5 k h
php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进( v) F1 f( U! s2 t. y
一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如2 @, U* S+ P y3 ?8 B
mysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。
" M9 N$ Z' U3 l" H/ G; S# J: s6 g. M2 v( b
0 D E' {7 }- N. i) [5、文件及目录的权限设置
" N# D7 M$ H: O1 D5 M8 L% ]
5 t# {0 X) X7 b9 Xweb目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,
. S, F6 x" x9 k' L- H/ t$ E) D攻击者可以修改主页文件,所以web目录的权限一定要设置好。
) e. K6 G; t( f# |
* L* \- g- w2 C" j u1 @还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属
9 z4 l) s* t5 D0 m$ H主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的
+ M( o* v5 \6 y2 f# |4 s! B错误:
3 r: b2 B9 k) J4 n' P3 V6 {+ j Z! y2 `- d X; y6 ~. b3 h7 I, A
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not ! N: I7 Y, ^# { y+ ]1 B) q
allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
% i# z. \! V, B8 don line 3
6 k# D# X2 `0 F+ J: y8 D) n
) f1 |2 H& W' d+ B. l' [6 z这样我们能防止许多系统文件被读,比如:/etc/passwd等。 , s9 |9 `% J: \4 R( I+ e+ k4 z
上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。
( y6 w$ E- N- Z% u" g* W1 |8 y
7 E2 ^: Y1 C3 ~5 w- a3 S. ~9 f9 `; m& l( y) [
6、mysql的启动权限设置
( P2 s$ ?/ \' L
5 H" Y7 ~1 w6 M- H1 Z2 `mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等+ M# o. y7 ], [) n+ Y
系统启动脚本里加上一句: - m) e( }8 @8 @# m! f
8 Y: _# L' w) e9 @! x4 _* o
su mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start"
" }& ~5 f6 r# c: p5 O& j, S: o
6 }6 n3 d& R1 w, A/ T; ~这样系统重启后,也会自动用mysqladmin用户启动mysql进程。 $ o# c8 ^8 H$ r/ W6 \3 r
7 w9 E# q: i3 j9 F- }+ P! p
5 ]2 R. s! z# h0 Z6 ^1 |% U7、日志文件及上传目录的审核及 ) \3 p: Z5 b+ S# l
: E( ~' O5 p- b' q, s
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且
4 d0 c2 S- k. e- D5 p4 A也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非' p* _ {0 a1 B3 W
法的文件,比如执行脚本等。 . B; e, X8 c8 ? L d1 j! q6 r
& ?9 X5 n1 y8 U3 a
1 v' j0 E T; [. R8、操作系统自身的补丁
+ b5 Y2 F" b) U& a& U4 U( {) x) H# U2 Y+ _
一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。 - I9 v8 u8 g: k# g5 y$ z; P# k
. p5 ]" y* _' ]1 V5 s1 F) _7 f- c2 }$ e' O! ? W, g. a o! @! K
经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,
5 N7 C: C, v& R3 \) T, ^8 Q. |即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。 P7 ^8 @$ b; ^4 y% O6 P' C- B
如果您还有更古怪,更变态的配置方法,希望能一起分享分享;)
- J D9 a6 Q, E2 m3 E ~2 n$ n/ X2 r: f
' O% C: y$ ^- A M% b% y7 c8 r' x2 w参考资料:
r8 W9 j1 i7 L* M& XPHP Manual C! X" U4 l s- E* u5 D
http://www.zend.com |
|