|
|
发布日期:2001-11-27
8 ^3 B7 n; f7 K+ N1 R% J6 F/ w( C0 e文章内容:
' }) Z' z/ K8 f9 e8 z$ H! q2 R--------------------------------------------------------------------------------
4 J3 ^4 s; b0 m3 L. X) j1 H) A9 I8 R+ e \- ~: a2 A
作者:san(小许) san@nsfocus.com
2 n4 T+ I$ ?/ h1 k+ v0 f* p( ^* v7 F+ L5 w
--------------------------------------------------------------------------------) x1 c: v; m' Y l0 ]4 \9 @
9 Z+ N+ {/ p( ~9 w4 g- I8 ~6 p
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以
( V0 t+ L" [" u% M& q8 ]. r及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配4 O ^4 ~7 l2 L
置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的
: b( ~3 I! n2 _6 ?过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的
+ F9 k4 B+ c6 ]. [; C C; yphpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现 `: V8 T) B( f& `; J
在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题6 F( ?% T% H* M8 P
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。
6 I+ Y* | ?' q" S+ r: f( V ] s3 z3 r/ u$ M O
, I& Z* K( J4 q C/ M# x6 l
1、编译的时候注意补上已知的漏洞 , f! T7 U6 @ B/ t0 ^. @
/ L2 G9 j5 _! }* ]3 M1 T从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突5 ^. t3 V" @8 h$ @2 a
破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源
8 ?; V4 m% N+ ^" b4 B码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件
1 V n2 p9 b4 G+ i的第152行,也就是下面这行:
# Z5 c! n8 F/ n, A+ r- [ I% i$ Y1 ?" x& }
if (extra_cmd != NULL) { ; v& b" x5 @6 Z' }* M* D
" r* h4 L8 @% n% ?. S. T
后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php & j$ R: b( ^9 o: l: O
那么我们就修补了这个漏洞。
2 `5 j8 c9 f! p; `# ~( i* B1 e
% R! u7 [* n5 C+ }* N; b* u7 U( ?* f* V4 y" s; h; I1 b5 J
2、修改php.ini配置文件
) x+ j& ]6 q' a& }! @% g9 t9 z
6 @( p, W( ~( o2 K! [# x以php发行版的php.ini-dist为蓝本进行修改。 1 U: `# O/ r+ {2 Y; e
6 p' k, J/ Q7 M: I! }; ]1 f/ e
1)Error handling and logging
% c) G$ q& G- J) ^, u在Error handling and logging部分可以做一些设定。先找到: 5 U r' n, y, L4 r" G' X: d6 ?
display_errors = On
: g/ A u( i" e: j. t
. t$ {4 t' U% a$ g _: X3 G& m X0 Zphp缺省是打开错误信息显示的,我们把它改为: ' }0 @) F" p' v, \& u8 F( }' }* c( x
: @2 y, z& @! F. L: {
display_errors = Off * _, Y9 |6 T2 Q* {- w7 r
9 L4 |9 @1 R5 [; w: X4 R0 Q e
关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻) _: O, S9 }4 L" Y
击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造 H! T8 {/ ^4 V) M; S. Q
成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以; d( G9 M \2 \7 e# {' v
下: 1 y( }8 c% b( D
. v5 ~, P4 X" j6 H- `
log_errors = Off : A6 i: @ t8 T+ p! l9 X7 q
. F3 e/ J8 ^& i/ o9 \. F改为: `( ] M7 _" g2 M6 u5 v3 z' i
log_errors = On ; Q3 f ^$ p4 N( `/ H$ W: T1 i
: r7 Q$ \6 |. i以及指定文件,找到下面这行:
0 H( t) S) Q( d( e9 S# l0 n. f. ~" ?: ?8 G& t
;error_log = filename ) e$ C! h5 e* e/ K
' b" H! c- ^0 P8 u$ f0 Y
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log / S+ \, k' W8 X7 H
' s* y+ L+ i( s5 H, nerror_log = /usr/local/apache/logs/php_error.log
! A# M, g4 R' k2 x* m
( H X; x7 ]+ T' U这样所有的错误都会写到php_error.log文件里。 $ _. f7 k/ ]* y7 S
- i2 O& ]7 g' c5 U$ \/ W2 V2)Safe Mode ' `! h4 W1 V! p2 a2 T
+ i3 _9 `5 x$ @, \* i/ @1 N& Vphp的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在% b3 P; [$ e5 ~# a" a- i1 d @
Safe Mode部分找到:
4 d( z$ `2 j% d2 p9 Q6 p; j) j3 B3 r t% |5 G
safe_mode = Off
! L9 O. s: l% A
% R q; r+ ]6 H改为: * h& h4 n# ?4 x6 P* b, S/ o
4 z% |' t; K6 m: h: B
safe_mode = On
! `" g4 ]! {& V2 S% ^/ n3 z0 O
* N- t% N' W$ U. C3 j5 ?这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它
* e0 @2 ]& c1 d' H. L的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行
9 ?* O- ?# P; i9 y8 \$ n' Gsafe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下: 8 h# L8 T3 v2 S2 y0 @* I# X: m9 W
1 H! q5 E) _% Z; r0 psafe_mode_exec_dir = 5 a+ B: Z5 K4 S4 i; ^
( M i) H! R$ n7 e& i
指定要执行的程序的路径,如:
8 X9 c8 b% w" }: V2 s6 o: a2 V4 T+ B5 }. |
safe_mode_exec_dir = /usr/local/php/exec
/ X% s. k4 N5 i3 r1 p; S7 e+ A
2 R( n, M' u, }4 B然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行2 c s# Z+ z. D+ d7 P
该目录里的程序。
; b7 t5 ^& o3 N/ N
# e2 g( Y i0 @* u" V" l' X5 ~; b关于安全模式下受限函数的详细信息请查看php主站的说明:
5 e. F$ f2 M( r" n5 rhttp://www.php.net/manual/en/features.safe-mode.php
' _4 {. t( [8 X
9 ?$ C! ~$ p5 {; {6 P, M3)disable_functions $ l" Z* u$ g" F! H3 p2 A
7 e# F- W9 B" u2 B+ H5 F
如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这
' w" ^7 j6 S% J* E( n行:
m; J7 _/ K. H' I4 ^# S4 [0 I% E7 R r8 F- P
disable_functions = 5 [! N/ f0 z @* f, }7 F, ~
5 B$ t# b+ j3 k% w在”=“后面加上要禁止的函数,多个函数用”,“隔开。 1 A0 x. o! y3 i' ^1 b0 p% [
7 s6 n$ q* N Z8 q) b( T) x3 p3 F X
3、修改httpd.conf 5 v5 @2 ^! ~* ?
: _1 t- N+ L) X0 |
如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作/ }5 W$ e" J, H0 Q/ D {) `
路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行: ! E0 h" O2 B- ?! J* K) `
( B; F$ c- j# V7 Y& F% i/ J$ _+ R
<Directory /usr/local/apache/htdocs> ; E, c w& h ^7 C5 {9 X
php_admin_value open_basedir /usr/local/apache/htdocs 9 _- q: S& e8 f* S9 y$ p: h0 }
</Directory>
# N5 @, h8 C. [) b
& c5 y k U' ]: d) B) v这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打
& Z, d7 [% P G开的话会提示这样的错误:
: B3 w( ]$ l; f# S; M$ N$ _7 {% o+ X1 d, E. ?
Warning: open_basedir restriction in effect. File is in wrong directory in # _; F- V7 D5 K+ Z8 A8 F0 y
/usr/local/apache/htdocs/open.php on line 4
. N5 [5 u- @& K f" {3 u8 z4 Z# m3 L. m0 R. o* c4 }8 q
等等。 / e( X$ q+ v1 Q" l9 e8 \- |6 ~
D+ B7 t" S* V8 P: i+ |9 L
/ I f" q8 r" F2 b5 [1 @' K4、对php代码进行编译 + E. v) o$ t, x* Z
- j; g! P; c8 t2 H2 g7 F
Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和
( e1 F& M9 }$ ~& _! ]' ^+ nZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就/ v4 I4 K* w' L
可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统
2 a% u. I3 m$ j:
' O& w3 u- w. r2 m0 m+ B: n: f% q' b: N
ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz a- S& f" k, a f, I( J$ f, J
ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz 5 G. H. o& B1 w1 e) s. j. y3 f: a
ZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz ) k. u3 } o' d2 X9 k/ W
ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip . ~1 W) m; h; z; E7 v Q
! }9 L: H0 F$ t2 Q3 f/ C" O优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里) N+ ~8 u) M" e [
的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句
& [# e* |, O: M( p:
6 u- \8 d- W* \4 B k$ t, ~0 |+ |9 U r! C. t3 x/ T
zend_optimizer.optimization_level=15
" X8 g$ u" X& ezend_extension="/usr/local/lib/ZendOptimizer.so" W, P! @3 U; n0 m* C/ ?8 s
9 p0 [, b5 j1 x. j* A就可以了。用phpinfo()看到Zend图标左边有下面文字: 2 z* ]; B1 U6 u5 c$ H; S
: l; W5 t7 o4 \; S/ z- Q' t
with Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies
1 @8 z6 R# p! T4 F6 d, F
' [) F0 E, ^4 ?9 a- i, S! L那么,优化器已经挂接成功了。 - Q7 a" @' |. }% T6 Y; a; a
# P) N0 X8 R) ?
但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设
: {; n) ^9 g7 c! S& U计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。 5 y+ n3 |7 O4 ^: w5 Z
1 B* J* b4 Z. x
php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进" w" b- S( ^) `0 Z3 K" Y
一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如: O1 q$ K6 ~# Q( }0 G6 u& P
mysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。
t. a" a w+ o. _6 Y3 g, o. q+ H& a3 t2 u
3 i% x2 ^, O8 L5、文件及目录的权限设置 3 j2 m7 }& w0 ^) ?6 `0 }# ^
G8 A" @: z4 @! u" Z7 [web目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则, F) b% W. a K
攻击者可以修改主页文件,所以web目录的权限一定要设置好。
, n$ O4 Z# h6 F4 O3 p' ~. n
$ N+ x2 |9 w1 C- h! H, l还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属/ t9 |6 L( ^8 }! u
主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的
9 e! y* l5 ~! I5 N错误:
" Q- E8 j$ g* {9 C7 m/ f4 w" I; }9 H
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not * v/ Q- l- ^9 R8 _ R* }0 V
allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
! x0 y1 A% C1 @+ Z. uon line 3
% ]3 @' Q# ~9 y1 w% k6 |, I, q6 u! v z; F; w8 V
这样我们能防止许多系统文件被读,比如:/etc/passwd等。 ( m, i; i: a- S. v
上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。 5 j' T- g r5 k2 \- p7 _
8 X, m& P' {+ h' g9 B! J1 `9 Y6 h, ^2 a" x8 N9 H! J# v
6、mysql的启动权限设置
! s1 ?# ?0 { G+ }9 _
e/ A1 Z+ f* G% U/ r) Nmysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等, i U8 t% C5 P3 J4 G# V* j
系统启动脚本里加上一句:
) I ^+ m3 F/ M3 C$ I/ F% X, H2 |. X7 y, g% f6 Y1 k7 ]
su mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start"
0 j! ?7 ~1 k K. N) r' C' i8 P7 ~+ ]3 Q' C' p
这样系统重启后,也会自动用mysqladmin用户启动mysql进程。 " G. \+ _3 M3 `! r, \9 T
0 B" e3 `4 y1 y# [' K* R5 W: [4 w
. J5 B% ~, w+ j( P: s: a7、日志文件及上传目录的审核及
D0 `' \3 K, T1 `7 y! d, n; H, C; X! H2 ^* C$ ?
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且
9 @0 n# C- j, M9 f. e$ }% S也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非
/ o% S" x( C+ C' S2 U) x法的文件,比如执行脚本等。 P; l! ~- E: F0 G8 ?$ |- E. u
7 g+ {9 e |) f2 ?6 ~ U3 s& s
2 w- y: {0 @" }" u$ P/ r. X8、操作系统自身的补丁
$ ~( k9 g* |: K+ D9 a7 O1 X
5 M! {: D7 B+ S. h& K* O% H+ m) ?一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。 ) O& t; s' @+ c ~
& @4 a7 l4 [; n" q) {: v! X F
. g& u& G R4 [1 F1 g9 [
经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,
% V; F2 f( \: m7 @7 [: _即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。
9 Q3 x/ p$ L0 d6 t% P- _2 u. u如果您还有更古怪,更变态的配置方法,希望能一起分享分享;) . u1 W7 c5 g; [2 ?. t1 N. c- [
D" W0 Q* T4 }: K( {
. s3 u" f' r7 O3 D' z! E参考资料: 5 r2 `; M" @+ S7 v; q
PHP Manual ; }+ ^! ^/ i6 T- `
http://www.zend.com |
|