4.4.1.13.威胁:代码替换(OAuth登录)
攻击者可能尝试使用受害者的身份登录应用程序或网站.依赖OAuth保护服务API为登录用户提供的身份数据的应用程序容易受到此威胁的攻击.这种模式可以在所谓的"社交登录"场景中找到.
作为先决条件,资源服务器提供API以获得关于用户的个人信息,该个人信息可被解释为已获得用户身份.从这个意义上讲,客户端将资源服务器API视为"身份"API.客户端使用OAuth获取身份API的访问令牌.然后,它会在身份API中查询标识符,并使用它来查找其内部用户帐户数据(登录).客户端解释因为它能够获得有关用户的信息,用户已经过身份验证.
如果客户端使用授权类型"代码",则攻击者需要从目标客户端应用程序使用的同一身份提供者收集相应受害者的有效授权代码.攻击者使用与目标应用程序相同的身份提供程序欺骗受害者登录恶意应用程序(对于身份提供程序可能看似合法).这导致身份提供者的授权服务器为相应的身份API发布授权代码.恶意应用程序然后将此代码发送给攻击者,攻击者又触发目标应用程序内的登录过程.攻击者现在操纵授权响应并将其代码(绑定到其身份)替换为受害者的代码.然后,客户端将此代码交换为访问令牌,而访问令牌又由身份API接受,因为相对于资源服务器的受众是正确的.但由于身份API返回的标识符由访问令牌中的标识(基于受害者的代码发出)确定,因此攻击者以受害者的身份登录到目标应用程序.
影响:攻击者可以访问应用程序中的应用程序和用户特定数据.
对策:
所有客户端必须在每次请求时指示其客户端ID以交换访问令牌的授权代码.授权服务器必须验证是否已向特定客户端发出特定授权代码.如果可能,客户应事先进行身份验证.
客户端应使用适当的协议,例如OpenID(参见[openid])或SAML(参见[OASIS.sstc-saml-bindings-1.1])来实现用户登录.两者都支持受众对客户的限制.
这对我来说相当混乱:"攻击者需要从目标客户端应用程序使用的同一身份提供者那里收集相应受害者的有效授权码".什么是"相应的受害者"以及"身份提供者"在此后续用途中的含义是什么?
整个攻击描述都很模糊.我开始理解为"不应该使用OAuth 2.0来实现用户登录",但这并不意味着像Facebook这样的主要平台容易受到攻击吗?而且很容易受到什么影响?
我可能只需要澄清本段中使用的一些术语.
我有这样的模特
class Thingy(models.Model):
# ...
failures_count = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)
我有需要执行此操作的并发进程(Celery任务):
failures_counter则相应的增量Thingyfailures_counter超过某些阈值Thingy,发出警告,但只有一个警告.我有一些关于如何在没有竞争条件的情况下执行此操作的想法,例如使用显式锁(via select_for_update):
@transaction.commit_on_success
def report_failure(thingy_id):
current, = (Thingy.objects
.select_for_update()
.filter(id=thingy_id)
.values_list('failures_count'))[0]
if current == THRESHOLD:
issue_warning_for(thingy_id)
Thingy.objects.filter(id=thingy_id).update(
failures_count=F('failures_count') + 1
)
Run Code Online (Sandbox Code Playgroud)
或者通过使用Redis(它已经存在)进行同步:
@transaction.commit_on_success
def report_failure(thingy_id):
Thingy.objects.filter(id=thingy_id).update(
failures_count=F('failures_count') + 1
)
value = Thingy.objects.get(id=thingy_id).only('failures_count').failures_count
if value >= THRESHOLD:
if redis.incr('issued_warning_%s' % thingy_id) == 1:
issue_warning_for(thingy_id)
Run Code Online (Sandbox Code Playgroud)
两种解决方案都使用锁 因为我正在使用PostgreSQL,有没有办法在没有锁定的情况下实现这一点?
我正在编辑问题以包含答案(感谢Sean Vieira,见下面的答案).问题是关于避免锁定的方法,这个答案是最佳的,因为它利用了PostgreSQL实现的多版本并发控制(MVCC).
这个特定问题明确允许使用PostgreSQL功能,虽然许多RDBMS实现UPDATE ... RETURNING,但它不是标准SQL,Django的ORM不支持开箱即用,所以它需要使用原始SQL raw() …