点击上方蓝字 江湖评谈设为关注/星标
前言
C/C++因为其难以察觉的BUG,一直被欧美嫌弃。最近美国NSA提议开发者使用安全的编程语言,大多数现有的各种漏洞都是不安全代码引起的。对于以非内存安全语言编写的现有产品, 到 2026 年 1 月 1 日前仍缺少明确内存安全迁移路线图的情况, 将被视为存在风险,而进行限制。
漏洞示例
C/C++的漏洞有多难发现,本篇以CVE-2021-22555这个存在字节对齐泄露的漏洞为例,以下代码你能看出它的漏洞点在哪儿吗?
void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
unsigned int *size)
{
const struct xt_target *target = t->u.kernel.target;
struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
int pad, off = xt_compat_target_offset(target);
u_int16_t tsize = ct->u.user.target_size;
char name[sizeof(t->u.user.name)];
t = *dstptr;
memcpy(t, ct, sizeof(*ct));
target->compat_from_user(t->data, ct->data);
else
memcpy(t->data, ct->data, tsize - sizeof(*ct));
pad = XT_ALIGN(target->targetsize) - target->targetsize;
if (pad > 0)
memset(t->data + target->targetsize, 0, pad); //漏洞代码
tsize += off;
t->u.user.target_size = tsize;
strlcpy(name, target->name, sizeof(name));
module_put(target->me);
strncpy(t->u.user.name, name, sizeof(t->u.user.name));
*size += off;
*dstptr += tsize;
}
以上这个代码的例子,就算是仔细看,基本上也很难看出它的漏洞点在哪,甚至作者本人都难以理解这段代码到底何处存在内存泄露。
这段代码漏洞点如下:
if (pad > 0)
memset(t->data + target->targetsize, 0, pad); //漏洞代码
变量target->targetsize
通过XT_ALIGN(target->targetsize)进行了字节对齐,计算出了需要补齐的字节数pad。但是t->data并没有字节对齐,而这段代码默认了t->data的字节对齐。这就导致了memset函数操作的时候,可能会覆盖掉下一个对象的部分字节。于是覆盖掉的部分可以通过内存重复使用,进行提权控制PC。
像这种常规的操作,Linuxkernel里面的代码数以万计,至于有多少漏洞,被审计了的有多少,被修复的有多少,还没有被发现的又有多少,难以统计和知道。
猜想,没有人愿意自己的资产经常被人攻击和利用吧。
Rust
Rust鉴于C/C++的这种隐蔽性的不安全操作,基本上针对于语言的设计从一开始就避免了漏洞的生存空间,
1.内存安全
确保内存的释放和分配有编译器检查,每块内存都有唯一的所有者,一旦所有者离开作用域,内存自动释放。借用概念进一步避免了悬浮指针和内存泄漏。
2.不可变和默认行为
所有变量默认不可变,你想要变?可以,你自己声明下mut,出了问题也好追查。
3.并发安全
直接研发出无数据竞争的线程模型,它依靠的就是所有权和借用权的规则,无线程竞争,并发自然是绝对的安全可靠,毋庸置疑。另外提供了线程安全的标准库std::sync
和 std::thread,
Send和
Sync,
trait等等。
4.未定义行为
unsafe
代码时,未定义行为仍受限于严格的规则。结尾
总体来说,Rust你想要写出不安全的代码,会受到种种限制。而C/C++你想要写出较为安全的代码,则是非常困难的。
按照目前的趋势,Rust在缓慢崛起。C/C++依旧规模庞大,但百足之虫死而不僵,它们的影响力依然可以发挥较长的时间。
往期精彩回顾
C++20重量级特性:模块(modules)
关注公众号↑↑↑:江湖评谈