我正在尝试了解flask-security
令牌创建的工作原理。我的flask
应用程序配置中有一个密钥,但我们的代码是开源的,并且在python中,所以它不是很秘密,真的。
我可以在代码中访问创建令牌的序列化程序:
serializer = current_app.extensions['security'].remember_token_serializer
然后我可以serializer.loads(token)
并收到用户名和哈希密码。
所以我的问题是这样:什么阻止恶意用户收听我的流量,具有密钥,做同样的事情 - 获得flask-security
令牌序列化程序,并反序列化我的令牌? flask
在创建令牌时是否使用了其他一些盐?但是,如果要重新启动服务,它将如何解密令牌?
答案 0 :(得分:3)
我不完全确定实施细节以及如何生成令牌(但我非常确定烧瓶安全性使用itsdangerous
)。
令牌的主要用途不是存储您不希望任何人看到的秘密,因为令牌很容易被任何人解码和查看(这就是采取额外措施的原因)存储无法解密的密码哈希值。
令牌用于将数据从一个源(客户端)发送到另一个源(服务器),并确保数据不是由任何人修改或更改
是的,任何人都可以查看内部并查看令牌中包含的内容,重点是没有密钥没有人可以篡改数据,如果攻击者生成自己的令牌,他必须使用{{ 1}}否则该标记将被烧瓶安全性拒绝,因为它无效。
这是一个快速演示我的意思是使用itsdangerous(Flask本身使用这个库进行会话)
我们假设在您的应用中,您只会通过检查令牌中的参数secret key
是否设置为is_admin
来授予用户管理员权限。
非管理员用户John进行身份验证并将其令牌发送给他。
'true'
在某种程度上,攻击者拦截令牌并且足够聪明,他知道令牌是base64编码的字符串,因此可以很容易地将它们解码回原始形式。 Python甚至在标准库中都有一个模块,所以他不必为自己压力。
from itsdangerous import URLSafeSerializer
>>> s = URLSafeSerializer('secret key')
>>> s.dumps({'username': 'john', 'is_admin': 'false'})
'eyJ1c2VybmFtZSI6ImpvaG4iLCJpc19hZG1pbiI6ImZhbHNlIn0.k45WPrVOG1Nrags0bwpVUbS7Vcw'
就像他能够解码我们的令牌并查看其中的内容(这就是为什么密码被哈希以获得额外的安全性)
由于他知道我们期望的参数,因此可以自然地猜测import base64
>>> base64.b64decode('eyJ1c2VybmFtZSI6ImpvaG4iLCJpc19hZG1pbiI6ImZhbHNlIn0===')
b'{"username":"john","is_admin":"false"}'
设置为is_admin
的任何用户都可以访问普通用户不会访问的内容,然后他会这样做继续生成自己的令牌。
由于他没有我们的服务器秘密,他只是使用随机秘密
true
好,然后他将令牌发送到我们的服务器。
当我们尝试使用我们的Serializer(已配置为使用我们的服务器密钥)解码令牌时,我们会收到错误消息。并且攻击者无法进入,因为他使用了错误的秘密来签署他的令牌。
>>> t = URLSafeSerializer('fake key')
>>> t.dumps({'username': 'john', 'is_admin': 'true'})
'eyJ1c2VybmFtZSI6ImpvaG4iLCJpc19hZG1pbiI6InRydWUifQ.fPUeGmfSaQWCysy5WWTmmMeuo6c'
服务器只能验证使用其密钥签名的令牌。因此,只要您的服务器密钥没有被泄露,您就不必担心任何人将修改过的数据发送到您的应用程序。
你只需要确保你不存储真正的秘密"在令牌
中>>> s.loads('eyJ1c2VybmFtZSI6ImpvaG4iLCJpc19hZG1pbiI6InRydWUifQ.fPUeGmfSaQWCysy5WWTmmMeuo6c')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/danidee/venv/lib/python3.5/site-packages/itsdangerous.py", line 582, in loads
return self.load_payload(self.make_signer(salt).unsign(s))
File "/home/danidee/venv/lib/python3.5/site-packages/itsdangerous.py", line 374, in unsign
payload=value)
itsdangerous.BadSignature: Signature b'fPUeGmfSaQWCysy5WWTmmMeuo6c' does not match
>>>
即使您尝试将权利令牌中的签名附加到错误的数据上,它也无法生效,您仍然会收到错误
# We can always load the correct token back
s.loads('eyJ1c2VybmFtZSI6ImpvaG4iLCJpc19hZG1pbiI6ImZhbHNlIn0.k45WPrVOG1Nrags0bwpVUbS7Vcw')
{'username': 'john', 'is_admin': 'false'}
免责声明:这可能不是烧瓶安全的确切实现,但我的回答应该让您了解幕后发生的事情。您可能还想阅读JSON web tokens
并且不要将您的秘密存储在配置文件中,将其存储在s.loads('eyJ1c2VybmFtZSI6ImpvaG4iLCJpc19hZG1pbiI6InRydWUifQ.k45WPrVOG1Nrags0bwpVUbS7Vcw')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/danidee/venv/lib/python3.5/site-packages/itsdangerous.py", line 582, in loads
return self.load_payload(self.make_signer(salt).unsign(s))
File "/home/danidee/venv/lib/python3.5/site-packages/itsdangerous.py", line 374, in unsign
payload=value)
itsdangerous.BadSignature: Signature b'k45WPrVOG1Nrags0bwpVUbS7Vcw' does not match
(不能成为源代码管理的一部分)中,或者将其设置为环境变量并导出/设置生产环境中的变量。
结帐dotenv