|
|
发布日期:2001-11-27
9 B4 | A% v3 ^1 t文章内容:
- J( z' ?, o9 |) L, u--------------------------------------------------------------------------------
/ w) U! N7 Z9 e
5 y( g, O1 S. [" b作者:san(小许) san@nsfocus.com % e) v5 G( z+ j6 u, m8 {2 W
& j0 q: @2 D4 K. C! t+ ?5 z) F
--------------------------------------------------------------------------------* _! \1 f' @' D, A2 u9 D
; R. J5 @ S) o, {
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以" Q& V) E$ n/ p1 W) T
及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配
% F- R1 W% O, L" v置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的9 i; G* S: q* F% d
过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的
" c( r& L8 m8 d/ nphpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现* p7 y/ q+ _2 L$ B
在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题+ V% G$ k! ` |
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 5 U, E6 S4 z% ^0 t/ o+ Z
8 \& D' B H- X0 {4 Z9 `) y0 r( f- i2 e2 a
1、编译的时候注意补上已知的漏洞
' @* d/ d9 D/ R; a0 n& R- h0 W3 `( d0 }7 k' E$ h
从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突" [+ o P H) B2 X6 d% i# f
破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源
}* z9 l" Z; N( N码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件/ _& s( g! i8 @) u
的第152行,也就是下面这行: 0 f' M$ q# c- @4 ~4 A; r% _
% [7 @+ X( T4 S/ J1 v
if (extra_cmd != NULL) { 5 W% s+ u5 @3 C
; b" }" y/ T& B6 v* i5 q) n
后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php
" A' g3 Z8 r$ T3 E/ R那么我们就修补了这个漏洞。 0 [& _" u4 u3 {2 H/ Y2 D c
& |! Z* n* a G, E1 [( S
8 Y* M; K% W; {9 K* P. d2、修改php.ini配置文件
( U& z2 U) m* k3 t
, L2 J' l3 i; x) o; k+ @! X以php发行版的php.ini-dist为蓝本进行修改。
% w! G) C$ M% J
6 f( J/ y! b8 i. g# r, o5 G1)Error handling and logging
& E" {+ |+ A3 F" Z6 O; n' ?( i, s在Error handling and logging部分可以做一些设定。先找到: Q- D/ f1 n) |/ }8 ^
display_errors = On % ~' M* J" q6 Z
* v% E( `+ g" ~0 h
php缺省是打开错误信息显示的,我们把它改为:
z8 r5 H0 T5 t1 v1 X' l
: N% H" Q( Y. r6 ~: ]) s: Zdisplay_errors = Off
( G. v% _/ J/ S; b6 \
) j) W% F8 Z7 G, f" _! v& W0 l关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻
5 d( {% ^5 J* J$ @# N2 H击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造
* O$ W/ I W9 {( C2 k+ m% k# g2 m成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以( f& I5 k4 {, s
下:
- S" a3 h7 d: I7 M
$ r) P8 {+ T% o, Elog_errors = Off
# g+ x2 h# A" V* u7 A. I0 E% S' c6 q" q# K. {( T6 ~- D4 {
改为: 3 }# @0 N r. k( S
log_errors = On " \" o' h, A" w1 Z5 X4 i
$ |- \8 ?( j. |
以及指定文件,找到下面这行: " s& }0 F2 L; T* p+ h
* C4 e+ L8 q3 \4 Q5 t
;error_log = filename
% ?# |8 X B. Q1 |+ q" @# t* x0 Z+ a1 ?; q; c
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
3 G( V. T4 {1 E3 _6 ~* M
# @$ z" Y; y4 _3 o1 j, Cerror_log = /usr/local/apache/logs/php_error.log / O( K* D! t7 i: K C
( h" y* w& t; ?/ d. J! I
这样所有的错误都会写到php_error.log文件里。
% N3 `5 [9 g, l! x3 I! P7 l# Y; U9 E" b6 b
2)Safe Mode
3 C! t2 C! F$ \6 ]9 G$ {3 ]; i3 Y, H2 W& D$ t, C q- a
php的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在: t+ b' I9 h+ K4 g6 e- S- o
Safe Mode部分找到: 2 N4 ?$ h! Q, l
5 B# |' d) f* @% D7 D$ j7 V2 Isafe_mode = Off
# B& Q6 o5 {3 w1 Z9 R! l# D" g, l4 u, m
改为:
$ K+ ?4 C% D! D0 h% g
: ]$ c( P$ X! P/ W4 i. q$ }safe_mode = On
3 r5 Q5 B' R' ?; |& O1 W0 w, Q. t: ]# b9 K& o+ G
这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它
2 ?- {9 D8 M: j. |6 O的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行
3 U1 ~, Y2 V% a6 ysafe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下: 5 l. F }1 a: ^% t
: N U8 E' U. l1 O M
safe_mode_exec_dir = % d, q$ f9 b4 m# m- a) w
# e) z) ^+ o o指定要执行的程序的路径,如: 3 j2 a/ q) e$ h1 p: Z
1 B0 E' B+ F/ v* N' I
safe_mode_exec_dir = /usr/local/php/exec ! _# r' J. Z4 n+ S- q5 `+ W
9 V# J2 J" N/ [! T$ O& J然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行
! j% G( O1 E. ] i& Q# A% t该目录里的程序。
i9 |" V+ r( K& U& O( \$ o& H3 A- L# e( Y, Y
关于安全模式下受限函数的详细信息请查看php主站的说明:
& U* P/ ?( t4 d( n; Q) e/ j& nhttp://www.php.net/manual/en/features.safe-mode.php
2 Z8 `* r1 c0 r: n- q/ Y6 `
# F- j; O# B2 v8 {7 I$ j0 C9 S" \; t3)disable_functions
# w6 G/ x2 {4 Z* g3 A# g4 Y
6 b4 J/ C# d% ~& d9 b9 u# y$ U如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这
5 f5 Z. z- O1 C; F, {行: ! L" H/ I# C( F
' ^7 d2 y# ^) @1 T, C
disable_functions =
4 ^* a, X# _$ _7 P/ H- n$ i" @' K [
, m) [" n' E, b* G' x在”=“后面加上要禁止的函数,多个函数用”,“隔开。
+ C; ?/ I$ B1 s; ^
- I* G9 C# g$ e* a% k! n3 x* ]
, r# Y8 c. t8 G$ A9 `# q0 j8 m3、修改httpd.conf % b9 `7 A9 F& o2 J. L- m
$ s/ l( o% A) w: G2 i如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作' m3 p) `( I/ c3 A) g7 I5 Y
路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行: E" A$ q% a9 m; n3 q+ U0 [( n: l* P
+ X& I" ~( n9 j: T8 f1 G
<Directory /usr/local/apache/htdocs> . t; C4 ]5 u# r7 i3 o- N4 ^
php_admin_value open_basedir /usr/local/apache/htdocs
/ e! Q" f; J6 S7 L</Directory>
+ _/ i( S8 t, M `
2 a( A; W+ Z& o% P. D0 h这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打+ j. I" m7 I& E. `+ \4 \- K
开的话会提示这样的错误:
; E* s, O; V& V) Y
' f- Y* ~6 `- O1 U) cWarning: open_basedir restriction in effect. File is in wrong directory in ; E; B* A; t0 D' B
/usr/local/apache/htdocs/open.php on line 4
3 t" @) h' {/ U0 R' x/ H! g
' q3 a3 t8 f) P6 {2 E等等。
& O1 z, {' C% I) O$ w& f( @& i6 y& T; h
) L+ m Q0 K) A4、对php代码进行编译 2 p8 d( s( |- B1 W
1 b" s" q3 j5 g+ O( D. g. u( O, D8 u
Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和' m7 E# J% S6 C |( ]1 M
ZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就
& D4 N8 L1 o4 J$ J) ?7 X可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统
2 \% ?) z% a5 ^' H:
: [6 N U: I) h* V6 _4 G; ?' B" I1 o9 x2 ]* y) j
ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz : J8 i( b7 Z6 L8 k4 N, v
ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz
% e+ b3 _2 J; k3 ZZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz
" s" \& y. ~! c& a" rZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip 2 } c- _7 T0 ?2 t) Z
- K' B5 w6 t2 s" `' l6 I& f
优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里' u+ ^, ~2 H# U+ U) W* v2 V* F
的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句( J0 Y7 [) o% O8 `3 @
: 0 ]9 J7 F& f7 J% }
4 r( `7 V( h# m/ t
zend_optimizer.optimization_level=15 * ?8 q" m4 x! F# N: L/ J
zend_extension="/usr/local/lib/ZendOptimizer.so" + I; u( z# z( F3 S9 X( `
4 Y" x' Y3 o" r' J2 Q1 b& u0 t
就可以了。用phpinfo()看到Zend图标左边有下面文字: * A3 l% o$ b, Q. l
* p6 @: W- E/ e X/ b0 k( ^( L
with Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies
, J. d; h4 j' h
1 t8 T0 F+ N' S9 |% `$ t* L' h那么,优化器已经挂接成功了。
" q+ H/ n+ P" ?# t: K
% ^: _. v1 i" e5 Q. \# i. w8 I' Z1 A但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设
7 Q7 a2 v8 s9 {" g4 J' {计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。 4 m9 L# T# ~, H( w- {4 S3 |, i
" w& H, j/ h6 o7 vphp脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进. r, M4 J. [; j( `$ z/ U
一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如$ R8 n- Z- S: |+ J1 S5 M
mysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。
' u5 f, S4 Y% H
- l! t/ s, N/ R g3 W/ ~5 V8 Q* k: v9 I, k# Y
5、文件及目录的权限设置 6 A2 p2 Q: M8 M6 R' g
! }( E+ L" c% y- q/ X/ z) R
web目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,: s1 J; ^# C* h' Z" m4 g7 h
攻击者可以修改主页文件,所以web目录的权限一定要设置好。
) T" E; d. O3 J w0 _) @+ w% i) g
6 f [+ O) S# t& {" x还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属
' J3 t d* y: y5 I' z3 b# |主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的
7 ]! u; s2 O$ B: h& G错误: & t& I6 f! Q+ z8 o/ p
# r, s H! R2 K9 QWarning: SAFE MODE Restriction in effect. The script whose uid is 500 is not , Z/ J h8 o) ~7 T8 K
allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
9 g# _* X; e/ u1 B% F2 G5 C. W+ v4 n: \on line 3
: m' H% G! T$ P. k( q5 l" o" H; K
这样我们能防止许多系统文件被读,比如:/etc/passwd等。 # [: I3 w- L; k2 ~1 E+ X
上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。 8 t9 M7 e$ k. T( Z4 {/ H6 E v. y
" N. }# V1 k% s5 D& R Q5 W1 ~
T- ~5 f: y7 @. V- H$ I# K6、mysql的启动权限设置 + P# k. w0 S& J3 C- @. T7 l d
( F8 d: {9 Z' u# R9 v- t
mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等
* s- w. a- w- n/ w; e. P系统启动脚本里加上一句: " \4 x. v6 x1 a
) r! |& }7 L) v& ^1 L3 _$ vsu mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start"
8 I- J( O& q' x5 R6 j9 K$ I" ?' |/ J6 I: R, `
这样系统重启后,也会自动用mysqladmin用户启动mysql进程。 ( I. e& ]6 F- A8 X2 V6 M/ M) y/ o
6 J- w0 L5 @+ W. l: g# L/ \7 f3 n! G6 N+ I
7、日志文件及上传目录的审核及 5 `1 V4 B1 {3 n3 \# A9 Q8 ~, x
6 e6 m" ^- T) y; B" ~8 g
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且
/ X2 @+ Q4 h" ~; @0 l2 H也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非; U# t( _3 ?& b
法的文件,比如执行脚本等。
" a/ l1 N# {* C$ _/ x6 [9 i& h8 {6 s( O6 r' s7 N
0 f' }- @9 q7 ?, ^% S- j& L8、操作系统自身的补丁
5 [9 Y5 H* K* x" w8 O: V1 i2 l8 k* O2 B6 I
一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。
# [/ k! c! E, \' b2 Q+ P8 _& g' T- d' M
9 E; \, ~9 @' _8 m3 x经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,9 ^3 ?, c, s% u7 B5 y, g8 _* H- Z8 v/ ~
即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。
( y- V! j; J* k如果您还有更古怪,更变态的配置方法,希望能一起分享分享;) , N! k5 x$ |8 W: o
% j$ r$ I, C5 ]' ~: U
3 h, L" O6 [- u
参考资料: 1 Z- P" W$ q0 i* j
PHP Manual 2 Q4 G3 B" D" q7 [0 y& W/ `
http://www.zend.com |
|