0x00 之前

在 RealWorldCTF 里面看到一道白盒审计的题目, 漏洞在一处写反了 decorator 包裹函数的顺序, 而导致的权限绕过, 比较好发现.

0x01 最近

在实际开发中遇到了一个问题, 我们假设有一代码如下:

class User(object):
    username = StringField()
    user_type = StringField(choices=['高富帅', '舔狗'])
    soulmate = ReferenceField(User)

    def get_soulmate_id(self):
        with no_dereference(self) as this:
            if this.user_type == '舔狗':
                raise ValidationError('舔狗最后一无所有')
            if this.id == this.soulmate.id:
                raise ValidationError('做自己的舔狗')
            soulmate_id = this.soulmate.id
        return soulmate_id

这是一个简单的 Mongoengine Model, 并有一个帮助函数用于获取某用户灵魂伴侣的user id的例子.

在我们调用get_soulmate_id()时, 将判断是否为舔狗用户, 如果是则直接中断流程跳到全局的 Exception Handler 中返回错误信息.

并且我们为了减少数据库的查询次数, 使用 no_dereference() 来防止 ReferenceField 自动进行 dereference 的操作.

那么, 这段代码真的能防止舔狗用户获取到自己的 soulmate user id 吗? 当我提出了这个问题时,显然答案是不行的。

0x02 原因

with 语法中所包含的 __exit__ 会捕获期间发生的异常,默认情况下并不会 reraise 到更上层。