|
|
发布日期:2001-11-27
6 G, \# ]. l7 E8 h: d' A+ i文章内容:. G0 W# v* e7 K* J. g5 z2 G
--------------------------------------------------------------------------------
* Z1 x A/ n# G& b: l4 i
6 G4 G2 [1 W$ j& C作者:san(小许) san@nsfocus.com 5 w9 `4 p3 H$ f3 N( n* N
) O& Y$ s- x3 Z. X-------------------------------------------------------------------------------- h; K0 e3 q( [ D; @! V7 M
+ b |9 G g, G$ l3 i5 y' n
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以
5 e- k0 W; d' H. e! E及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配
( _8 s7 M$ V% A' |: Z- z置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的
2 u9 N7 C, [: L/ |) X. ^' p过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的
& c7 b3 q' @2 v" v fphpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现
) G% Y+ g9 K4 t5 U+ V. S" k在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题3 e* u' }" E4 Z
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。 & S, G* `$ Y. s9 B' r8 o5 n
3 X6 a* ? m; x) n+ Y2 q
2 k# O% u2 d0 b8 N3 b0 M1、编译的时候注意补上已知的漏洞 D/ @, Y+ v c `7 |
. q# L( l$ F0 j, q$ Z( o4 [! `
从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突
4 _ H: ~" b" F$ K破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源3 J8 U# k8 m8 u: Y* Z; A0 |! e- R
码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件
: m7 r4 P$ O3 ^& q1 p- ^4 z的第152行,也就是下面这行: " P: _6 z% m- y& ~- }$ k3 a
+ ^. k( Q+ r: B- ~ c
if (extra_cmd != NULL) { * u9 G4 n) V) i, S3 a5 D
: b/ e$ b+ ]; r5 `3 W后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php # C0 y+ Y/ Q7 F, H! d% w4 n
那么我们就修补了这个漏洞。
" p( X' C3 {; C2 i
, g0 S6 |; e+ L$ ^0 E2 h) C! j' n9 R3 M- [
2、修改php.ini配置文件
6 P3 Q9 \; \, Z* ^; _1 m" s5 v: A2 { s( M i' Q# A
以php发行版的php.ini-dist为蓝本进行修改。 % n/ _1 @7 [ Q) l
0 U Y2 k# o% n M
1)Error handling and logging
7 e( A( r% e5 S在Error handling and logging部分可以做一些设定。先找到: ! H) o/ i7 o: r' c- P
display_errors = On
8 k- W0 r( g7 M( Y6 M$ X/ B
. Y+ @1 w) z( r/ _php缺省是打开错误信息显示的,我们把它改为: 1 A1 `0 q9 t9 W3 y6 h8 @$ f
6 M' |" H2 H! T) O% t" zdisplay_errors = Off
3 N' R7 t" B. T0 P9 k
( T' h4 ]/ R$ }2 e+ r; v关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻
: q% p$ f' |1 b9 p击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造
7 L. t5 r+ M, ]+ e9 I成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以
: t7 `& O u+ Y- m. M" d下: 5 s. H3 S8 m% H0 h- n
, q8 o, C) i2 s2 f, Y( Ylog_errors = Off
2 d" u/ b! Q7 k. b# w
$ S, k3 b9 D7 K: y( h改为: % O. p+ d6 r& D3 _! f* s, k
log_errors = On 7 ], j- J" `6 d! r
! o# }; f E8 d% i q' z& o; |以及指定文件,找到下面这行:
! {+ j/ U6 \! |' _
9 n' ^$ B( D6 W;error_log = filename , ^ m& Z* s1 @$ f
& Q- R' L1 v7 @. c. V
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
* e% Q( O# l5 ~( I3 e* R* ?5 M: F' i$ L P( H' f+ }" m
error_log = /usr/local/apache/logs/php_error.log 4 ?( f# O- F5 K+ c
! {( F! s( Z/ x3 C9 b/ x: U% ]这样所有的错误都会写到php_error.log文件里。
* m, [( a% o6 P+ W; [9 ~4 F) o: _' S6 v5 L! `# s
2)Safe Mode
: Y; ]2 t6 C! L, L
& f7 O, v4 I% G. d7 Jphp的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在
' q4 d% d3 e1 K) A, z$ [2 S' WSafe Mode部分找到:
9 d! Q* ^. s* {1 |2 t% B
+ u5 [/ y) |+ x3 |3 Ysafe_mode = Off - i) W' r; x( x$ e" n ?3 C! N
# m+ p3 N: Z' O改为: 8 R/ m+ P2 E9 s$ |0 h
3 Y% w' o! ] ] I
safe_mode = On ) o T* n+ |" [ K2 ~& q7 C
1 p8 _, }+ K8 R% a7 ], z这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它
/ `* e4 j) g$ J, {5 P% {- Q6 L的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行( w m7 }/ w Q$ {* k$ \
safe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下: 9 j; t( y, X) m
, {/ N; N& x) }4 `% S/ R
safe_mode_exec_dir = : Z8 P r) s- R& `' e$ g
' G. i, U1 @5 X4 ^; A, G* e
指定要执行的程序的路径,如: : l+ ?& l6 f2 A& Q
! N& K- c, B# \8 V1 ^3 r
safe_mode_exec_dir = /usr/local/php/exec
" r3 S( f7 S8 I5 O
, @$ {- Z4 }* r. ^3 o然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行0 A: ]( e v, g' L* B
该目录里的程序。 ! w% P% I! G' {. |4 P# V
$ s. @! T, J: R+ ^关于安全模式下受限函数的详细信息请查看php主站的说明:
# Y1 n2 Q. ]) o: H. a2 V0 Shttp://www.php.net/manual/en/features.safe-mode.php 8 E5 `8 i0 M2 ^- y! ^% l' i
8 k% U) A P- O6 J4 a/ O! A3)disable_functions
* [8 p% y9 e6 Z" O, Z
2 _" t9 v2 c; y* a+ W) [) C' Z如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这
! J: X; I7 q! o; R行:
, p6 \$ @( [4 H0 E* } J
0 j! f* M1 [" y \4 y7 Rdisable_functions =
4 A$ E: ]- P! n$ M+ f* x8 ~1 j6 Q- ^
在”=“后面加上要禁止的函数,多个函数用”,“隔开。
2 v8 ~7 q" r0 f0 `9 A3 f% T1 i x9 R2 V. n7 N
! H' S) g5 i2 O j
3、修改httpd.conf
2 E6 l0 C# K: x/ W
9 N0 {+ X2 D0 I/ D8 B3 T如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作
. E) q/ h' i8 P路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行:
; Y5 c. m7 ]3 w" G& Y3 K
# E: S. k7 g% x7 \<Directory /usr/local/apache/htdocs> 4 X. |' H- P8 W. o1 y. e
php_admin_value open_basedir /usr/local/apache/htdocs ( r& E& o8 \: H
</Directory>
* Y0 p2 z+ B5 f( w+ x; s4 d6 N
6 ?- n% l2 |$ c这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打9 i3 \1 L* r) M+ G! i; P( E
开的话会提示这样的错误:
$ x T' X# f& S% l* b# I# I) g0 y; k X ]
Warning: open_basedir restriction in effect. File is in wrong directory in ' e* L) U0 ]/ `# `: J4 B
/usr/local/apache/htdocs/open.php on line 4 0 f' ] S! F1 o" V. W8 |" l; b: u
9 s0 ~% Z7 e* V- a Y
等等。
7 i2 Y. i! y$ G2 s! g7 z! ^: Y( t9 P$ l
, f% i! l( o: C3 e$ _, Z5 w. p4、对php代码进行编译 : f( Y6 F2 S0 X9 z- B; g
: G9 O0 z" {* e5 ?
Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和
9 _- { w! ]1 a. n7 Q, U: a- AZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就$ B% f& x" }! J: P8 E7 ?* E& S# ]
可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统! F. V6 W; }( b8 M
:
6 b, P5 M* r& k! L9 C( y/ S' G" k4 Y: j; u1 K5 X
ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz
) \. A* G5 i9 Q$ v8 J! V/ MZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz " Z+ A% X, ~9 w- Z/ K
ZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz + ~2 J5 i0 d a
ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip 3 B& E7 |' V. v4 s/ U: g* j6 k T. L
/ K: l$ l7 t% x9 t
优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里$ X- S8 c. ^9 R. J9 Y; A: v* }1 h
的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句/ j" v* K4 B- [7 f% D# g/ W9 }
:
' \. g0 ^' Z1 Y: z0 \! y3 L
4 Q% Z; \$ R- W$ n0 u1 B5 lzend_optimizer.optimization_level=15 ( N9 q N/ W; Z7 J7 D
zend_extension="/usr/local/lib/ZendOptimizer.so"
% u/ G/ }* a- G. p2 i# B! P) S: R; @6 ]4 c
就可以了。用phpinfo()看到Zend图标左边有下面文字: % h0 `" Q& }* X2 a3 r. T
( B- E7 @( _ S! D3 Qwith Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies ' N% Y X" m4 k: Y/ G4 E# }/ q' g( c
# P4 }& p" Z, T# i3 m0 ~: T* ^. j那么,优化器已经挂接成功了。 / y( j, E2 ?5 n0 _0 D+ g( [. e
8 h: d' E7 b7 Z. C# Q1 U u
但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设
2 P. `& E) J5 n* D# t计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。
/ f; I7 S9 ^$ O) p' M# H3 \4 x- B2 W( H& a. x4 G* W5 [
php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进
6 X) W# h B: Y一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如$ K/ ?. I2 x& G/ |0 P5 F
mysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。 ( ?1 g( K6 c& |" O3 w: |( }3 h
3 ]2 _) i+ f3 I# H, v
8 b, `& T6 \/ Z# X6 G' C! A5、文件及目录的权限设置
+ o! C F9 K u' g+ f9 L! m% u4 j
web目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,2 m3 i1 \7 p$ q! _3 G: U% d
攻击者可以修改主页文件,所以web目录的权限一定要设置好。 ( A9 J: ]+ v! R
0 F4 K) m6 ?; q8 ~0 I
还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属
, G: \0 E) i7 x. W) _/ B! D4 o+ v主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的3 \/ z& T. e% P' |7 l8 C$ Z
错误: ; `$ P6 H2 Q8 g" F! C
+ J0 h+ C' t& `, K* |4 Q' |" L) a% \Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not
5 Z* ^5 v* o7 i# {allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php 8 b3 ]* K& M3 m0 x
on line 3
' |' L: D2 J0 E; v# ]5 S4 M# c1 e
这样我们能防止许多系统文件被读,比如:/etc/passwd等。 ( M- j' w* m+ K1 K5 m! `$ t
上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。
# A1 C& A1 I7 X! i- D% y5 `9 j* d* U y( v' Z+ F2 ?% I
: C0 U7 j7 {. b, R+ `) N6 Q2 a
6、mysql的启动权限设置
! e* j* ]: T( I) p; y! H: _0 k% ]4 N4 y3 L
mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等: p4 y; R) j) ]& {; B8 j" C0 j
系统启动脚本里加上一句: 5 o7 m, H. e' k" F0 H8 |: C5 {
( \! d! s$ w) I3 U* e
su mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start"
5 O" R7 x7 j; Q9 t. N$ J
! N$ z4 P |4 j7 M% L这样系统重启后,也会自动用mysqladmin用户启动mysql进程。
, P! J7 `' L8 V$ q( O# t1 W/ k) f- y2 n& D" \* R$ W& r
7 I/ S, u. [, d( {4 j2 y, ]7、日志文件及上传目录的审核及 4 D; c6 f3 Z1 c ]
- h/ C) N; S7 n) k) t) w' n% a
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且
$ x$ |' N4 Z5 R4 g- ~也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非: k- K/ F; _2 R; C% Y% Z
法的文件,比如执行脚本等。 4 W& X+ J# P; \! ]" }' v6 q2 ]6 D
" s) @. Z% F/ B
* M+ w9 R5 x4 |4 `4 V4 ^+ L8、操作系统自身的补丁
+ _8 ]3 x$ z3 X7 p2 z9 B- E6 G* z6 Y# @& R& E! H& b; v; I
一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。 . n% R- b, _; g# x. j4 e$ g: q) Y
$ O8 ]$ f( R5 z+ E$ L9 ]3 z0 X) e( S8 l4 X
经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,9 y/ |5 s8 _ _! ]) ^
即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。
0 A% G: y/ m/ k6 o8 Z1 [1 k* L如果您还有更古怪,更变态的配置方法,希望能一起分享分享;) ( e6 u# r4 ]# E% X
5 r0 J; a+ b7 v K! R2 x5 M
2 |5 F9 Q5 q7 N/ L4 S* R4 t参考资料:
# o- `' L+ a: qPHP Manual & j+ Q6 V/ d: \4 \6 `& J
http://www.zend.com |
|