Posted by D Blog on November 9, 2023

参考: The Web Application Hacker’s Handbook Chapter 7

会话管理机制通常容易受到攻击,因为令牌是以不安全的方式生成的,它允许攻击者识别已经发给其他用户的令牌的值。

NOTE
在许多位置,应用程序的安全性取决于它生成的令牌的不可预测性。这里有一些例子:

  • 在许多位置,应用程序的安全性取决于它生成的令牌的不可预测性。这里有一些例子:
  • 在隐藏的表单字段中放置的令牌,以防止跨站点请求伪造攻击(见第13章)
  • 用于一次性访问受保护资源的令牌
  • 在“记住我”函数中使用的持久令牌
  • 让客户购买不使用身份验证以检索现有订单的当前状态的令牌

本章中关于令牌代的弱点的考虑在所有这些情况下都适用。事实上,因为今天的许多应用程序都依赖于成熟的平台机制来生成会话令牌,所以通常是在这些其他功能领域中,在标记生成中发现了可开发的弱点。

1.有意义的令牌(Meaningful Tokens)

一些会话令牌是使用用户的用户名或电子邮件地址或与该人相关的其他信息进行转换创建的。这些信息可以在某种程度上被编码或混淆,并可能与其他数据相结合。例如,以下的标记可能最初似乎是一个长随机字符串:

757365723d6461663b6170703d61646d696e3b646174653d30312f31322f3131

然而,在更仔细的检查中,你可以看到它只包含十六进制字符。猜测字符串可能实际上是一串ASCII字符的十六进制编码,您可以通过解码器运行它,以显示以下内容:

user=daf;app=admin;date=10/09/11

攻击者可以在这个会话标记中利用这个意思来尝试猜测其他应用程序用户的当前会话。使用枚举或常见用户名的列表,它们可以快速生成大量潜在的有效标记,并测试这些是有效的。

包含有意义的数据的令牌通常会显示一个结构。换句话说,它们包含几个组件,通常由一个分隔符分离,可以单独提取和分析,以允许攻击者了解它们的功能和生成方式。以下是一些可能在结构化令牌中遇到的组件:

  • 帐户用户名
  • 应用程序使用的数字标识器来区分帐户
  • 用户的第一个和最后一个名字
  • 用户的电子邮件地址
  • 用户在应用程序中的组或角色
  • 日期/时间戳
  • 递增的或可预测的数字
  • 客户端IP地址

在一个结构化的令牌中,或者实际上是整个令牌,每个不同的组件都可以以不同的方式编码。这可以是一个故意的措施来混淆它们的内容,或者它可以简单地通过HTTP确保二进制数据的安全传输。通常遇到的编码方案包括XOR、Base64和十六进制表示,使用ASCII字符(见第3章),可能需要测试一个结构化令牌的每个组件的各种解码,以将其打开到原来的表单中。

NOTE
当应用程序处理包含一个结构化令牌的请求时,它可能实际上不会用令牌或所有组件中包含的所有数据来处理每个组件。在前面的示例中,应用程序可以base64解码标记,然后只处理“用户”和“date”组件。在一个令牌包含二进制数据团的情况下,大部分数据可能是填充。只有一小部分可能与服务器在令牌上执行的验证相关。将实际需要的标记的子部分缩缩可以大大减少令牌所包含的表观熵和复杂性的数量。

HACK STEPS

  • 1.从应用程序中获取一个标记,并以系统的方式修改它,以确定是否验证了整个令牌,或者它的一些子组件是否被忽略了。尝试将令牌的值一次更改为一个字节(甚至是一个字节),并将修改后的令牌重新提交到应用程序,以确定它是否仍然被接受。如果您发现该令牌的某些部分实际上不需要是正确的,您可以从任何进一步的分析中排除这些,可能会减少您需要执行的工作量。您可以使用Burp入侵者中的“char f抢劫者”有效载荷类型在一个字符位置上修改一个令牌的值,以帮助完成这个任务。
  • 2.在不同的时间登录为几个不同的用户,并记录从服务器接收到的令牌。如果自动注册是可用的,您可以选择您的用户名,用一系列类似的用户名登录,其中包含它们之间的小变化,如a、AA、AAA、AAAA、AAAB、AAAC、AABA等。如果在登录或存储在用户配置文件(如电子邮件地址)中提交其他用户特定的数据,则执行类似的操作,系统地更改数据,并在登录后记录令牌。
  • 3.分析与用户名和其他用户可控数据相关的任何相关性的令牌。
  • 4.分析任何可检测的编码或混淆的令牌。用户名包含相同字符的序列,在令牌中查找相应的字符序列,这可能表明使用XOR混淆。在令牌中查找包含只有十六进制字符的序列,这可能表明ASCII字符串或其他信息的十六进制编码。查找在一个等号中结束的序列,或者只包含另一个有效的Base64字符:a到z,a到z,0到9,+,和/。
  • 5.如果任何含义都可以从会话令牌的示例中进行反向设计,那么考虑一下您是否有足够的信息尝试猜测最近发给其他应用程序用户的令牌。找到一个应用程序的页面,它是一个依赖于session的页面,例如在没有有效会话的情况下返回一个错误消息或一个重定向的返回页。然后使用一个工具,比如Burp入侵者,用猜测标记来对这个页面发出大量的请求。监视该页面正确加载的任何情况的结果,指示一个有效的会话令牌。

2.可预测令牌(Predictable Tokens)

一些会话标记不包含与特定用户关联的任何有意义的数据。然而,它们可以被猜测,因为它们包含了允许攻击者从标记的样本中推断的序列或模式,以实现应用程序最近发布的其他有效令牌。即使外推涉及到一些试验和错误(例如,每1000次尝试一个有效的猜测),这仍然可以使自动攻击在较短的时间内识别大量有效的令牌。

与可预测的令牌生成相关的漏洞可能更容易在会话管理的商业实现中发现,比如web服务器或web应用程序平台,而不是在定制应用程序中。当您远程锁定一个定制的会话管理机制时,您的发布令牌的示例可能会受到服务器容量、其他用户活动、带宽、网络延迟等的限制。然而,在实验室环境中,您可以快速创建数百万样的标记,所有精确的排序和时间戳,您可以消除其他用户造成的干扰。

在最简单、最粗糙的脆弱案例中,应用程序可以使用一个简单的顺序数字作为会话标记。在这种情况下,您只需要获得两个或三个令牌的样本,然后启动一个将迅速捕获100%当前有效会话的攻击。

图7-1显示了Burp Intruder 被用来循环一个顺序会话令牌的最后两个数字的最后两个数字,在这里,会话仍然是活跃的,可以被劫持。在这里,服务器响应的长度是一个可靠的指示器,一个有效的会话已经被发现。提取grep特性也被用来显示每个会话的登录用户的名称。

在其他情况下,应用程序的令牌可能包含更详细的序列,需要一些努力来发现。您可能在这里遇到的潜在差异类型是开放式的,但作者在feld的经验表明,可预测的会话标记通常来自三个不同的来源:

  • 隐藏序列
  • 时间依赖性
  • 弱随机数

我们将依次观察这些地区。

2.1 隐藏序列(Concealed Sequences)

遇到会话令牌是很常见的,因为在他们的原始表单中分析时,不容易预测,但它包含在标记被适当地解码或未包装时显示的序列。

figure7-1

考虑以下一系列值,它形成一个结构化会话令牌的一个组件:

lwjVJA
Ls3Ajg
xpKr+A
XleXYg
9hyCzA
jeFuNg
JaZZoA

没有任何直接的模式可以识别;然而,粗略的检查表明,令牌可能包含base64编码的数据。除了按字母顺序和数字字符之外,还有一个+字符,这在base64编码的字符串中也是有效的。通过Base64解码器运行令牌显示如下:

--Õ$
.ÍÀŽ
Æ’«ø
^W-b
ö‚Ì
?án6
%¦Y

这些字符串似乎是胡言乱语,也包含非打印字符。这通常表明您正在处理二进制数据而不是ASCII文本。将解码的数据呈现为十六进制数字,如下:

9708D524
2ECDC08E
C692ABF8
5E579762
F61C82CC
8DE16E36
25A659A0

仍然没有可见的模式。然而,如果你从前一个数字中减去每个数字,你就会到达以下位置:

FF97C4EB6A
97C4EB6A
FF97C4EB6A
97C4EB6A
FF97C4EB6A
FF97C4EB6A

这立即揭示了隐藏的模式。用于生成标记的算法将0x97C4EB6A添加到前面的值,将结果截断为32位号,并将其编码为二进制数据,以允许使用基于文本的协议HTTP进行传输。使用这些知识,您可以很容易地编写一个脚本来生成服务器将在下一个生成的系列的系列,以及它在捕获的示例之前生成的系列。

2.2 时间依赖性

一些web服务器和应用程序使用算法来生成会话令牌,它使用生成的时间作为令牌值的输入。如果在算法中包含了其他熵,您可以预测其他用户的令牌。虽然任何给定的令牌序列都可能是随机的,但相同的序列加上关于每个令牌生成的时间的信息可能包含一个可识别的模式。在一个繁忙的应用程序中,每秒钟都有大量的会话,脚本的攻击可能会成功地识别大量其他用户的令牌。

在测试在线零售商的web应用时,作者遇到了以下一系列会话令牌:

3124538-1172764258718
3124539-1172764259062
3124540-1172764259281
3124541-1172764259734
3124542-1172764260046
3124543-1172764260156
3124544-1172764260296
3124545-1172764260421
3124546-1172764260812
3124547-1172764260890

每个令牌显然由两个独立的数字组件组成。第一个数字遵循一个简单的递增序列,很容易预测。第二个数字每次都增加一个不同的数量。计算每一个连续标记之间的值之间的差异揭示如下:

344
219
453
312
110
140
125
391
78

这个序列似乎没有一个可靠的可预测的模式。然而,在自动攻击中,在自动攻击中发现有效的值是可能的。然而,在尝试这个攻击之前,我们等了几分钟,并收集了进一步的令牌序列:

3124553-1172764800468
3124554-1172764800609
3124555-1172764801109
3124556-1172764801406
3124557-1172764801703
3124558-1172764802125
3124559-1172764802500
3124560-1172764802656
3124561-1172764803125
3124562-1172764803562

将第二序列令牌与第一顺序进行比较,两个点是显而易见的:

  • 第一个数字序列持续地继续进行,然而,自第一个序列结束以来,已经跳过了5个值。这大概是因为在两个测试之间的窗口中登录到应用程序的其他用户已经发布了丢失的值。
  • 第二个数字序列与以前一样以类似的间隔继续进展;然而,我们获得的第一个值是一个大的539,578,比上一个值要大。

第二个观察立即提醒我们在生成会话令牌时扮演的角色。显然,在这两场比赛中,只有fi的令牌已经发布。然而,大约10分钟的时间已经过去了。最可能的解释是,第二个数字是时间依赖的,可能是简单的毫秒数。

事实上,我们的直觉是正确的。在我们测试的后续阶段,我们执行代码审查,它揭示了以下的tokeno - generation算法:

String sessId = Integer.toString(s_SessionIndex++) +
“-” +
System.currentTimeMillis();

考虑到我们对标记的创建方式的分析,很直接地构建了一个脚本的攻击来获取会话标记,将应用程序问题标记给其他用户:

  • 我们继续向服务器进行投票,以快速继承新的会话令牌。
  • 我们在第一个数字中监视增量。当这个增加超过1时,我们知道一个令牌已经发给了另一个用户。
  • 当一个令牌被发给另一个用户时,我们知道被发给那个人的第二个数字的上和下边界,因为我们拥有在他和之后立即发布的令牌。因为我们经常获得新的会话标记,所以这些边界之间的范围通常只由几百个值组成。
  • 每次向另一个用户发出令牌时,我们就会启动一个暴力破解攻击来遍历范围中的每个数字,并将其附加到我们知道的丢失的增量数中,并向其他用户发布。我们尝试使用我们构建的每个令牌访问受保护的页面,直到尝试成功,并且我们已经破坏了用户的会话。
  • 连续运行此脚本攻击将使我们能够捕获所有其他应用程序用户的会话令牌。当一个管理用户登录时,我们将完全破坏整个应用程序。

2.3 弱随机数(Weak Random Number Generation)

在计算机内部发生的很少是随机的。因此,当随机性被要求时,软件使用各种技术以伪的方式生成数字。一些算法使用的序列似乎是随机的,并显示出一个甚至在可能的值范围内传播的算法。然而,他们可以通过一个小的值样本,以完美的精度推断远期或反向。

当一个可预测的伪随机数生成器用来生成会话标记时,产生的令牌就容易受到攻击者的排序。

Jetty是一个在100% Java中编写的流行web服务器,它提供了一个会话管理机制,用于应用程序运行。2006年,NGSSoftware的Chris Anley发现,该机制很容易受到会话令知预测攻击的影响。服务器使用Java API Java.util.Random 生成会话令牌。这实现了一个“线性一致性生成器”,它生成序列的下一个数字:

synchronized protected int next(int bits) {
	seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
	return (int)(seed >>> (48 - bits));
}

这个算法使用生成的最后一个数字,将它乘以一个常数,并增加另一个常数以获得下一个数字。这个数字被截断到48位,算法将结果转换为返回调用者请求的特定数量。

了解该算法和由它生成的单个数字,我们可以很容易地推导出该算法将会生成的数字序列。有了一个数字理论,我们也可以推导出它之前生成的序列。这意味着从服务器获得一个会话标记的攻击者可以获得所有当前和未来会话的令牌。

NOTE
有时,当以伪整数生成器的输出创建令牌时,开发人员决定通过从生成器连接几个顺序输出来构造每个令牌。这种感知的理由是,它创造了一个更长的时间,因此“更强大”,令牌。然而,这种策略通常是错误的。如果攻击者可以从生成器中获得几个连续的输出,这可能使他能够推断出一些关于其内部状态的信息。事实上,攻击者可以更容易地推断出发电机的输出序列,无论是前进的还是向后的。

其他现成的应用程序框架在会话令牌生成中使用令人惊讶的简单或可预测的熵源,其中大部分是确定性的。例如,在PHP框架5.3.2和更早的时候,会话令牌是基于客户端的IP地址、令牌创建的时代时间、令牌创建的微秒、以及一个线性一致性生成器生成的。虽然这里有一些未知的值,但一些应用程序可能会披露允许它们推断的信息。一个社交网站可以披露网站用户的登录时间和IP地址。此外,在这个生成器中使用的种子是PHP进程开始的时候,如果攻击者在监视服务器,那么它可能会被确定在一个小的值范围内。

NOTE
这是一个不断发展的研究领域。在2001年,PHP会话令牌一代的弱点被指出在完整的信息邮件列表上,但没有被证明是可开发的。2001年的理论最终被Samy Kamkar在2010年与phpwn工具进行了实践。

2.4 测试随机性的质量(Testing the Quality of Randomness)

在某些情况下,您可以在一系列的令牌中识别模式,而不是肉眼检查,或者是少量的手工分析。然而,一般来说,您需要使用更严格的方法来测试应用程序的令牌中的随机性。

这个任务的标准方法适用于统计假设测试的原则,并使用各种有记录的测试,在一个标记的样本中寻找非随机性的证据。这个过程的高级步骤如下:

  • 1.从随机生成的令牌开始的假设开始。
  • 2.应用一系列测试,每个测试都观察样本的专门化属性,如果这些标记是随机生成的,可能会有一定的特性。
  • 3.对于每个测试,计算观察到的特征的概率,研究假设的假设是正确的。
  • 4.如果这个概率低于一定级别(“表示值”),拒绝假设,并得出结论,令牌不是随机生成的。

好消息是,你不必手动做任何事情!目前用于测试web应用程序的随机性的最好工具是Burp测序器。该工具采用各种标准的测试方法,并给出了易于解释的清晰结果。

要使用Burp测序器,您需要从应用程序中得到一个响应,这是您想要测试的令牌,例如对登录请求的响应,它会发布一个包含会话标记的新cookie。从Burp的上下文菜单中选择“发送到测序器”选项,在测序器配置中,在响应中设置令牌的位置,如图7-2所示。您还可以配置影响如何收集令牌的各种选项,然后单击开始捕获按钮开始捕获令牌。如果您已经通过其他方法获得了一个合适的令牌示例(例如,通过保存Burp入侵攻击的结果),您可以使用manual load选项卡来跳过捕获令牌,并直接进行统计分析。

figure7-2

当您获得了一个合适的令牌样本时,您可以对示例进行统计分析。您还可以执行临时分析,而示例仍然被捕获。一般来说,获得一个更大的样本提高了分析的可靠性。Burp需要的最小样本大小是100个令牌,但理想情况下,您应该获得一个比这个更大的样本。如果对几百个令牌的分析最终表明令牌失败了随机性测试,您可能会合理地决定不需要捕获进一步的令牌。否则,您应该继续捕获令牌,并定期重新执行分析。如果你捕获了5000个被显示通过随机性测试的令牌,你可能会认为这是充分的。然而,为了实现对随机性的正式FIPS测试,您需要获得2万个令牌的样本。这是Burp支持的最大样本大小。

Burp测序器执行字符级别和位级的统计测试。所有的测试的结果都是聚合来给出在令牌中有效熵的数量的总体估计;这是考虑的关键结果。然而,您还可以深入研究每个测试的结果,以了解令牌的不同部分通过或失败的原因,如图7-3所示。测试结果下面描述了每种测试类型的方法。

figure7-3

请注意,Burp在令牌中对每个字符和一些数据进行单独的测试。在许多情况下,您将会失去一个结构化令牌的大部分都不是随机的;这本身可能不会存在任何类型的弱点。重要的是,令牌包含了一个足以传递随机性测试的比特数。例如,如果一个大的令牌包含1000位信息,而只有50个这些比特传递了随机性测试,那么作为一个整体的令牌就像一个50位的令牌,完全通过了测试。

NOTE
在对随机性进行统计测试时,要记住两个重要的警告。这些警告影响了对测试结果的正确解释,以及它们对应用程序安全姿态的影响。首先,以完全确定性的方式生成的令牌可能会通过统计测试来进行随机性。例如,一个线性一致的伪随机随机数生成器,或者计算一个顺序数字的哈希的算法,可能会产生通过测试的输出。然而,一个知道算法和发电机内部状态的攻击者可以在向前和反向的方向上输出完整的可靠性。

第二,在任何实际情况下,对随机性的统计测试都失败的令牌可能无法预测。如果一个给定的一个令牌失败了测试,这只意味着在这个位置上观察到的位序列包含不太可能在一个真正的随机令牌中发生的特性。但试图在下一个令牌中预测这一点的价值,基于观察到的特征,可能比盲目的猜测更可靠。在大量需要预测的部分中乘以这个不可靠性可能意味着做出正确预测的概率非常低。

HACK STEPS

  • 1.确定何时以及如何通过从第一个应用程序页面通过任何登录函数在应用程序页面中访问应用程序来发布会话令牌。两种行为很常见:
    • 应用程序在收到请求的时候创建一个新的会话,而不是提交一个令牌。
    • 应用程序在成功登录后创建一个新的会话。 为了自动地获取大量的令牌,最好地确定一个请求(通常是得到/或登录提交),从而发出一个新的令牌。
  • 2.在Burp套件中,发送一个请求,它创建一个新的会话来打嗝排序器,并配置令牌的位置。然后开始一个实时捕获,以收集尽可能多的令牌。如果使用自定义会话管理机制,并且您只访问应用程序, 尽可能快地收集令牌,以尽量减少向其他用户发送的令牌的损失,并减少任何时间依赖的影响。
  • 3.如果一个商业会话管理机制在使用和/或您有本地访问应用程序时,您可以在受控条件下获得无限大的会话令牌。
  • 4.而Burp测序器正在捕获令牌,使“自动分析”设置,使Burp会周期性地自动执行统计分析。在详细检查结果之前,收集至少500个令牌。如果令牌中的足够多的比特已经通过了测试,那么继续收集令牌就可行,回顾分析结果,因为进一步的令牌被捕获。
  • 5.如果令牌失败了随机性测试,似乎包含可以利用的模式来预测未来的令牌,从不同的IP地址和(如果相关的)不同的用户名重新执行练习。这将帮助您确定是否检测到相同的模式,以及第一次练习中接收的令牌是否可以推断来确定在第二个过程中接收的令牌。有时,一个用户捕获的令牌序列显示了一个模式。但这不会允许直接推断给其他用户的令牌,因为诸如源IP这样的信息被用作熵源(比如对随机数生成器的种子)。
  • 6.如果您相信您有足够的深度来了解令牌的生成算法,以对其他用户的会话进行自动攻击,那么最好的实现这一方法的方法很可能是通过定制的脚本。这可以使用您所观察到的特定模式生成令牌 并应用任何必要的编码。请参阅第14章,用于一些通用技术,将自动化应用于这种类型的问题。
  • 7.如果有源代码,请仔细审查负责生成会话令字的代码,以了解使用的机制,并确定它是否容易预测。如果从可以在应用程序内的应用程序中确定的数据来确定熵,那么考虑到使用应用程序令牌需要的实际数量的实际数量。

3.加密令牌(Encrypted Tokens)

一些应用程序使用带有有意义的用户信息的令牌,并寻求避免这种明显的问题,这需要在向用户发布之前对其进行加密。由于这些令牌是使用一个未知的密钥加密的,这似乎是一种鲁棒的方法,因为用户将无法对其内容进行解密和篡改。

然而,在某些情况下,根据使用的加密算法和应用程序处理令牌的方式,用户可能会篡改令牌的有意义的内容,而不需要对它们进行解密。听起来很奇怪,这些实际上是可行的攻击,有时很容易交付,许多现实世界的应用程序已经被证明是很容易受到攻击的。适用的攻击类型取决于正在使用的精确加密算法。

3.1 ECB加密(ECB Ciphers)

使用加密令牌的应用程序使用对称加密算法,以便从用户那里接收到的令牌可以被解密以恢复其有意义的内容。一些对称加密算法使用“电子码本”(ECB)密码。这种类型的密码将明文划分为相等的块(例如8个字节),并使用密钥对每个块进行加密。在解密过程中,每一块密文都使用同样的密钥来恢复原始的明文。这种方法的一个特点是,在明文中,模式可以在密文中产生模式,因为相同的明文块将被加密到相同的密码块中。对于某些类型的数据,如位图图像,这意味着在密文中可以看到来自明文的有意义的信息,如图7-4所示。

figure7-4

尽管与ECB有这种缺点,但这些ciphers通常用于在web应用程序中获取信息。即使在不存在明文的情况下,漏洞的问题仍然存在。这是因为cipher的行为将相同的明文块在相同的密文块中。

考虑一个应用程序,其标记包含几个不同的有意义的组件,包括一个数字用户标识器:

rnd=2458992;app=iTradeEUR_1;uid=218;username=dafydd;time=634430423694715000;

当这个令牌被加密时,它显然是没有意义的,而且很可能会通过所有标准的随机性测试:

68BAC980742B9EF80A27CBBBC0618E3876FF3D6C6E6A7B9CB8FCA486F9E11922776F0307
329140AABD223F003A8309DDB6B970C47BA2E249A0670592D74BCD07D51A3E150EFC2E69
885A5C8131E4210F

被使用的ECB密码在8个字节的数据块上运行,而纯文本地图的块则在相应的密文块上如下:

rnd=2458  68BAC980742B9EF8
992;app=  0A27CBBBC0618E38
iTradeEU  76FF3D6C6E6A7B9C
R_1;uid=  B8FCA486F9E11922
218;user  776F0307329140AA
name=daf  BD223F003A8309DD
ydd;time  B6B970C47BA2E249
=6344304  A0670592D74BCD07
23694715  D51A3E150EFC2E69
000;      885A5C8131E4210F

现在,因为每块密文都将总是对同一块明文进行解密,因此攻击者可以操作密文块的序列,以便以有意义的方式修改相应的明文。根据应用程序如何处理结果解密的令牌,这可能使攻击者切换到不同的用户或升级特权。 例如,如果第二个块在第四块之后被复制,那么块的顺序将如下:

rnd=2458  68BAC980742B9EF8
992;app=  0A27CBBBC0618E38
iTradeEU  76FF3D6C6E6A7B9C
R_1;uid=  B8FCA486F9E11922
992;app=  0A27CBBBC0618E38
218;user  776F0307329140AA
name=daf  BD223F003A8309DD
ydd;time  B6B970C47BA2E249
=6344304  A0670592D74BCD07
23694715  D51A3E150EFC2E69
000;      885A5C8131E4210F

992;app= 0A27CBBBC0618E38

解密令牌现在包含一个修饰uid值,同时也包含一个重复的应用程序值。具体的是,应用程序如何处理解密令牌。通常,使用标记的应用程序只检查解密令牌的某些部分,比如用户标识器。如果应用程序这样运行,那么它将在有992的uid的用户的上下文中处理该请求,而不是原来的218。

刚才描述的攻击将取决于被发送的合适的rnd值,当这些块被操纵时,它对应于一个有效的uid值。另一种更可靠的攻击是注册一个包含数值值的用户名,并复制这个块,以替换现有的uid值。假设您注册了用户名daf1,并以以下标记发出:

9A5A47BF9B3B6603708F9DEAD67C7F4C76FF3D6C6E6A7B9CB8FCA486F9E11922A5BC430A
73B38C14BD223F003A8309DDF29A5A6F0DC06C53905B5366F5F4684C0D2BBBB08BD834BB
ADEBC07FFE87819D

这个令牌的明文和密文的块如下:

rnd=9224  9A5A47BF9B3B6603
856;app=  708F9DEAD67C7F4C
iTradeEU  76FF3D6C6E6A7B9C
R_1;uid=  B8FCA486F9E11922
219;user  A5BC430A73B38C14
name=daf  BD223F003A8309DD
1;time=6  F29A5A6F0DC06C53
34430503  905B5366F5F4684C
61065250  0D2BBBB08BD834BB
0;        ADEBC07FFE87819D

如果您复制第四个块之后的第七块,您的解密令牌将包含一个uid值为1:

rnd=9224  9A5A47BF9B3B6603
856;app=  708F9DEAD67C7F4C
iTradeEU  76FF3D6C6E6A7B9C
R_1;uid=  B8FCA486F9E11922
1;time=6  F29A5A6F0DC06C53
219;user  A5BC430A73B38C14
name=daf  BD223F003A8309DD
1;time=6  F29A5A6F0DC06C53
34430503  905B5366F5F4684C
61065250  0D2BBBB08BD834BB
0;        ADEBC07FFE87819D

1;time=6 F29A5A6F0DC06C53

通过注册合适的用户名和重新执行此攻击,您可以通过整个有效的uid值来进行循环,因此化装程序作为应用程序的每个用户。

3.2 CBC加密(CBC Ciphers)

ECB密码的缺点导致了密码块链接(CBC)密码的开发。用CBC cipher,在每块纯文本被加密之前,它都是与前面的密码文本块相结合的,如图7-5所示。这可以防止相同的明文块被加密到相同的密码文本块中。在解密过程中,XOR操作被应用于反向,每个解密的块都与前面的密码文本相匹配,以恢复原始的明文。

figure7-5

由于CBC 加密避免了ECB 加密的一些问题,在CBC模式中使用了ddes和AES等标准对称加密算法。然而,在web应用程序中经常使用的cbc加密令牌的方式意味着攻击者可以在不知道密钥的情况下操作解密令牌的部分。

考虑在前面的应用程序上的一个变化,它们的标记包含了几个不同的有意义的组件,包括一个数字用户标识器:

rnd=191432758301;app=eBankProdTC;uid=216;time=6343303;

就像以前,当这些信息被加密时,它会导致一个很明显的意义:

0FB1F1AFB4C874E695AAFC9AA4C2269D3E8E66BBA9B2829B173F255D447C51321586257C
6E459A93635636F45D7B1A43163201477

因为这个令牌是使用CBC密码进行加密的,当令牌被解密时,每个密文的每一个块都是x的,在下面的解密文本块中,以获取明文。现在,如果一个攻击者修改了密文(他收到的标记)的部分,这就导致了一个专门的代码块来解密垃圾。然而,它也会导致下面的解密文本块以不同的值被xof,从而导致修改,但仍然是有意义的明文。换句话说,通过操作一个单独的标记块,攻击者可以系统地修改跟踪它的块的解密内容。根据应用程序如何处理结果解密的令牌,这可能使攻击者切换到不同的用户或升级特权。

让我们看看如何。在描述的示例中,攻击者通过加密令牌工作,以任意方式更改一个字符,并向应用程序发送每个修饰标记。这涉及到大量的请求。下面是应用程序解密每个修饰标记的值的选择:

  • ????????32858301;app=eBankProdTC;uid=216;time=6343303;
  • ????????32758321;app=eBankProdTC;uid=216;time=6343303;
  • rnd=1914????????;aqp=eBankProdTC;uid=216;time=6343303;
  • rnd=1914????????;app=eAankProdTC;uid=216;time=6343303;
  • rnd=191432758301????????nkPqodTC;uid=216;time=6343303;
  • rnd=191432758301????????nkProdUC;uid=216;time=6343303;
  • rnd=191432758301;app=eBa????????;uie=216;time=6343303;
  • rnd=191432758301;app=eBa????????;uid=226;time=6343303;
  • rnd=191432758301;app=eBankProdTC????????;timd=6343303;
  • rnd=191432758301;app=eBankProdTC????????;time=6343503;

在每一种情况下,攻击者都像预期的那样对垃圾解密进行了修改(显示???????)然而,下面的块解密了有意义的文本,与原始令牌略有不同。就像已经描述的那样,这种差异发生的原因是,解密的文本是与前面的密码文本块相结合的,攻击者稍微修改过。

虽然攻击者没有看到解密的值,但应用程序试图处理它们,攻击者看到应用程序的结果反应。具体的情况取决于应用程序如何处理已损坏的解密令牌的一部分。如果应用程序拒绝包含任何无效数据的令牌,攻击失败。然而,通常情况下以这种方式使用令牌的操作只检查解密的某些部分令牌,如用户标识器。如果应用程序这样运行,那么前面列出的第8个示例成功了,应用程序也成功了在用户的上下文中处理该请求,其uid226比原来的216

您可以使用“bit flipper”负载类型在Burp Intruder中轻松地测试这个漏洞。首先,您需要使用您自己的帐户登录到应用程序。然后是应用程序的页面依赖于登录会话,并显示登录用户的身份在反应中。一般来说,用户的主页或帐户细节页面服务于此。图7-6显示了Burp的目标用户主页,带有加密的会话令牌,标记为有效负载位置。

figure7-6

图7-7显示了所需的有效载荷。它告诉Burp在标记的原始值上操作,将其处理为一个编码的hex,并在每个字符位置上下移动每一个字符。这种方法是理想的,因为它需要一个相对较少的请求(在令牌中每个字节的8个请求),而且几乎总是识别应用程序是否很脆弱。这允许您使用更集中的攻击来执行实际的开发。

当执行攻击时,初始请求不会导致应用程序响应的任何明显变化,用户的会话仍然完整。这本身很有趣,因为它表明标记的fi rst部分不被用来识别登录的用户。稍后在攻击中请求的许多请求会导致登录页面的重定向,这表明修改性在某种程度上使令牌无效。至关重要的是,还有一个请求的运行响应似乎是有效会话的一部分,但与原始用户身份无关。这与包含uid值的令牌相对应。在某些情况下,应用程序简单地显示“未知用户”,表示修改后的uid与实际用户不对应,因此攻击失败。在其他情况下,它显示了应用程序的不同注册用户的名称,最终证明了攻击已经成功。图7-8显示了攻击的结果。在这里,我们定义了一个提取的grep列,以显示登录用户的身份,并设置了一个过滤器来隐藏对登录页面的解析。

figure7-7

figure7-8

为了识别这个漏洞,你可以通过更集中的攻击来利用它。为了做到这一点,您将从结果确定的结果,在用户上下文更改时,加密令牌的哪个块被篡改了。然后您将提供一个攻击,测试该块内的许多进一步值。您可以在Burp时使用数字有效负载类型来完成此操作。

NOTE
一些应用程序使用在请求参数内的有意义的数据的技术,更普遍地是为了防止数据的篡改,比如购物项目的价格。在任何位置,您可以看到在应用程序功能中起关键作用的加密数据,您应该尝试使用bit-fl启动技术,以查看是否可以以一种有意义的方式操纵加密信息,以干扰应用程序逻辑。

在寻求利用本部分描述的漏洞时,您的目标当然是将化装程序作为不同的应用程序用户——理想的是具有更高特权的管理用户。如果你被限制盲目地操纵一个加密的标记,这可能需要一定的运气。然而,在某些情况下,应用程序可能会给你更多的帮助。当应用程序使用对称加密来保护用户不篡改数据时,同样的加密算法和在整个应用程序中使用的关键都是常见的。在这种情况下,如果任何应用程序都公开了用户对任意加密字符串的解密值,可以利用这一点来完全解密任何受保护信息。

作者观察到的一个应用程序包含一个文件上传/下载功能。上传了一个文件后,用户得到了一个包含文件名参数的下载链接。为了防止操纵文件路径的各种攻击,应用程序在这个参数中加密了文件名。但是,如果用户请求删除一个被删除的文件,应用程序显示一个错误消息,显示所请求文件的解密名称。可以利用这种行为来查找应用程序中使用的任何加密字符串的明文值,包括会话令牌的值。在本节中描述的类型攻击类型中,可以发现会话令牌以结构化格式包含各种有意义的值。因为这些值包括文本用户名和应用程序角色,而不是数字标识符,因此,它将会非常分散,以执行一个成功的开发,只使用盲比特。然而,使用filename解密函数,可以在查看结果时系统地操作标记位。这允许构建一个令牌,当解密时,指定一个有效的用户和行政角色,从而完全控制应用程序。

NOTE
其他技术可能允许您对应用程序使用的加密数据进行解密。“揭示”加密oracle可以被滥用以获得加密令牌的cleartext值。虽然当解密密码时,这可能是一个重要的漏洞,但解密会话标记器并不能提供直接的其他用户会话的手段。然而,解密令牌为cleartext结构提供了有用的洞察,这在执行一个有目标的bitfl ipping攻击方面很有用。参见第11章,了解更多关于“揭示”加密oracle攻击的细节。针对衬垫或指的侧通道攻击可能被用来妥协加密令牌。有关更多细节,请参阅第18章。

HACK STEPS
在许多情况下,在许多情况下使用加密令牌,实际的可利用性可能取决于各种因素,包括与攻击所需要的数据相关联的块边界的偏移量,以及应用程序对周围的纯文本结构的更改的公差。工作完全失明,可能会出现扩散邪教来构建一个有效的攻击,但在许多情况下,这是可能的。

  • 1.除非会话令牌显然是有意义的,或者是连续的,总是考虑可能被加密的可能性。您可以经常识别一个基于块的密码被用于注册几个不同的用户名,并每次都添加一个字符。如果您找到一个点,在您的会话令牌中添加一个字符结果以8或16字节的速度跳跃,那么可能会被使用一个块密码。您可以通过继续为用户名添加字节来确认这一点,并在稍后寻找相同的跳跃发生8到16字节。
  • 2.ECB加密操作漏洞通常很难在纯黑盒上下文中识别和开发。您可以尝试盲目地复制和移动您的令牌中的密码文本块,并审查您是否仍然登录到您自己的用户上下文中的应用程序,或者其他用户的应用程序,或者根本没有登录到应用程序。
  • 3.您可以通过运行一个Burp对整个令牌的攻击来测试CBC密码操作漏洞,使用“比特翻转”有效负载源。如果比特反转攻击标识了令牌中的一个部分,则在一个有效的会话中,它的操作使您保持在一个有效的会话中,但作为一个不同或不存在的用户,在这一节上执行一个更集中的攻击,在每个位置尝试更广泛的值。
  • 4.在两个攻击过程中,监视应用程序的响应,以识别与您的会话相关的用户,遵循每个请求,并尝试开发可能导致的特权升级的任何机会。
  • 5.如果您的攻击不成功,但从第一步开始,您控制的变量长输入将被纳入令牌,您应该尝试通过添加一个字符来生成一系列的令牌,至少在使用的块的大小上。对于每个生成的令牌,您应该重新执行步骤2和3。这将增加你需要修改的数据与你的攻击成功的界限。

Chapter 7 Attacking Session Management(1)-The Need for State
Chapter 7 Attacking Session Management(3)-Weakness in Session Token Handling

: