Tornado的日常犯傻(2)
问题描述
搭建简单的AES
的ECB
攻击试验时,需要直接获取query
参数,但是传过去的参数都是自行构建的,如下:
import time
timestamps = int(time.time()).to_bytes(length=4, byteorder='little')
server_id = settings.SERVER_ID.encode(settings.CHARSET)
plaintext = timestamps + server_id
ciphertext = aes.encrypt(plaintext)
response = requests.get(settings.SERVER_ADDRESS, params={'ciphertext': ciphertext})
可以看到,这里传过去的参数是字节型,且无法直接decode('utf-8')
对应的参数,因为timestamps
我使用了字节存储。如果直接在服务端使用get_argutment('ciphertext')
去获取对应的参数,肯定会直接报错的,因为tornado
的所有获取参数的方法都会对获取到的参数执行默认的decode
操作,如注释所说:
这个方法会在所有get_arguments
被调用,而且它也没有提供可以自行设置字符集的参数(decode('latin1')
其实是可行的)。所以,需要直接得到url
里面的参数,不能使用已经包装好的方法。
问题解决
def get(self, *args, **kwargs):
ciphertext = self.request.query_arguments['ciphertext'][0]
直接从query_arguments
中获取参数
需要注意的是,parse_qs_bytes
方法是使用latin1
进行编码的
考虑到latin1
的编码空间:
Latin1
是ISO-8859-1
的别名,有些环境下写作Latin-1
。ISO-8859-1
编码是单字节编码,向下兼容ASCII
,其编码范围是0x00
-0xFF
,0x00
-0x7F
之间完全和ASCII一致,0x80
-0x9F
之间是控制字符,0xA0
-0xFF
之间是文字符号。
可以看到,latin1
的编码空间符合我对timestamp
的处理,当然,手动引入from tornado.escape import url_unescape
然后对self.request.uri
进行url_unescape(self.request.uri)
也是可以的,这样可控性更好,只是相对麻烦一点。
小结
没事别瞎折腾。。做个实验都快出花了。