|
|
发布日期:2001-11-27
% H/ ]: q& l# {文章内容:
# ^2 X9 h% N) a+ n* C--------------------------------------------------------------------------------
! T9 u/ L# X- {5 Z. |1 O
A- v& a. o2 A% K作者:san(小许) san@nsfocus.com
6 e# ^/ a& J) z3 L. u+ K
+ O/ {. f$ q, ?: T--------------------------------------------------------------------------------/ u- b0 H9 I0 D& u
. R" y( a: Q' b% X# J. }. _0 Y9 v( ^1 t前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以
* H, x6 L3 P! e/ Z4 C, s" F4 x及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配
, @# n! U* Q6 K# f5 A置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的
5 X+ m5 Z! Y& @: @过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的8 x& |+ l0 W$ ]$ P
phpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现
( X9 ~6 f6 M( y0 ^* M; f在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题& ?3 ]2 G& R# T- Z! V2 B! P
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 " a% M+ j0 @- N. V# F* o
" a+ T/ |9 V; `1 C. |
5 v: k' G0 [9 }! f' i
1、编译的时候注意补上已知的漏洞 4 Q! J6 v+ y5 P& F1 N
7 E% l3 R$ ^- n% X9 n. }从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突. A6 r4 D, w9 P- S( Q- S
破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源
' m, G' M( F" j( y码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件
`; ^8 y1 b8 d E8 ~ T的第152行,也就是下面这行:
/ z: m4 ~+ e' q" I/ `% p+ Z( D. M2 a
if (extra_cmd != NULL) {
) i3 _7 e8 h8 R' ?( |# U
- R+ N( Y5 V3 B$ [后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php 4 b6 A3 j# }8 r' z- q
那么我们就修补了这个漏洞。
|8 L( s0 l: a' J& k9 i" L7 M3 k0 T$ h: v1 ` P% l$ Y: W' Z
# a0 E4 ~0 a: l8 N2、修改php.ini配置文件
& j. j s$ _) }$ X
7 F! U# m5 k# L以php发行版的php.ini-dist为蓝本进行修改。 . U D, o" J, e9 l( n( H) `
1 C1 u8 r# p1 X' ]6 Y8 c1)Error handling and logging
. D' q$ y q$ G) l. ]在Error handling and logging部分可以做一些设定。先找到: - i; ^7 U9 Z: P$ f" l* E5 q
display_errors = On 3 W2 g. |7 L% M+ F) F A
/ o8 |7 _1 d5 Z; P, g2 c; O
php缺省是打开错误信息显示的,我们把它改为:
! e! g' A3 h; W. T8 l0 {3 _+ X: W8 M: _: B" `! V
display_errors = Off
* l R, T$ T% v
+ V( }: F T6 u l) `# k关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻2 s- N" l* G" h3 u
击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造" ?$ [$ @2 w9 `- f d: [
成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以7 i% Q5 L3 p# l- w( b
下: ( Q s" D. n, Q) ~: Z! T4 b" }/ y
3 l. r! G* {' }: U4 J! L% Plog_errors = Off
$ x E& C9 [$ B9 I9 L" q0 Z% q% T& m: B
改为:
0 A, R4 n7 V" S3 p* N: q# ?log_errors = On $ ^) V2 M" p" ^/ P% W" N
6 v m: Z' `2 W: l- @
以及指定文件,找到下面这行:
* Q) i, Q& Z# v4 c! u$ F, A2 R5 t/ q# r$ x; N
;error_log = filename 5 f$ `# a4 v* k' \% ?* ^ d
0 H4 @2 L% V8 o% ?$ Z
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
2 U% j. ^6 y. G2 K( S0 d+ ]% k7 E% Q% d; ?" z
error_log = /usr/local/apache/logs/php_error.log + X4 {$ | L/ C: `2 q: @8 D9 n
% b/ P" W: Z: n5 C
这样所有的错误都会写到php_error.log文件里。
# h: K% D) G4 E( n" m. }
% d- [2 w9 R) U6 G' i8 A2)Safe Mode 2 P2 O2 N$ o. s, @* E M
/ o. L% N% h& n/ _9 @1 Pphp的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在
, ~( g# x+ c7 P2 T0 y5 uSafe Mode部分找到:
' ?/ v& Q6 G. K1 D" j$ d( ]% R/ H8 d8 j* m
safe_mode = Off $ J9 D8 B- W, ]8 r1 H6 Y
) b( H. Z+ t# V改为:
3 y9 s0 A0 r0 A7 C) u, y* [/ R0 s; b6 r, y3 D. b" G
safe_mode = On % x+ u5 f5 O- H, @3 n
5 U$ G) D8 O; ~9 _这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它
, G7 R# G; p. U6 c0 [ M的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行, |0 ~8 F$ g% a( E1 I7 k/ m: e
safe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下:
# J7 ^ _+ a! _! J, v" h( q( k# ]5 ?! {3 T% K" v+ z
safe_mode_exec_dir = " S, \4 S1 n* [& V, l
4 x* n! o4 ^: R" \$ x1 G指定要执行的程序的路径,如:
1 {: X; J$ U: ?2 B4 O; Q* u9 @$ e
safe_mode_exec_dir = /usr/local/php/exec
: l$ |2 i, G1 S% A
3 w3 P( T3 `) R3 p; `2 y然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行 f6 u: I7 Q. G0 {
该目录里的程序。
! Q9 k. s1 @( h" |5 O# L6 M9 N1 o
关于安全模式下受限函数的详细信息请查看php主站的说明:
6 [ `) }% l+ J( R! Vhttp://www.php.net/manual/en/features.safe-mode.php 7 R C- P! k! P2 e
; i5 Y' p" \9 x$ |# R
3)disable_functions
: V) y) n; y' @+ M9 t9 o C3 M; u3 O% D" [" Y" V9 b0 u+ B: k) T% i
如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这! i# G: n6 k* E# _3 f' W
行: ! S9 }+ x2 \- h/ ^
9 L# d6 C3 }/ a' M! r9 Ddisable_functions =
) t5 b* r& O4 }: F3 t6 h
6 j$ k! N6 B$ i在”=“后面加上要禁止的函数,多个函数用”,“隔开。
" L) a6 S' k* r2 b( g6 S. T P- Q- b% k
7 j- d" n0 {+ V3、修改httpd.conf $ N' t! a! R: L$ e: q/ n1 p
. n1 s! ^- d3 c8 {! h如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作
! A% x" j: w) G+ u( r7 `( h路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行: & l4 q" h: v5 R K1 o9 m' e: y
2 B _2 l3 X& d5 B- a
<Directory /usr/local/apache/htdocs> , o& Q% ^. n) g4 x, `. e& h
php_admin_value open_basedir /usr/local/apache/htdocs + L8 {* {/ D- j+ c3 F! N# s
</Directory> 4 i0 \8 n- \; T- g5 D2 m6 F
+ N1 `+ _4 A( Y# T
这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打/ D) ^, S/ D0 y
开的话会提示这样的错误:
7 H# U: {3 L W$ R/ c3 p8 G9 i
Warning: open_basedir restriction in effect. File is in wrong directory in ( L' r5 U+ l" z
/usr/local/apache/htdocs/open.php on line 4
" b% E. {) m' i) v
6 p. ]) Y7 V) l等等。 * k# |7 q% M4 C9 e3 l
/ v, Q& Q% O* T3 E( Z, }, g2 g; [3 K
7 H% n# A& l5 ]+ o! G+ O% C, x4、对php代码进行编译
, j( d1 W0 C9 C7 \9 m- Y7 T! P2 r
Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和; k X$ I3 s0 J4 s% h2 b! N
ZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就( S! x. A7 D% T, o' @% x+ R' }
可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统
' J3 l% j* h: O1 E' |: " Q. W# F! P) h( ]4 p% u
; |9 t4 f+ q# x1 o% h$ YZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz
+ o7 p& `* l' Z1 z- S4 T+ ]5 JZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz
( l4 J' \) T3 b- B( @1 ?ZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz
, S$ H H8 o' G, s: G8 A+ j6 |ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip 9 V0 ^) e X* a( h
3 e1 B0 N }- c) w" G! i! I! q
优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里
4 `- v; ~ w7 A1 y: \$ o的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句 L4 b7 v2 {4 b- R& ]
:
. n* Z2 K% e0 i3 U" E
, y, P A8 x6 I! S3 [zend_optimizer.optimization_level=15
9 g, k8 G- X( j' o* {9 rzend_extension="/usr/local/lib/ZendOptimizer.so" 5 K$ B( U$ {6 `" P2 |" ?) u
' R7 a6 c) h4 d6 y就可以了。用phpinfo()看到Zend图标左边有下面文字: 3 h: d7 u* |4 h$ C' o
+ y7 D, l: B9 e# uwith Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies
, J. w/ [! R z. g3 _0 @0 f, Q( w6 q: D' f- g) f' S; ?. n, Y
那么,优化器已经挂接成功了。
8 z2 [' I+ P% i/ [: Y: S
7 ?* e) n8 n( W2 I: N但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设5 E% E% l* [+ x! D1 O3 {
计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。
- q, o; v1 y+ F2 V/ n9 D S" U: ?$ X" X+ p
php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进) p' {1 n. y, h5 t4 z8 d4 i9 k
一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如
# b! ? h/ d* i+ O; ~mysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。 ; Z9 }/ y7 k) N+ `# j
+ L( Z$ U) m: n) r2 k' T# U% c/ @' k# |
5、文件及目录的权限设置 2 Q" D& ^: u" P# T: K# z6 B
. A5 o. \& C' T" q5 Y7 _5 I! F, P
web目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,
' i+ M" ]. f' P, T: M; p攻击者可以修改主页文件,所以web目录的权限一定要设置好。 9 ~1 K' r6 `. i# M6 @0 e& n* C" `0 u
0 R+ L! r& Q: k" _0 `3 x" H还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属
* [& _6 a0 i3 n, @" G0 I主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的
@) c/ H8 Z+ \, o ^# z错误: & e/ w7 o+ {: q# H( j/ ~' \0 F
5 L: t1 P! c. C/ ]Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not 9 J; M1 T+ C! j) d: x
allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
/ M8 l- g5 l' z6 \$ ?$ H& A4 bon line 3 ; R8 x% ^! ]2 j' ^
0 d. Q2 K2 I, M# a4 b+ \这样我们能防止许多系统文件被读,比如:/etc/passwd等。
# m2 S! I8 f7 W# W$ C上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。 2 R- p6 N: Y) r7 h& @
+ R" i# ~: w7 b2 c* ]
5 d) U7 P3 z* l4 \
6、mysql的启动权限设置
8 F8 q _8 |. h! U
# l) B8 `- N" r2 r ]mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等" f7 Y+ D1 d" ~8 ~3 W/ v p4 R
系统启动脚本里加上一句: 1 l7 r& V8 h- b1 v9 m
; c+ l" y# a% |
su mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start" ! P& b6 `7 y" K( @; H
' V Z; P+ B3 E9 k这样系统重启后,也会自动用mysqladmin用户启动mysql进程。
7 r0 }4 o& g% F, p
. J( |8 D& {! \8 L3 W# C+ t) N& O5 Z t9 B# V
7、日志文件及上传目录的审核及
0 Y& d9 j3 \1 w4 W% _3 B9 B* v; t- W+ b
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且0 D3 A7 F+ F2 R9 H" D
也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非: i0 k! p7 ] V. C
法的文件,比如执行脚本等。
/ T& }. J* A4 X/ k5 z4 R' @
5 T/ \" O4 i% L6 d5 u3 O
% ~; }6 G% [6 Q8 S2 o6 F5 l8、操作系统自身的补丁
( {' C1 D) t' f. n4 g& `7 ]0 s
6 |; Y8 L; d) z& n一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。 3 k3 `) _7 v8 }- B1 ?
9 v+ I4 w' X: t, \6 N E& d% ?% H! q
经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,
6 U6 G$ }4 H0 ~% c2 _& E即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。 ( i( N' H+ H8 Q, |
如果您还有更古怪,更变态的配置方法,希望能一起分享分享;)
( N. | @! j/ g0 K# m% u- `$ O! s" }9 ^
6 d( I7 w4 ~! m# S1 Y% W4 U, W, X参考资料: & w5 O( w9 y# o- v$ t) Q
PHP Manual e1 X4 _# H! w3 l* |
http://www.zend.com |
|