|
|
发布日期:2001-11-27
0 n' Y+ ~6 V# _5 y文章内容:
$ g7 ]- D. Z9 r+ N: Y--------------------------------------------------------------------------------+ x& p. H4 H3 h& i
& I- \% Q3 |- @- U
作者:san(小许) san@nsfocus.com
) _* W( d6 p! v0 B) [6 H7 {- C2 ]9 e8 L% G% m
--------------------------------------------------------------------------------/ t, ~$ I+ D0 H W
: @0 l( n/ p- M
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以
, u' m8 W/ z: a a# u9 Z2 b* N# C, F及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配/ V% q, a0 @+ r
置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的
/ c( F$ s" M9 R5 L5 h过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的
% @* U4 K+ M- x1 g4 m2 A+ tphpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现/ }) ~, h" m4 L# U+ {! R
在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题5 [: w2 ^: j4 H' {: ]2 y4 q0 y
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 - K* p' t& o& }3 O2 e9 Q, H
0 Y, f- `4 R& c5 D8 n) l# n- x
7 Y) t; G7 x" T7 c1、编译的时候注意补上已知的漏洞
4 y. s V! T1 W! o
% i1 i$ ?3 O3 O$ [/ S9 @; l7 v从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突6 b+ ?7 u e, J& d
破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源
$ d D- h* j9 {5 a+ T% }# x$ ]码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件
' t- c: c( K9 L7 n的第152行,也就是下面这行:
5 z6 d, W. k' w1 y1 u, X' X& N7 {
if (extra_cmd != NULL) {
( j. a% m# @, K+ i0 f/ W% m p( n9 f3 t- Z t4 D4 \2 e* f
后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php ! c+ E* `2 H z5 H
那么我们就修补了这个漏洞。 7 w W% |, v: K1 u- F
5 A5 Y% a' r) u N Y! ?3 i! C
- |( E% s! ^( }! P/ A% Q9 K2、修改php.ini配置文件
! n# Q) t9 s$ N
/ b6 B$ G, ?7 S( I6 L/ g- Y3 J以php发行版的php.ini-dist为蓝本进行修改。 ' Y6 y! G. J0 ^' ?* t$ g" s3 `
! T3 B; i0 U3 ]- W2 r1)Error handling and logging
( s. x& ^5 I: [: W+ q- m5 l6 X在Error handling and logging部分可以做一些设定。先找到: 4 t4 B! m0 p9 m/ _, }8 {
display_errors = On
; R& c& S- x6 d% R) h
" r) j* O$ z# L2 g; z3 mphp缺省是打开错误信息显示的,我们把它改为: 2 @+ J, i4 {' P) H N R
- W' ~. {0 I4 L& R" C8 V4 [- adisplay_errors = Off % D8 S6 [. F% w
) `& H3 J% w, d& w% B" ]3 J& w关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻2 L1 [9 o# j, k
击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造" J* I1 g" V- O7 \# V5 U3 o# r! c
成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以5 [" q7 F. F, n1 x9 b
下: ( [5 l% a2 I" |$ P9 }6 G, |$ m
1 O- F( S8 A1 _# f. z
log_errors = Off $ k5 ^2 p; t8 X6 F
' u) G) n9 V) L
改为: ( l2 `7 L& S7 V1 F. a
log_errors = On
. o7 Q" C. q, C! X# j' i, k5 y8 E: Z2 K( ]: k3 M6 j
以及指定文件,找到下面这行:
! N& u- J6 k6 J7 j# L
, I h+ N) p- A3 l4 U6 M;error_log = filename
; Y4 a$ n2 ^3 D, {% y% y
1 Q( Y6 e2 z2 k) R- F' X去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
: ]1 U! W; `7 N" e+ b7 F' w) i: M) L4 h4 Y2 m. w+ I- U1 a
error_log = /usr/local/apache/logs/php_error.log
1 U7 |; G# s% v! I! E0 f7 B2 p2 F; S4 }7 c' Y2 D, Z4 h+ m
这样所有的错误都会写到php_error.log文件里。
5 [/ E' x( p6 u* p8 c
. ?; S+ n% U; N0 W2)Safe Mode 0 N/ d0 v% O! ]$ @
; O! Z7 e; V5 E, v5 z" A" B6 [
php的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在
. K2 I8 h' J8 tSafe Mode部分找到:
9 t: m. s; c2 P. \) | h: q' c7 W* k& t; m; J( x. v; `
safe_mode = Off
, m9 U1 F1 R3 w
+ q9 A0 @ [( n* a改为:
r% b9 N9 x/ \+ e' ]. v, E
% E5 X* S+ c- q7 d1 s Csafe_mode = On , l. D8 k/ ?- e- d4 C& y0 c
/ i1 `! O. O j% L这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它. H2 ]/ M' ]3 m/ ?: W0 {! h
的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行3 W0 _% @; d0 t1 m G! h
safe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下:
0 M3 ^$ }7 U% v: v
! ~% L) n, s7 [5 v. |: B& S( fsafe_mode_exec_dir =
; b2 H- f* v V; f# t* |
( W0 ?! P% i0 u+ W: H7 b c8 t指定要执行的程序的路径,如: 4 y2 h$ ?" F" J( y# I9 I8 J4 v
; R, X; _5 S" o& T; B1 W$ I
safe_mode_exec_dir = /usr/local/php/exec ) c3 N7 t6 ?, K( q$ q
& z3 q% P* L* t- y然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行5 w. E1 ?1 }2 ]3 _3 y& p
该目录里的程序。 9 r' Y" M& t1 \, ^: m
# C4 E7 F# W9 S$ {) A: G. f, t8 V
关于安全模式下受限函数的详细信息请查看php主站的说明:
" \% \& n6 i4 z7 ?2 k; Lhttp://www.php.net/manual/en/features.safe-mode.php % M% j0 K5 H9 s$ y; _# d
+ W6 b+ \4 B4 l
3)disable_functions . F* G0 `5 Z7 y3 Y1 X& D
2 l6 K) D$ _6 J& K9 c4 c. ^如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这
2 W' N. Z. z; P# e行: 4 I+ n7 m2 n$ \0 B! d+ f
+ Z2 s K' \6 }/ Y' n
disable_functions = . \6 x# P8 W* r: O
) K$ j8 @+ t/ j- X, x* ~1 @) S- s, }在”=“后面加上要禁止的函数,多个函数用”,“隔开。
- z/ s+ M' ~" g+ @: L4 k1 A7 G* K% M/ \0 \/ J
# V0 o$ Q0 T! m" b- r
3、修改httpd.conf
p5 V0 m, w H1 I: t
0 I2 W* G1 C" m. ^5 ?8 i如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作
& }$ L% o& B$ \: x& {9 W# u, W路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行:
/ ^9 U7 y4 @" T r. {2 @! \: |
8 N2 L u3 F/ i; s% c<Directory /usr/local/apache/htdocs> 9 m+ S1 C! U, Z1 z- P3 C% O' v* T1 ^
php_admin_value open_basedir /usr/local/apache/htdocs
& W8 T f% E& \$ q& n& h</Directory>
* L. P! @% e. z/ O8 \, [/ V9 m' A4 y9 S @8 D3 d
这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打' z) _) O0 s, j* A3 Y3 ^0 Y/ ^! G
开的话会提示这样的错误:
0 a" ^4 e6 g( P; y1 B4 m
- [1 k3 l- z1 y: OWarning: open_basedir restriction in effect. File is in wrong directory in ! z7 W( O% S) j$ p6 S1 z5 t* r
/usr/local/apache/htdocs/open.php on line 4 $ J: m) E5 e: E
% I( S* @/ ~1 p" \, S) r* }; y
等等。
2 G% ?: H, U& e* b
5 |: D! W7 j5 |. C1 [9 F. v! U' _" w; s+ W
4、对php代码进行编译 ) U! j3 o J X$ [6 m! j; u
+ A) O0 h% F0 X- r- DZend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和3 ^* x4 Y9 u7 V& o6 o7 h0 h
ZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就$ |9 W2 g- z2 I
可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统
8 P8 d7 J: D t+ Y! f& \0 S:
1 Z' B1 m0 R0 c! w! ]* y4 A( g! Q
ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz 9 W ?6 J- Z3 ?4 O! ^
ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz * P6 ~( `6 J3 z! o$ d C* N
ZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz * u0 Y" {6 n5 Y% f Z/ A% U9 ~$ n. e
ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip
& {8 b/ ^: ]5 E8 _- Q
8 V8 v* |# t! f2 H% L; y3 w优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里5 h# n( Q2 E p
的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句! n) O0 [% `4 `% Z N* ]
:
1 ~* w& j7 k$ `; d" {8 S
7 g6 R) b" b# P5 G3 Wzend_optimizer.optimization_level=15 & D1 W5 H( X( |# G4 ?0 T6 ` B- e
zend_extension="/usr/local/lib/ZendOptimizer.so"
# {; N. a1 P# q, A+ m
s, A5 @( |3 C1 T- b就可以了。用phpinfo()看到Zend图标左边有下面文字: 1 k4 J$ J3 m) r$ L
9 D/ H7 |0 o! h9 }: F. X4 B9 [0 w
with Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies
9 B3 @6 N% j2 I8 E9 W
6 U( N3 f% @( B8 S$ \4 C那么,优化器已经挂接成功了。
) w4 S9 a, }' H5 ^$ V2 q5 I- \
1 e* b# Q, J, }: b8 e" I; B但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设
+ k! b6 h0 ^ {9 Y! N计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。 7 U- f; ]7 B3 h
7 t1 | w8 i& z" O2 ^; w
php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进% j+ M7 b# h/ k+ d
一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如* U* s( u! C7 Q0 c2 F# ^
mysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。
: f) u7 e4 n* _' m" h3 c0 k! d$ i! Z; N9 K4 p s5 M
3 c' Z6 o7 }: l- }7 M
5、文件及目录的权限设置
/ T3 Q; Y; k* { y, |( c
x4 f; I7 E1 y/ t, dweb目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,0 j' u% j4 M' S: ~ U) D
攻击者可以修改主页文件,所以web目录的权限一定要设置好。 8 {# t1 R. Z5 n0 p( O: ?" F2 ^- Y! P
5 U3 R0 L$ i8 l7 n, T% ~8 b, A. ~: R3 P还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属
# k( }1 q' h4 k7 Q$ E' b主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的 Q b2 ^8 j; c8 X) L5 i6 H7 L
错误:
5 L8 Y( j2 z, L4 \3 B2 [( g2 b
; F1 t2 o1 E7 d' Q6 {Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not 2 `4 `; v# V: `# h' N
allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
0 O. D) g$ X( \on line 3
7 C9 @; v: `* z3 Z/ k; e* Z8 ?+ H* f5 Z, C+ f
这样我们能防止许多系统文件被读,比如:/etc/passwd等。
: s% _: _* u4 r, ]上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。 8 C2 S+ x! F3 N5 _+ F, G6 D, h
: |# Q4 A7 T% X
; U6 \- J2 J% t# [6、mysql的启动权限设置 ' @6 y* t4 o- ?0 ~
) F3 _5 [) M" \5 d) {: P/ X/ _
mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等
6 S6 d6 [' H/ ]8 S+ q" K( R系统启动脚本里加上一句: 6 ?, `5 U6 R( r0 J# Y7 N
# C$ ], H6 C. r. H
su mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start" , Q7 H4 p e* F) L& f
4 N9 k) Y6 m- f! U& i/ I/ p
这样系统重启后,也会自动用mysqladmin用户启动mysql进程。 2 i7 z$ Y/ o/ T( \& [$ G
& w6 d& E6 D" O
' r, w7 }4 Q4 O+ m3 `# b8 R7、日志文件及上传目录的审核及 # N( k; P5 C* V9 q) N
* o7 Q Y4 F6 ]# k查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且
* I4 W0 u' {* \7 g; s u也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非4 c4 }5 U+ {# s9 H3 p
法的文件,比如执行脚本等。
4 ?* U1 q$ j0 i% ~3 u @0 `0 t- m2 V# w7 W5 E5 b+ m
/ F" L5 v; m0 g2 Q6 U9 ~0 U
8、操作系统自身的补丁
9 ~( l$ |! |' d
1 T% l4 ]8 r% K0 O( K' P一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。
! l2 y9 W+ y t$ `' v4 w" @5 ]
# S' L: s# s$ M# C& r$ W+ T
- ~" d$ V. U4 \% y4 i# [6 c% e经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,
$ X& d( i6 c/ p5 c即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。 ! A- c) E! P* k% O* b6 ]9 k, }
如果您还有更古怪,更变态的配置方法,希望能一起分享分享;)
5 F6 Y' I1 x) V" a% x. |3 y' a, f( c* ~4 N2 ?" j/ o3 }2 a# h
; z* T8 E5 d' ^0 `: t% D7 W参考资料:
\8 ]7 I5 u1 n4 d' y- o* [PHP Manual # f: s/ r7 p2 c1 w% Y
http://www.zend.com |
|