代码注入漏洞的关键方面是:
该程序将数据视为代码并对其进行编译
在大多数情况下,程序故意像执行代码一样执行数据是不寻常的,但将数据用于构造有意执行的对象却很常见。
1、格式化字符串漏洞
大多数C程序员熟悉printf函数。大体上,这些格式字符串后跟一个其他参数的列表,并且该格式字符串被解释为一组指令,用于将剩余的参数呈现为字符串。
大多数用户知道如何编写最常用的格式说明符:例如字符串,整数和浮点数——%s,%d,%f,但是不知道还有其他格式字符串指令可以被滥用。
以下是printf函数通常被滥用的一种方式。有些程序员习惯编译字符串如下:
printf(str);
虽然这将在大部分时间内都具有所期望的效果,但它是错误的,因为printf的第一个参数将被编译为格式字符串。所以,如果str包含任何格式说明符,它们就将被这样编译。
例如,如果str包含'%d',它会将printf参数列表中的下一个值解释为整数,并将其转换为字符串。在这种情况下,没有更多的参数,但机器在执行的时候并不了解这一点; 它所知道的全部是,函数的一些参数已经被推送到堆栈。
因为在C运行时没有机制可以告诉机器已经没有更多的参数了,所以printf将简单地选择恰好在堆栈中的下一个项目,将其编译为一个整数并打印出来。
很容易看出,这可以用来从栈中打印任意数量的信息。例如,如果str包含'%d%d%d%d',则将会打印堆栈上接下来四个字的值。
虽然这是一个代码注入安全漏洞,但由于它唯一可能造成的伤害就是可以被用来获取栈中的数据,所以它还是可以被原谅的。
可如果位于那里的是敏感数据(如密码或证书密钥),情况就会变得很糟;而且由于攻击者还可以在那里写入任意内存地址,因此情况还可能会变得更糟。
使这种糟糕情况的发生成为可能的是格式说明符'%n'。通常,相应的参数是指向整数的指针。当格式字符串为了建立结果字符串而被编译时,一遇到'%n',到目前为止写入的字节数就被放置到由该指针所指示的存储单元中了。
例如,在下面的printf完成之后,i中的值将为4:
应该遵循的两个黄金规则以防止代码注入漏洞:
1.如果你可以避免的话,尽量不要将数据像代码一样编译;
2.如果你无法避免的话,请确保在使用数据之前验证数据是否良好。
为避免格式字符串的漏洞,这些规则中的第一个是最合适的; 你可以编写代码如下:
测试这些类型的漏洞可能很困难; 即使能实现非常高的代码覆盖率的测试也不能触发这些问题。
测试安全漏洞时,测试人员必须采取一个攻击者的心态。
诸如模糊测试的技术可能是有用的,但是该技术通常太随机,无法高度可靠。
来源:电子伊甸园
文章来源于网络,版权归原作者所有,如有侵权,请联系删除。
觉得文章不错,点击“分享”、“赞”、“在看” 呗!