第16章
1. 如果不采用特殊的防御措施,为什么栈缓冲区溢出比堆溢出更容易被攻击者利用?
利用基于栈的溢出,通常可以立即控制栈上的已保存返回地址,并因此控制当前功能返回的指令指针。可以将指令指针指向包含shellcode的任意地址(通常位于触发溢出的同一缓冲区内)。
利用基于堆的溢出,通常可以将内存中的任意指针设置为任意值。正常情况下,利用这种修改来控制执行流还需要采取其他步骤。此外,使堆缓冲区溢出后,渗透测试员可能无法立即实施攻击,而要依赖于影响堆内存分配的意外事件。
2. 在C与C++语言中,字符串的长度如何决定?
标准C/C++字符串的长度并没有具体的限制。这类字符串在遇到第一个空字节时结束。
3. 与在因特网上运行的所有权Web应用程序中存在的溢出漏洞相比,非定制网络设备中存在的缓冲区溢出漏洞为什么更可能被攻击者所利用?
虽然探查和检测远程Web应用程序中存在的缓冲区溢出漏洞相对较为容易,但要设计出针对这类漏洞的有效攻击往往极为困难(尽管并非完全不可能)。
另一方面,通过在本地访问易受攻击的网络设备,就可以附加调试设备并全面调查漏洞的本质,从而设计出经过优化的攻击,对漏洞加以有效利用。
4. 下面的模糊漏洞字符串为什么无法确定许多格式化字符串漏洞?
%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n...
默认情况下,最新的printf系列函数禁用了格式说明符%n。因此,应始终提交大量%n说明符,如果应用程序以危险的方式处理输入,这些说明符将受到支持,并很可能会触发异常。
此外,仅仅使用printf系列说明符无法检测对其他格式化函数(如FormatMessage)的危险调用。
5. 假设在一个大量使用本地代码组件的Web应用程序中探查缓冲区溢出漏洞,发现了某个请求的一个参数可能存在漏洞,然而无法让监控到的反常行为再次发生。有时,提交一个长度较长的值会立即造成系统崩溃,有时则需要重复提交几次才能导致崩溃。另外,如果提交大量“良性”请求也会引起系统崩溃。
什么原因最有可能导致应用程序出现这种行为?
这可能说明应用程序中存在堆溢出漏洞。提交的每一个超长请求都可能破坏堆控制结构。但是,通常情况下,只有在执行相关堆操作时,堆受到的破坏才会引发异常,而堆操作的时间可能取决于与所提交的请求无关的其他事件。
请注意,在极少数情况下,其他操作也会导致上述行为——例如,由于负载平衡或对输入的延期处理。
第17章
1. 假设受攻击的应用程序使用两台不同的服务器:一台应用程序服务器和一台数据库服务器。已经发现一个漏洞,可以在应用程序服务器上执行任意操作系统命令。是否可以利用这个漏洞获取保存在数据库中的敏感应用程序数据?
几乎可以肯定能够利用该漏洞获取保存在数据库中的应用程序数据。应用程序本身必须拥有访问自己的数据所需的证书和权限。可以检查服务器端应用程序的脚本和配置文件,以了解它如何访问应用程序。要对所发现的漏洞加以利用,一个明显的方法是在Web根目录中创建一些新脚本,以执行任意查询并使用浏览器检索查询结果。
2. 在另外一种情形中发现了一个SQL注入漏洞,可以利用它在数据库服务器上执行任意操作系统命令。是否可以利用这个漏洞攻破应用程序服务器?例如,是否可以修改保存在应用程序服务器中的应用程序脚本以及向用户返回的内容?
即使完全攻破了整个数据库服务器,也不一定有办法攻破应用程序服务器。通常,应用程序服务器将数据库服务器作为数据库客户端访问,应用程序服务器并不以任何其他方式信任数据库服务器。
但是,渗透测试员或许可以修改向用户返回的内容,因为其中一些内容将使用数据库中包含的数据生成。例如,即使应用程序中不包含可以在它自身中触发的保存型XSS漏洞,仍然可以通过直接修改数据库中的数据,将任意脚本注入应用程序的响应中。如果可以通过这种方法攻击管理用户,就可以迅速攻破整个应用程序。
3. 在攻击共享环境中的一个Web应用程序时,与ISP签订合约后,在所针对的同一台服务器上获得了一些Web空间,允许向其中上传PHP脚本。
是否可以利用这种情况攻破目标应用程序?
PHP语言包含许多强大的函数,可用于执行操作系统命令和访问文件系统。如果能够修改由其他应用程序使用的文件,就可能攻破该应用程序。但是,攻击成功的几率在很大程度上取决于PHP环境的配置,以及应用程序是否对在技术堆栈以下执行的操作实施了任何控制。
4. Linux、Apache、MySQL与PHP等架构组件常安装在同一台物理服务器上。为何这样做会削弱应用程序架构的安全状况?
通常,如果将所有应用程序组件安装在同一台服务器上,将无法对这些组件进行有效隔离。也就是说,如果攻击者攻破应用程序架构的其中一个组件,就能够迅速攻破其他组件。例如,可以利用Web应用程序中的文件泄露漏洞从数据库中检索包含敏感数据的文件。同样,可以利用SQL注入漏洞、使用数据库函数在服务器文件系统上写入任意文件,在Web根目录中创建可以从浏览器访问的脚本,并因此直接攻破应用程序层。
5. 如何找到证据来证明所攻击的应用程序由某个应用程序服务提供商托管?
第18章
1. 在什么情况下Web服务器会显示目录列表?
(a) Web服务器找不到默认文档(如index.html);
(b) 目录列表已启用;
(c) 具有访问目录所需的权限。
2. WebDAV方法有什么作用?为什么说它们会造成危险?
使用WebDAV方法可以基于Web创作Web内容。
如果未对这些方法实施严格的访问控制,则这些方法可能会造成危险。此外,由于涉及复杂的功能,以前它们一直是Web服务器中漏洞的源头——例如,是通过IIS服务器利用操作系统漏洞的攻击向量。
3. 如何利用一个配置成Web代理服务器的Web服务器?
如果可以通过代理服务器反向连接到因特网,就可以利用它攻击因特网上的第三方Web应用程序,这时提出的请求似乎是来自配置不当的Web服务器。
即使向因特网提出的请求被阻止,仍然可以利用代理服务器访问组织内部无法直接访问的Web服务器,或访问服务器本身上的其他基于Web的服务。
4. 何为Oracle PL/SQL排除列表?如何避开这个列表?
PL/SQL排除列表是一个模式匹配黑名单,旨在防止将PL/SQL网关用于访问某些强大的数据库包。
有各种方法可以避开PL/SQL排除列表过滤器。这主要是因为该过滤器采用非常简单的表达式,而后端数据库却遵循更加复杂的规则来说明输入的重要性。人们已经找到大量方法,可用于设计与黑名单模式不匹配、但能够成功执行数据库中的强大包的输入。
5. 如果一个Web服务器允许通过HTTP与HTTPS访问它的功能,当查询漏洞时,使用其中一个协议与使用另一个协议相比有哪些优点?
使用HTTPS进行通信也许能够避开某些网络层入侵检测系统。但是,通常情况下,如果使用HTTP,自动化攻击的执行速度会更快。应用程序可能包含不同的功能,或者在通过不同协议访问时会表现出不同的行为,因此,一般来说,应准备使用这两种协议进行测试。
第19章
1. 列出3种可在源代码中找到明确签名的常见漏洞。
(a) 跨站点脚本
(b) SQL注入
(c) 路径遍历
(d) 任意重定向
(e) 操作系统命令注入
(f) 后门密码
(g) 某些本地代码漏洞
2. 当审查PHP应用程序时,为什么有时很难确定用户输入的所有来源?
PHP使用一系列内置数组来存在用户提交的数据。如果启用了register_globals,则PHP会为每个请求参数创建一个全局变量,并且应用程序会通过引用一个同名变量来访问参数——没有任何语法现象表明此变量表示用户输入,而不是在其他位置定义的任何其他变量。
3. 以下两个执行SQL查询的方法都使用了用户提交的输入:
// method 1
String artist = request.getParameter(“artist”).replaceAll(“’”, “’’”);
String genre = request.getParameter(“genre”).replaceAll(“’”, “’’”);
String album = request.getParameter(“album”).replaceAll(“’”, “’’”);
Statement s = connection.createStatement();
s.executeQuery(“SELECT * FROM music WHERE artist = ‘” + artist +
‘” AND genre = ‘” + genre + ‘” AND album = ‘” + album + “’”);
// method 2
String artist = request.getParameter(“artist”);
String genre = request.getParameter(“genre”);
String album = request.getParameter(“album”);
Statement s = connection.prepareStatement(
“SELECT * FROM music WHERE artist = ‘” + artist +
“’ AND genre = ? AND album = ?”);
s.setString(1, genre);
s.setString(2, album);
s.executeQuery();
哪一个方法更加安全,为什么?
方法1更加安全。
虽然方法1从用户输入动态构建SQL查询,但它将输入中出现的所有单引号全部配对,并将所有用户提交的参数视为字符串数据。虽然这并非安全处理SQL查询的最佳方法,但目前似乎并没有任何SQL注入风险。
方法2使用一个参数化查询,这是在SQL语句中安全合并用户提交的输入的首选方法。但是,在三个用户输入中,只有两个输入被正确参数化。其中一个输入被错误地直接放置到指定查询结构的字符串中,因此应用程序肯定易于受到SQL注入攻击。
4. 在审查一个Java应用程序代码时,首先要检查HttpServletRequest.getParameter API的所有用法。下列代码引起了你的注意:
private void setWelcomeMessage(HttpServletRequest request) throws
ServletException
{
String name = request.getParameter(“name”);
if (name == null)
name = “”;
m_welcomeMessage = “Welcome “ + name +”!”;
}
这段代码表示应用程序中可能存在什么漏洞?还需要进行哪些代码分析才能确定应用程序是否确实易于受到攻击?
该应用程序可能易于受到反射型XSS攻击,因为它似乎正从请求参数直接构建在屏幕上显示的欢迎消息。
仅仅从这个代码片段无法最终确认应用程序是否易于受到攻击。为此,还需要进行以下调查:
(a) 是否对其他位置的name参数执行了任何输入确认;以及
(b) 在将m_welcomeMessage复制到应用程序的响应中之前,是否对它执行了任何输出确认。
5. 假设渗透测试员正在审查一个应用程序用于生成会话令牌的机制。相关代码如下:
public class TokenGenerator
{
private java.util.Random r = new java.util.Random();
public synchronized long nextToken()
{
long l = r.nextInt();
long m = r.nextInt();
return l + (m << 32);
}
}
应用程序生成的会话令牌是否可以预测?请解释理由。
是。了解所使用的令牌创建算法后,就可以基于一个令牌示例进行前后推断,从而确定应用程序创建的所有令牌。