|
|
发布日期:2001-11-27
4 J: e/ s" Q( A3 s4 n8 \文章内容:1 Z/ p/ ]" N; D, ~. \" t% ~! h% i3 u
--------------------------------------------------------------------------------. U% o0 G, S9 D, {3 [( g
# d- o) K7 a+ O5 b2 n C作者:san(小许) san@nsfocus.com
* }2 H5 \1 \1 _. L, e, F6 B- ^2 Y! {3 X; p1 w
--------------------------------------------------------------------------------
8 l1 H% x! e3 W0 h
, c$ q* q1 K( X/ B. j$ _' x前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以% H7 t3 k7 r8 L* M
及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配! U$ ~. a- P/ S. N1 ~4 M
置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的
8 S' n) A* N; _' h9 i4 J/ |过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的% Q" k3 S" ^5 N$ b
phpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现
$ ?( `3 a0 X$ t) \; e0 c6 }在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题5 e) z4 Z* T: {) v, ^$ F# P3 d
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 / z* M; k3 D) f9 Z+ y$ N7 ?
% b. i; w' o% L7 b% n: L
6 F2 g$ Z, B8 e4 F1 M+ o6 S1、编译的时候注意补上已知的漏洞
- U0 {' u: S2 }! M9 ~/ |
- F! z3 W' B$ z$ e6 c% ~0 p从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突+ {0 G$ P0 a& q# O- o
破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源
5 q' Z( _2 d* \$ x码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件/ a& G/ ?# S) [$ R& S
的第152行,也就是下面这行: ' D2 V9 N2 |, o J d- F
2 [9 N+ O9 l% y+ Wif (extra_cmd != NULL) { 8 r$ D# x1 b$ e) w- q0 F4 d
9 h6 G) T5 S) d1 }4 K8 \7 r% C
后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php 4 |' n+ ]0 x8 F4 s: R( z* \) D
那么我们就修补了这个漏洞。
2 X3 r6 s1 Z* ^/ U5 d$ `) F& r( J/ X! T6 r
- r6 K; J( h M( g
2、修改php.ini配置文件
% W( U6 [$ q7 J8 K
' M( T+ D2 q# O; u" {5 _) R/ L以php发行版的php.ini-dist为蓝本进行修改。 8 t2 _% q! `0 @8 U) \& C8 z3 j2 `
- C* N3 W* I; m- g6 \
1)Error handling and logging , `' h7 a# \# P2 v8 Z
在Error handling and logging部分可以做一些设定。先找到: ) C3 r( J$ e9 s, K, ^) F4 ?
display_errors = On
8 Z' m7 h- e }* q* b& p* G
7 B0 p+ T" b* z2 I+ ?php缺省是打开错误信息显示的,我们把它改为:
' q- c# B! ?" Y ]1 w. b- V6 M5 g5 C# W6 H, B
display_errors = Off 4 Z3 H8 S0 }% c# }5 D
$ [/ u7 p9 D# }+ B7 L, ?关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻
: S- b1 c+ r6 `1 q$ t2 x$ X1 B击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造! }7 L4 l. H/ O( h2 g
成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以
8 H$ Z0 O, j: V! E1 R下: 7 T: l/ @9 s: S
4 Y; s2 \; _9 N, B$ M( clog_errors = Off
& K2 S# ?# W! @" t8 F5 w! i
. c1 Y: J* d# g# [. }! b' [改为: 9 }" W% u5 J, r
log_errors = On
6 ?; D* a4 {, N9 k% Z" V/ i8 i( H# Y; B
以及指定文件,找到下面这行: ( A/ B* t5 Y$ H" o1 b
6 ^4 z2 }& |. P$ {
;error_log = filename
6 `3 b/ j% b) j# O: E7 m5 e( ]$ E! i4 _6 |8 v C R1 D6 [- S/ q
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log - o1 w3 Y# [% h, d
+ I: x7 Z* M( I9 A( Y
error_log = /usr/local/apache/logs/php_error.log 5 T6 e3 I* S- ?8 z7 T" D. D
w8 K" E5 q, @# V- E
这样所有的错误都会写到php_error.log文件里。
4 U4 p: U9 E/ B" j2 }6 I1 n/ V$ @
9 r1 ]6 O( U1 }) b% D2)Safe Mode 0 ^1 Z. r- \+ K' M0 `, A M
7 U5 D+ Q' L' l }4 d* K) V
php的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在# n2 x, t, P5 b+ o: P0 o
Safe Mode部分找到: , C7 M0 L% _8 e* C7 y4 P( O1 o
7 s4 {* q* G! M7 g5 L9 y& H# @safe_mode = Off
( U* U& S" G L( J( o! D: e) h' x4 y4 k. G% B, [
改为:
3 ^, H: ^: A* P
4 Q6 w( f1 G% e+ h/ ?8 psafe_mode = On 6 ^: { C5 o0 y2 W
( o$ x1 \; ^9 C# w; v- s. v' P$ U
这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它) q7 a* G1 b3 R- k: f' [/ y' S
的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行; g. \# h6 D& J( g; W
safe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下:
( T0 C0 b, x- W" f* `' W$ o
) f' I1 E* C% f q( Nsafe_mode_exec_dir =
2 D$ P& d V5 o) D6 b( y( Q0 _; {3 O \, Q& G+ S5 h/ W$ I9 d. L6 z
指定要执行的程序的路径,如: L. U! }8 N6 f
. K: A7 A o9 w/ g; m8 g( msafe_mode_exec_dir = /usr/local/php/exec 3 T9 q' K6 X" @
' M) } y$ [$ _2 M. N4 V* z然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行! \! s; T; D0 v& t( P" T5 S# w& O
该目录里的程序。
* T. x6 T# E$ P2 u5 ^8 J
) Q7 X$ p5 ` b( @$ K关于安全模式下受限函数的详细信息请查看php主站的说明:
6 x* l* O; I& K! B, a% Xhttp://www.php.net/manual/en/features.safe-mode.php 1 M) I# R0 o( o7 [" m, l
4 F. h( B6 Q, C) g
3)disable_functions . N' L+ ~$ T, h, S
% i+ W( i$ l; n如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这
% K8 [: N6 c2 \2 {. |# x行:
' B# r @6 H1 E% z3 ^5 j" o3 g; t- d
O+ j8 E3 \6 S# q4 B% |8 ~disable_functions =
0 F; r) d) W9 A5 P; a7 b! G! @ h: a9 e5 f0 k
在”=“后面加上要禁止的函数,多个函数用”,“隔开。
2 Z2 j5 F k/ i& L8 ]
9 a! O: y2 {; k( I) T, r/ G, u
9 q5 s% o$ j% e) z5 E- `: D3、修改httpd.conf I# P" R/ Q7 }: q9 n
* s: i. j6 j7 |0 M# v6 M如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作# s0 W( U. O: d
路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行: + s5 m8 t: X9 j6 d8 V# m. w# Q3 T; C
2 d) Z& P: _: V7 n3 B/ q. }0 ]<Directory /usr/local/apache/htdocs> 5 o! ^3 o" Q2 \8 R
php_admin_value open_basedir /usr/local/apache/htdocs # A* L, B* E$ V) ^( f' P/ g# s
</Directory> " T+ t8 n, a& ~; t( j# Z
' Z$ u7 [+ l/ U" e5 B
这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打
) q( Q. j4 g0 f0 d$ `! c9 c5 r开的话会提示这样的错误: ' ^/ r( i6 J% S$ s- A1 u# S9 j
8 f* L' x% k: V
Warning: open_basedir restriction in effect. File is in wrong directory in
! P. C: ?& O2 C9 @9 H. L/usr/local/apache/htdocs/open.php on line 4
2 P, K/ a0 I( r8 |! `, ] ~0 W7 E5 t2 D4 v3 A
等等。
* o3 {/ {' c9 s3 c- V5 Q
* |5 v- Z9 W2 r1 |, r9 i; y5 O. d5 ~- P( A( C) u, l# U/ u
4、对php代码进行编译 2 q0 l- X. ~ [# N _$ o8 T6 H( \% `
3 {+ U$ _: R' l; \& m; @Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和( |6 L3 ] [! ?# _: i- U
ZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就
/ l, s- [9 R% D可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统9 |) {' _: Z3 Q! T5 h) d" _3 j/ z
: 9 A; H$ y6 E4 f" A! N, D' g0 L
4 s( T3 l8 c( _" f
ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz ' M( P. m) m( m2 j
ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz & R, d' o) ~ o8 P, j" G
ZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz : ~% D' E8 r4 O5 }, y
ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip : I4 {' G A# L0 e3 O# s4 R
9 i& H8 ?) s( ~; K6 X/ M! a
优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里4 H: ]1 |, m9 S4 g: x
的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句% ~' c0 g8 I, B! J9 H4 |
:
; r7 W! P" ~: r
' |# r2 c K! O$ o9 f7 d* k+ g" Fzend_optimizer.optimization_level=15 5 Z, I6 V# I4 a! L. \; x" x5 A; u
zend_extension="/usr/local/lib/ZendOptimizer.so" & F0 Q: U7 h) r
u- P- W+ o& t( V% S* `5 `就可以了。用phpinfo()看到Zend图标左边有下面文字: - _; W6 W& @, K3 m& @* W/ ?
2 L) X# k7 [/ A8 Z
with Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies M* K w+ H* z- U
5 s1 p: X( I' H4 z1 s. c那么,优化器已经挂接成功了。 6 u" r9 \) ]- d
4 U5 \$ t, A; E1 W4 h) p2 n但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设, [; @2 n( k! Y* p8 E
计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。
$ k( U3 z. p* O" ~
: s3 j, ~; z" T: ^* x+ W& ?php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进
. y" ^( T* E8 B1 h0 X+ L, O一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如
$ @3 B, U- \7 m* Hmysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。
1 i3 e2 @. ?4 v2 }3 }, `- H1 y& \9 j" k
: N( x" \& L6 d0 p+ A( V3 s5、文件及目录的权限设置 ! W0 Z& a( f" r. y9 J, ^/ ?
; X6 R$ b: ?& v# F3 d# g' o0 Jweb目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,
1 n. T* D: a( p# N# T4 P0 h( f' \攻击者可以修改主页文件,所以web目录的权限一定要设置好。
5 P. Z4 o" _6 R! X6 H* b, K+ j1 x, ~4 }2 O) j7 a0 D
还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属/ ^8 o+ M, P5 R% ]$ W3 l
主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的
3 c- _2 f0 U- j4 k) |错误: $ V! R( C; F. u* `
" V, P6 r, I" s% F# P; ?" @/ x
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not 3 X; V' m8 U r7 K* {
allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php 5 V5 p5 \' g x3 r
on line 3 * h$ k/ U$ [8 z! B5 a
5 J0 Y3 x. I% x. o2 a
这样我们能防止许多系统文件被读,比如:/etc/passwd等。
+ F. b2 t8 T) K" ]) W$ p上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。
# H+ E3 F- G! p. E+ N6 k" L- }( x: @5 i* Q Z# S( i* e! C: H2 @
9 ]3 D- V6 H6 l. s- z4 _6、mysql的启动权限设置 + G/ y5 R. q0 z6 |8 x; z
# ?& A; y8 v$ s0 s) l; |& v5 R, ~- r
mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等' W! ?5 {" U8 U6 Z
系统启动脚本里加上一句:
1 j6 U9 K; M) b$ E) A
6 I) W. Q( D/ S. m/ I3 v isu mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start" ( Q+ A p; Z# s1 p
' q. `: e3 a F# y2 q这样系统重启后,也会自动用mysqladmin用户启动mysql进程。 % P" h0 |- A5 q% d0 m
5 ~8 u" G- b/ @5 x4 r2 @2 n
5 U& U E6 Y8 k7、日志文件及上传目录的审核及 ! Z% H% ]( U5 j) X. }+ H9 l
2 }6 p* N( C2 }0 D查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且' I7 p& t1 s( k# W2 g
也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非
& N& r1 N$ [0 @法的文件,比如执行脚本等。 * V. r' n9 D, L% j7 {$ k4 f& P! _
$ M o8 V* C6 F! `; t* o8 n# [1 v8 z
8、操作系统自身的补丁
! z0 L: Q g ]/ Q4 O5 v# L: G7 D* Y4 k+ V3 P+ M$ p
一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。
; q& y: S) R" x! K
, J# @) D$ F) X; h6 x$ w6 f: y
, ^ _/ g2 g- A# _4 [# N( S, E" Q6 g经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,; T+ X' j# O: y4 c; d; v
即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。 + ?% \8 t8 H" A1 B! H
如果您还有更古怪,更变态的配置方法,希望能一起分享分享;) ( b6 f+ j; t. y7 y. |
$ X Y; i1 T5 y. Q
6 u( c( p9 @' }4 s2 O% Z) ]
参考资料: " v @! X9 ^8 g, w0 F' K z; |
PHP Manual
- k& I9 l) i+ { n! B; ]7 V) phttp://www.zend.com |
|