Django下防御Race Condition漏洞

本文通过一个实例展示了Django应用中如何遭受Race Condition攻击,详细解释了无锁无事务、无锁有事务时的竞争攻击,并提出使用悲观锁和乐观锁结合事务来防御这种并发漏洞。通过实验验证了悲观锁和乐观锁的有效性,提供了防止资产损失的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天下午在v2ex上看到一个帖子,讲述自己因为忘记加分布式锁导致了公司的损失:

c1684f9e019bf8a3ebff1958e90a3b5d.png

我曾在《从Pwnhub诞生聊Django安全编码》一文中描述过关于商城逻辑所涉及的安全问题,其中就包含并发漏洞(Race Condition)的防御,但当时说的比较简洁,也没有演示实际的攻击过程与危害。今天就以v2ex上这个帖子的场景来讲讲,常见的存在漏洞的Django代码,与我们如何正确防御竞争漏洞的方法。

0x01 Playground搭建

首先,使用我这个Django-Cookiecutter脚手架创建一个项目,项目名是Race Condition Playground。

创建两个新的Model:

class User(AbstractUser):
    username = models.CharField('username', max_length=256)
    email = models.EmailField('email', blank=True, unique=True)
    money = models.IntegerField('money', default=0)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    class Meta(AbstractUser.Meta):
        swappable = 'AUTH_USER_MODEL'
        verbose_name = 'user'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username


class WithdrawLog(models.Model):
    user = models.ForeignKey('User', verbose_name='user', on_delete=models.SET_NULL, null=True)
    amount = models.IntegerField('amount')

    created_time = models.DateTimeField('created time', auto_now_add=True)
    last_modify_time = models.DateTimeField('last modify time', auto_now=True)

    class Meta:
        verbose_name = 'withdraw log'
        verbose_name_plural = 'withdraw logs'

    def __str__(self):
        return str(self.created_time)

一个是User表,用以储存用户,其中money字段是这个用户的余额;一个是WithdrawLog表,用以储存提取的日志。我们假设公司财务会根据这个日志表来向用户打款,那么只要成功在这个表中插入记录,则说明攻击成功。

然后,我们编写一个WithdrawForm,其字段amount,表示用户此时想提取的余额,必须是整数:

class Withd
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值