|
发布日期:2001-11-27
+ C* u4 F+ x6 H! M) ~$ n6 U( a文章内容:
* q+ L; y# o) I6 E! J* n--------------------------------------------------------------------------------
2 m; K& Z1 q! P( X0 G6 ? }6 K/ O x4 [' @
作者:san(小许) san@nsfocus.com 7 J9 j! n6 ^8 S3 M# p0 E
# x& z0 g7 H& T- P5 Z2 @ {. p--------------------------------------------------------------------------------$ P5 l# z, l" m* D1 [
) n: o8 e' z( L' V, u
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题,以- E- G7 L: x+ L7 \9 ^
及如何通过应用程序漏洞突破系统,这篇文章我们来通过对php的一些服务器端特性来进行配: \7 }. p, V% ~2 C2 p g
置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的
' K- q* W! [# T$ T/ x: P# I; z过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的
' R8 Z3 S% E+ Cphpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现9 @0 G6 Q5 k7 w
在我们假设php脚本已经出现严重问题,比如象前一阵子phpnuke的可以上传php脚本的大问题8 S" a% ~( \7 }
了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。
9 p/ `8 e L$ H" B$ l$ _3 p7 s. N
3 N/ v# ?; S" l# H, L$ J4 {8 K+ Z2 k0 s7 v
1、编译的时候注意补上已知的漏洞 0 L0 l, @" \& U; Y
8 k a9 ^ O( K+ ^
从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突
' ?% P) F, s$ ]) H' w) U破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源, \: z. E9 ] j2 F' k
码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件
1 Z. e1 ~' N! [8 U9 j+ s6 b8 e' Q1 w的第152行,也就是下面这行:
# s( Q3 ^' B- l2 ~) S
7 p3 p9 a. ?+ s& x2 A5 k. D' G4 `if (extra_cmd != NULL) { 2 R( N% I! W2 o4 w: A+ c) s
\/ I) A7 Y, W# Y8 M* U
后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php 3 E# P- y2 m; n0 W: g, R' Z0 A+ f
那么我们就修补了这个漏洞。
$ C1 S7 ~ ]8 X7 e* s" ^/ ?8 G9 x3 m- }/ j1 q
2 y7 y$ B1 y# u; T* F2、修改php.ini配置文件 * _: n- Q( H6 E, N$ v
+ A" T9 z1 B6 m" O4 N以php发行版的php.ini-dist为蓝本进行修改。 % o7 n; K, Y1 M5 n% w
% \4 D' @( \5 f8 J% h- J: F/ G1)Error handling and logging
! b! s/ m- H+ F6 @& C在Error handling and logging部分可以做一些设定。先找到: - g; }6 J8 C0 \+ }% |$ f0 l
display_errors = On 1 \; h: b& G1 d5 D" Q
( m$ J+ ^- C$ n' iphp缺省是打开错误信息显示的,我们把它改为:
8 m/ d/ R1 g, i) @! X: q3 Q- P, }/ h, v* H9 p, r
display_errors = Off : O" @' E+ U9 F* C. I- f
' H$ _7 w3 O# K6 b* m" r
关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻
: q8 ~3 G$ V8 u击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造
6 }$ x% O5 D! k# G* c成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以
; S9 y8 J" q( ?0 W$ U9 H* ?% k% r1 n下:
\* t7 F6 O. z
C8 a; E0 h* }" i# i* U& J/ Nlog_errors = Off 2 i) L* f M# p" f
4 g t) R( k! ~; [5 V I8 `0 \
改为:
. y7 M2 W! z5 B0 u1 k4 s {3 Xlog_errors = On ) [0 ^! e% \8 k7 {4 |
6 w' u& g9 K4 ~% @$ o3 j
以及指定文件,找到下面这行: " A* V8 f- x- A
8 L0 a9 C4 ]3 i! Y9 b/ N
;error_log = filename , }; v" r9 [, n
4 R0 q6 @) V) d& I+ o, k
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
1 v# s3 i$ z2 ]2 }: e( c
_' \5 a8 h% Z% ierror_log = /usr/local/apache/logs/php_error.log 0 k" O# w" ~" c0 t1 W9 G7 t
( R) I& _% G2 d这样所有的错误都会写到php_error.log文件里。
' S* a q$ g2 ]: c' s
6 b q" U! i; [' u$ A4 n2)Safe Mode 5 O c4 x5 I* F: u- i7 O! o! D% ^
9 o& j& G; `* W. m
php的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在
/ U* h) y% y" v/ \: oSafe Mode部分找到: ; Q4 V e7 N+ V& l- Z% B3 Q
' ~' D/ j+ @1 nsafe_mode = Off
( t4 u4 U2 G& h' F Q& r: F
/ q* H. H: l( T5 E: a8 x改为: / a( ?1 R I2 Z- I
% k f/ Q) g5 |. _- w$ C ~safe_mode = On % B& R1 U$ _ _6 k5 L* {
- I( S; T% X0 n; t0 m) w3 v
这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它
: x0 l3 ^; W7 m' Z8 y) e& ]8 }+ J的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行
; @' H# \& Y- {! h6 ^. s6 u/ D/ Vsafe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下:
, i: z K; j5 A, y/ J5 L1 r, i% B+ J' m6 `- P3 V
safe_mode_exec_dir = * o6 C* h" Q0 @( ~
* s/ y3 x6 @& u指定要执行的程序的路径,如: 5 z, W9 b1 \+ U9 \& d0 Z6 ~! m
4 a5 o. S, B3 U. p+ R9 I
safe_mode_exec_dir = /usr/local/php/exec
0 `; H) l5 X- r6 [
! `" u/ d/ J- `6 ^然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行
2 I8 _) s2 Y7 t% w% C- ~该目录里的程序。 " r% A4 Z( G7 O. c! y$ Y H
, K" L% @" n& }, u关于安全模式下受限函数的详细信息请查看php主站的说明: " n S( x$ K9 ]& \* q# c- h
http://www.php.net/manual/en/features.safe-mode.php ! ? W, C4 Z$ E
1 x1 J) _* f4 _2 Y
3)disable_functions
4 M6 I0 b$ m; r9 c$ ~7 d$ u$ D+ O6 |2 b% u$ j: h$ y( b
如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这
3 M' \ `, J2 v7 T1 I行: . z, L0 k3 y/ X0 G3 m/ L+ R5 \
( A3 X, v+ }4 k+ }, @7 h. o6 Udisable_functions = ) R. A0 ~2 u0 L$ `2 l4 F; I9 v
: u- k9 Q" d- o- R
在”=“后面加上要禁止的函数,多个函数用”,“隔开。
/ \. @# A; Y; Z* j4 a& s" j3 `
& E! X/ H, I1 ^4 r {" n1 d! }- l! y) ~0 ~
3、修改httpd.conf + W! t$ @+ U" Q* f0 `
% T5 I4 ^& H( i) a$ ^) }如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作2 H% \" T% l9 ^
路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行:
- P' `: l( q, ? @8 k( U4 E: t; }0 L& X" T D' v
<Directory /usr/local/apache/htdocs>
Q3 D: p2 E6 a7 l& O4 Sphp_admin_value open_basedir /usr/local/apache/htdocs ( {' @3 V3 Q l9 V7 ?3 X7 @2 [
</Directory>
$ f5 J6 l5 w7 x
' j1 @$ O. F; J H* t( U0 g1 s这样,如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许,如果错误显示打: Q x# f9 R! H
开的话会提示这样的错误: 5 ?8 h" b" t4 l2 ^' \! U
% M0 S) y; I L/ N
Warning: open_basedir restriction in effect. File is in wrong directory in
7 }- h' O- H4 X/usr/local/apache/htdocs/open.php on line 4
+ Q, `, k. J: F
6 A* k8 {" N& h5 Q2 `等等。 4 N3 \ z7 ~4 r+ N/ w
3 S$ k8 a5 W5 E$ Q
4 x2 t# t+ Z; _% u5 k
4、对php代码进行编译
, R+ z8 f' {, g6 z- C" d: A, r$ ^9 o) F/ w" k0 |
Zend对php的贡献很大,php4的引擎就是用Zend的,而且它还开发了ZendOptimizer和( Q8 \5 |9 e* _+ h
ZendEncode等许多php的加强组件。优化器ZendOptimizer只需在http://www.zend.com注册就
7 V! j) R% \4 M2 y6 K5 Q2 N7 g可以免费得到,下面几个是用于4.0.5和4.0.6的ZendOptimizer,文件名分别对于各自的系统: h( r$ j- G0 X7 \2 P$ v: ?
: ! U+ O( M3 H4 y
6 b% `. F8 a3 u7 B1 a0 E4 c
ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz 0 ]9 v+ `$ y9 U: J0 d
ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz
/ r4 U3 M3 |* S4 u! O PZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz ) F! B' j* P+ n
ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip
) c- ~& j/ ^9 W) n& I3 o1 g7 ~
* E4 B8 o4 O* ]9 h2 [8 G# [优化器的安装非常方便,包里面都有详细的说明。以UNIX版本的为例,看清操作系统,把包里
1 W% n, @7 e4 z( h的ZendOptimizer.so文件解压到一个目录,假设是/usr/local/lib下,在php.ini里加上两句
Y. E( B( z% x8 C: 6 [- N4 G$ _8 s6 M, p, u' r
" j7 h0 P1 U, s8 Mzend_optimizer.optimization_level=15
1 B& [6 `1 L+ }, dzend_extension="/usr/local/lib/ZendOptimizer.so" + c" F& l( o$ l, O+ R, l
# M8 l" o" G. c# Q就可以了。用phpinfo()看到Zend图标左边有下面文字: 9 }; a6 x7 m% O4 q* j2 H/ Y# a
# O' x: k' N" B+ g, e/ q% B# W Pwith Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies 1 `" U' x% ~6 @& e+ c8 g, c
) |% J6 a I# Y5 W$ [
那么,优化器已经挂接成功了。 " G# Z8 q8 Y! Y& A5 X
; ~$ y( I/ d/ y0 x& g' i
但是编译器ZendEncode并不是免费的,这里提供给大家一个http://www.PHPease.com的马勇设
8 p$ |6 z& _ e o" ?计的编译器外壳,如果用于商业目的,请与http://www.zend.com联系取得许可协议。
+ U( Z* l: e! r! C m& Q0 n3 X& g" ?4 | _2 }# D2 f5 n
php脚本编译后,脚本的执行速度增加不少,脚本文件只能看到一堆乱码,这将阻止攻击者进
( M" E4 d" ]5 S$ j/ D' _% t5 i$ {$ W一步分析服务器上的脚本程序,而且原先在php脚本里以明文存储的口令也得到了保密,如
2 C; l/ b: t9 w( O) \$ @mysql的口令。不过在服务器端改脚本就比较麻烦了,还是本地改好再上传吧。
$ e2 ?3 @6 m1 p* w# e
v" A2 [2 t9 \% P- P1 `! U- ?" s7 q
, j, ?: G1 v, o, w: o% Q5、文件及目录的权限设置
2 g8 o2 f- t" j% V3 X# _; P
B& L- d) ~3 Qweb目录里除了上传目录,其它的目录和文件的权限一定不能让nobody用户有写权限。否则,
9 q* z j, ?# M1 n8 _攻击者可以修改主页文件,所以web目录的权限一定要设置好。
; W! i# n4 K: p. `4 ?% T/ P9 E
+ ~& ~. Y) [# l3 D) m. c" L还有,php脚本的属主千万不能是root,因为safe_mode下读文件的函数被限制成被读文件的属, f- H' X. v, x4 T- @0 T" r2 u5 Y
主必须和当前执行脚本的属主是一样才能被读,否则如果错误显示打开的话会显示诸如以下的5 p1 `" U$ F1 `, o$ H' U
错误:
' |: _" E: J4 o( R6 ]. f+ b! q% L3 [# W( s% }
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not
1 I$ f6 E4 k9 ?( Q# a: |- Fallowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php
4 d& j4 \; L) xon line 3 # e2 A9 g3 g0 m, I* m. W
7 G* U" k& V! w/ @( y5 v8 S
这样我们能防止许多系统文件被读,比如:/etc/passwd等。
3 B# ]0 ~' _6 m上传目录和上传脚本的属主也要设成一样,否则会出现错误的,在safe_mode下这些要注意。 7 ^$ V4 n+ x, K7 B) `* b Z
+ a, W& q/ Y/ H" r# k0 G* ~/ R
- _: ~; w: n/ ]9 n/ ^6、mysql的启动权限设置 $ Z2 X7 t# p. p) g0 [
% y, N0 ^& t+ Y3 m0 z1 R
mysql要注意的是不要用root来启动,最好另外建一个mysqladm用户。可以在/etc/rc.local等
}( |/ V( Z2 t- {8 w* n9 ^4 k6 ]系统启动脚本里加上一句: 8 P3 i( T$ _5 V% T1 S6 ^
8 c4 |/ g/ N$ t/ M( s4 csu mysqladm -c "/usr/local/mysql/share/mysql/mysql.server start" ) x$ [9 V' {# N. H# ?; L; c
, ?' e" Q) H9 s( q) D! c% g5 Q J
这样系统重启后,也会自动用mysqladmin用户启动mysql进程。
7 r) c- S! G6 b8 A' h: _, s3 m
* D- J% h8 e+ n. N. o4 }( G
* V6 {' e: u! N7、日志文件及上传目录的审核及
. Y3 ]' _5 {: F& H# i5 E, z3 L" E: }6 R2 Z3 m4 q8 d8 }
查看日志和人的惰性有很大关系,要从那么大的日志文件里查找攻击痕迹有些大海捞针,而且& R8 ^. L1 g' a0 I4 N9 s& v* E0 \
也未必有。web上传的目录里的文件,也应该经常检查,也许程序有问题,用户传上了一些非8 k) {3 V' y( q9 a4 z
法的文件,比如执行脚本等。
8 ~( [* D, F& Z
1 ^# N! J' n9 O. h. G, _; n6 H) b& w) C
0 Q" |8 Z# v0 i. ]8、操作系统自身的补丁 2 }2 e" {2 V% J' `% P4 C
/ B; x/ f, c. P' z
一样,给系统打已知漏洞的补丁是系统管理员最基本的职责,这也是最后一道防线。 - r3 N: f% A2 I" k/ K
& z# D% s' _; s# K. }$ |* A3 b$ F9 K& P
经过以上的配置,虽然说不上固若金汤,但是也在相当程度上给攻击者的测试造成很多麻烦,7 q8 Y: T/ c' _" q
即使php脚本程序出现比较严重的漏洞,攻击者也无法造成实际性的破坏。 . ]6 K0 V+ g% D. C) `/ r
如果您还有更古怪,更变态的配置方法,希望能一起分享分享;) % S: a3 q/ ^2 ]1 A N: ~
, D1 J) S" j9 ]6 y% F6 N1 A, `
8 M' R8 I4 I) n" l( N/ g, A参考资料:
; F- f0 P" t" m* `PHP Manual
/ |, |; ~& t9 I( y$ }9 thttp://www.zend.com |
|