即使有时将软件错误和漏洞视为同一个概念,但它们之间至少必须有一个不同的方面,我认为最突出的一个方面是可利用性(后者具有属性)。 >我很好奇的是,即使看到许多案例都将零除错误报告为软件问题,我几乎也无法提出使用零除错误的攻击(DoS除外)。我知道并不是所有类型的Bug都会在安全性方面对系统产生相同的影响,但是是否有任何攻击方法使用除以零的Bug来实现不同于DoS的功能,例如特权升级?

评论

我对多年前的CVE记忆犹新,它的核心是除以零,但它是一个远程根任意代码错误。这可能类似于约翰·德特斯(John Deters)所描述的,但我记得不够多,不能冒险给出答案。

我假设您是在谈论整数除以零?因为IEEE 754浮点除以零是明确定义的,因此应该没有问题(但是在John Deters的回答方案中适用的部分内容也将在此处适用)。

从这个问题中我得到的另一个结论是,代码审查应确保在每次除法运算之前都要对分母进行审查。分母为零表示需要研究某种错误。

我在一个项目中,我们不得不向美国政府报告用户可控制的零除,这是一个重大的安全漏洞。用户可以制作会导致mod 0操作(导致被0除)的数据包。被杀死的是一个入侵防御系统。因此,您可以在开始攻击之前用狡猾的包装将其关闭。当然,这是一个非常奇怪且具体的示例。

发生过几次这样的情况导致屏幕保护程序崩溃的情况,从而使系统处于解锁状态且不受保护

#1 楼

问题在于异常处理程序将被调用以处理被零除。通常,攻击者知道异常处理程序没有常规代码流那样经过充分的测试。您的主要逻辑流程可能很健全且经过了全面测试,但是异常处理程序可以由其范围内代码中任何地方发生的中断触发。

int myFunction(int a, int b, SomeState state) {

    state(UNINITIALIZED);
    try {
        state.something(a/b);
        state(NORMAL);
    }
    catch () {
        state.something(b/a);
        state(INVERTED);
    }
    return retval;
}


这种可怕的伪代码说明了一种可以利用该缺陷的方式。假设未初始化的状态易受攻击。如果调用此例程,则状态将首先未初始化。如果b为零,它将捕获异常并尝试执行其他逻辑。但是,如果a和b都为零,则会再次抛出该状态,而未初始化状态。

除以零本身并不是漏洞,可以利用它周围的不良代码。 >

评论


评论不作进一步讨论;此对话已移至聊天。

–Rory Alsop♦
19 Mar 8 '19在9:36

#2 楼

要添加另一个人为的但基于真实示例的例子:

许多月前,我的高中正在运行Novell Netware并对其进行了配置,以使学生无法直接运行dos提示(这是烦人,例如您是否需要格式化软盘)。但是,发现如果您输入的密码超过X个字符(即仅按住一个键一段时间),这将使Netware崩溃并使系统退回到... dos提示符。这很可能是缓冲区溢出,但是原理是一样的:如果您要处理的系统(尤其是嵌入式系统)通过将您置于维护模式来处理至少一些意外崩溃,则存在安全问题。

评论


带回美好的回忆...

–种未知
19 Mar 6 '19 at 10:11

有一天,我将要讲述有关利用某些Apple []公告板软件中类似漏洞的完整故事。该软件最初是为整数BASIC编写的,但无需过多考虑即可移植到浮点BASIC。您只要在任何整数输入提示下输入“ 99e999”,就可能导致浮点BASIC崩溃并发生溢出。这将使您进入命令提示符,例如,您可以阅读您无权访问的私人电子邮件或论坛。

– David Schwartz
19年3月7日在18:08

#3 楼

正如其他答案所暗示的那样,它完全取决于整个系统。这不仅是代码,还包括平台,语言和编译器。

例如,在c ++中,整数除以零是未定义的行为。关于该特定语言的规则之一是编译器可能会假设未定义的行为将永远不会发生,并且允许这样做。

任何事情都包括崩溃并显示错误消息并进行清理,崩溃而不显示错误消息并使所有内容保持怪异状态,或者是最可怕的尝试,使一切似乎都没有发生。

现在,实际上,大多数优秀的现代编译器在遇到类似问题时都会尝试使它们崩溃,但是这应该清楚地说明了为什么假定它是漏洞。如果仅使用不同的编译器或不同的设置来构建代码,甚至不更改代码,则该程序的工作可能会从崩溃到清除数据库。

评论


最后一段取决于一个人对“好”的定义。有人会认为编译器可以优化(x!= 0)launch_nuclear_missiles();返回1 / x;通过使函数调用无条件优于无条件调用。我要说的是,适合于涉及不可信输入的任务的高质量编译器应该崩溃或不做任何响应以除以零(如果代码计算z = y / x;但是从不使用z,则编译器会忽略x通常,不应将其完全视为不如陷阱(如果为零的话)的陷阱),但是...

–超级猫
19 Mar 4 '19 at 17:01

@supercat我认为这需要保证launch_nuclear_missles总是返回。

–所罗门·乌科(Solomon Ucko)
19 Mar 5 '19 at 0:01

@SolomonUcko:为什么?如果x为零,则无论该函数是否被调用返回,都将被除以零。如果x不为零,则该函数可以在不调用UB的情况下返回。

–超级猫
19 Mar 5 '19在5:03



@supercat糟糕,没关系。缺少花括号和所有内容都在同一行的事实一直让我感到震惊。

–所罗门·乌科(Solomon Ucko)
19 Mar 5 '19 at 11:43

@MSalters:在大多数平台上,除非实现无法引起其他行为,否则尝试加载类型为double的不确定值将尝试加载任意值或触发陷阱,该陷阱的默认行为将导致程序异常终止。同样,对于大多数形式的UB,除了(IIRC)附件L中被描述为“严重的未定义行为”的UB外。尽管附件L的编写过于精确,以至于没有真正的含义(要有意义,它应该定义一个行为模型,然后指定-关键UB可能以以下任何方式表现...

–超级猫
19 Mar 5 '19 at 14:32

#4 楼

加上配置错误的Web服务器,当导致零除(内部路径泄漏)时,PHP环境可能会显示脚本的物理路径:

php?number = 0,我们可以看到:

警告:在第3行的/var/www/html/script.php中被零除。

评论


可能值得添加的是,您有时会使用它来获取更多详细错误:(“错误,Select登录名= 1/0时,来自Select *的错误”)“详细错误”是一种错误的配置,但这是一种廉价的方法利用它。

– JeffUK
19 Mar 5 '19在11:20



那将是配置非常差的PHP安装。并不是说这样的安装不存在。缺省情况下,display_errors长时间未开启。

– Kevin_Kinsey
19 Mar 5 '19 at 17:34

#5 楼

虽然有时我在研讨会和讲座中说软件中的所有安全问题本质上都是bug,但反之并不能自动成立。仅仅因为您和我无法找出一种利用方法,并不意味着一个更狡猾的人就不会有一天。我们将必须提供正式证明,证明它不可利用。祝您好运,并拥有当前编程语言中的形式化证明。通常,它将导致异常并因此终止软件。对于攻击者而言,这本身可能就是重要的信息(他现在知道某个变量为零)。是问题的一部分。

因此,要结束循环,您应该始终认真对待所有错误。如果您不确定(例如您的部门使用了您无法控制的变量),则需要捕获并处理它,无论是否安全。 “是的,这是一个错误,但我不知道如何利用它”不是一种注重安全性的心态。

评论


“软件中的所有安全问题本质上都是错误”,其中一些是PEBCAK = P

–alo Malbarez
19年3月8日,1:12

@aloMalbarez我经常以此假设挑战人们。哎呀,我已就此发表主旨演讲。 “用户==失败者”是懒惰的人用来不讨论其用户界面设计的缺点,后果的可见性或普通的过错责任的借口。

–汤姆
19年8月8日在8:59

#6 楼

零除并不是天生的安全漏洞。

但是,如果您可以使应用程序服务器崩溃并使其除以零而保持脱机状态,则可能构成拒绝服务漏洞。 >

评论


问题中已经提到了这一点。

– JAD
19 Mar 4 '19 at 8:45

@JAD:似乎有两个相关的类pf拒绝攻击。一种是提供单个输入,以使服务器状态持续受到破坏。二,提供重复输入,使服务器反复崩溃。该答案似乎涵盖了第一种情况(保持离线状态),而问题似乎涵盖了第二种情况。但是它们绝对是相关的。

– MSalters
19 Mar 4 '19 at 12:03

@jad,在这方面标题和问题不一致。应该可能会更改标题。

– JeffUK
19 Mar 5 '19 at 11:19

基本上,程序中任何可能导致崩溃的错误都可能是安全漏洞,而无法防止被零除是常见的此类错误,但是崩溃和其他原因之间并没有内在的区别。例如,数组越界错误同样危险。

–麦凯(Michael Kay)
19年3月7日,11:30



#7 楼

我认为最终您的答案将归结为各个系统。系统如何处理除以0的尝试?如果情况优美,那么您的攻击选择就有限或不存在。如果它做得很时髦,您可能可以带上一些东西。错误的错误处理是许多漏洞的根源。

评论


我对Intel Pentium II CPU的处理方式绝对不满意。

–注意
19 Mar 4 '19 at 14:01

除零错误将出现在应用程序中。如果它降低到CPU级别,则说明您已经遇到问题了。

–securityOrange
19 Mar 4 '19 at 14:14

我知道。当他们从P1 CPU切换到P2 CPU时,英特尔遇到了这个问题。

–注意
19 Mar 5 '19在7:12

#8 楼

如果程序仅接收可信赖的数据,并且如果在收到恶意制作的数据时它不必满足任何行为要求,则可能会产生比某些行为要求时更有效的代码。必须满足所有数据。

由于某些任务仅涉及处理可信赖的数据,而另一些任务涉及处理来自不可信赖的来源的数据,因此C标准允许仅针对前一个任务的实现进行优化,在适用于后者的应用程序中是不合适的,对于打算适合后者的应用程序提供适当的保证,这些保证会不必要地阻碍优化,这些优化可能在处理前者时有用。没有提供任何方法可以使实施方案表明它们将提供超出标准要求的行为保证的种类。在编写C89时,作者希望“市场”比标准的作者能做得更好,因为在标准不加任何规定的情况下,至少通过某种方式可以预测地确定哪种实现应支持哪些“流行扩展”要求,并且即使不再适合当今的编译器市场,这种态度也没有改变。

给出类似这样的信息:查看一个编译器,该编译器用对launch_nuclear_missiles()的无条件调用替换“ if”,优于仅在launch_nuclear_missiles为非零时仅调用x的编译器,但是这种行为仅在处理永远不涉及不可靠输入的任务时才适用。 >
如果人们知道一个编译器正在使用的软件将秉承通用编译器过去提供的弱行为保证的原则,并且即使编写了恶意设计的输入,也有助于编写满足弱行为约束的程序,那么被零除可能不会带来安全漏洞。但是,对于不适合于涉及不可靠输入的任务的激进优化编译器,有必要添加足够的安全检查逻辑,以抵消诸如“优化”可能提供的任何优势。

评论


@PeterCordes:如果x不为零,则该函数可以返回而不会导致UB。如果x为零,则UB将发生,无论调用该函数将执行什么操作。

–超级猫
19年3月5日下午5:00

哦,是的,你是对的。 @SolomonUcko的参数不成立,因为x = 0会导致y / x在不调用可能不返回的函数的情况下运行,因此可以假定未发生。显然,这段代码有一个错误,但是是的,某些故障模式比其他故障模式更糟糕。 C不是安全的语言。

– Peter Cordes
19 Mar 5 '19在5:19



@PeterCordes:令人遗憾的是,对于编译器来说,将Rationale中提到的“流行扩展”视为“错过的优化机会”是一种时尚,而不是意识到他们允许许多程序以比其他方式更便宜的方式满足需求。

–超级猫
19 Mar 5 '19在5:29

#9 楼


,但是有没有一种攻击方法使用除零错误来实现不同于DoS的功能,例如特权升级?揭示大部分被零除会导致拒绝服务,但是CVE-2005-0998的一种特殊情况还允许其他情况:允许远程攻击者通过无效的show参数获取敏感信息,这将触发除以零的PHP错误,从而泄漏服务器的完整路径名。升级或特定攻击,但通常来讲,敏感信息在设计其他攻击时可能很有用。换句话说,被零除本身可能只是一个垫脚石。

#10 楼

我知道您来自哪里。就其本身而言,很难看到仅可以使用算术错误来导致需要输入数据的任何事情(例如代码执行)。有选择地使线程崩溃等。这是使您感到更复杂的事情,或者如果您真的(不幸)不幸,直接导致触发一条导致双重利用的途径。请记住,数据输入和错误不一定必须相同。
如果这样做是在线程中并且由于某种原因(例如有人将stats打印语句放入错误的迭代循环中),则有可能这将使列表处于同一状态,并带有2个相同元素的副本。 ,并且可以使stat结果除以零并仍然控制足够的内容,这很有可能会被利用。

#11 楼

最好将问题表述为“为什么拒绝服务被视为安全漏洞?”。在x86处理器上运行Linux时,如果处理器将整数除以0(或最小带符号整数值除以-1,感谢超级猫),则程序将收到SIGFPE信号。在Windows中,这是非法操作。 C / C ++标准将其视为未定义的行为,这意味着您仅通过查看代码就无法可靠地知道会发生什么。

通常,与许多但不是全部的拒绝服务漏洞一样,导致“崩溃”。这是程序异常终止时可以利用的一些可能性:


它可以允许另一个程序使用与第一个程序相同的资源(例如端口),并假装为相同的程序。
崩溃可能会规避该程序使用的任何可能被利用的清除操作。
如果该程序的退出代码正在另一个不检查子信号状态的程序中使用进程的PID,可能会认为程序返回了错误代码。例如,在我的Linux计算机上,以下2个程序都将$?(shell脚本中用于表示前一命令的返回代码的变量)设置为136:会导致诸如核心转储之类的事情,其中​​可能包含受保护的内存,例如安全密钥,密码和可口可乐的配方。 0并可能优化您可能没有考虑的代码。这仅适用于C和C ++之类的编译语言,它们具有未定义的行为(或等效行为),可以被零除。我无法生成使用clang或gcc的其他答案中的示例来执行此操作的优化代码,但是并没有阻止它们或其他编译器在过去或将来执行此操作的功能。

评论


“崩溃”是否表示安全漏洞取决于执行环境。但是,如果使用疯狂进取的C实现,则即使行为在C不会崩溃的情况下,其行为不受C Standard强制执行的任何操作也可能导致安全漏洞。

–超级猫
19 Mar 6 '19 at 21:33

@supercat我试图根据您的评论改善答案

–错误
19 Mar 7 '19 at 14:04

您应该说,如果在Linux上运行的机器代码尝试将整数除以零(或将-2147483648的32位整数除以-1),则会引发SIGFPE。尝试执行这种除法的AC程序可能会在SIGFPE可能会造成安全漏洞的情况下,而且在C优化器认为程序的输入将永远不会除以零的情况下可能会导致编译器优化安全性仅在发生此类输入时才有意义的代码。

–超级猫
19年3月7日在15:22

#12 楼

这是一个可能有所作为的示例。

它是100%人为设计的-但通过理论上的“人为”示例可以识别许多类别的漏洞利用,直到找到具体示例为止。

它是伪代码。

try:
   get the average cpu usage per logged in user
   if this average is too high, tell the person logging on that we're busy.
   get login credentials
   verify login credentials
   if credentials are invalid, tell them to go away
   restrict access for this session to the correct access for this user
if there is an exception:
   do nothing

let the user in


在这种情况下,每个登录用户的平均cpu可以计算为“总cpu /登录数”用户”-如果没有登录的用户,则得到“除以0”,并且直接跳到“如果有例外”子句。这包括限制访问-新会话可能具有与最后一个用户匹配的访问权限,或者无限制访问。

虽然本示例将所有代码放在一起,但通常您的主代码会调用某些东西,而该调用其他方面,以及相互作用的两个方面(在这种情况下,是被0除,并且忽略了异常的事实)可能在代码中相距很远的部分中运行。

正如许多人所提到的那样,零除(本身)不是安全漏洞,或者根本不是漏洞。据我所知,大多数(也许是所有!)编程语言都清楚地记录了有关零除的情况。我认为几乎所有有例外的语言都存在被零除的例外情况(我见过机械式计算器陷入无限循环)。

#13 楼

这里有一些非常具体的答案。我同意,(未处理的)除以零的问题主要是功能性问题-但这并不意味着它不能被用作安全性问题。确实,将如此多的错误应用于错误时,可以将“功能性”与“安全性”的分类视为毫无意义。

您无需进行任何讨论就可以忽略一类安全性问题(DOS)。您认为超出范围的内容。最明显的情况是,触发错误将导致程序实例停止。但是还有更细微的影响-如果它导致将大量数据写入文件系统(例如核心转储),则会通过填充文件系统为第二种类型的DOS提供一条途径。 />杰弗里(Jefrey)提到了一个PHP应用程序的公开信息-但是错误消息,日志和核心转储为试图从不应以任何语言编写的程序访问的信息中提取信息的人们提供了丰富的选择依据。程序的过早终止会导致某种响应,然后攻击者可以选择自己的方式来触发特定程序-他们可以控制系统的运行,从而促进攻击/特权升级。 br />
即使控制系统是手动的,该系统仍然存在过渡状态,在该状态中,安全行为的定义不太明确,并且密码短语,密码和私钥等资产正在使用中。 />