Bugku login4

随便登录个账号看到提示说只有admin可以能看到flag,尝试登录admin账号,他说admin不允许被登录。看到题目提示说是CBC字节翻转攻击,那么就想他肯定会告诉我们iv、cipher什么的吧,于是burp抓包发包,发现响应头中返回了iv、cipher,但是还没完,因为我们不知道后台对我们传进去的username、password作了什么处理,试了一下,发现存在.index.php.swp,访问下载到备份文件,vim -r index.php.swp即可恢复,下面是关键代码部分

在这里我们可以看到后台将我们传进去的username、password构造成了数组info,登录的时候先将其序列化,再加密形成cookie中的cipher,并以此来作为我们的身份标识。当我们不post数据而是将返回iv、cipher添加到我们的请求头中再次发起请求时,服务器不会更新我们的身份,而是会利用我们请求头中的iv、cipher来解密,再反序列化得到用户名以此来验证我们的身份,我们来验证一下

假设我们的username为admik,密码为123,那么序列化后就为

那我们的思路就是,修改cookie中的值,使其解密出来的username为admin,即将k改为n

知道了思路之后,我们来了解一下CBC是怎么工作的

加密过程

Plaintext:待加密的数据

IV:用于随机化加密的比特块,保证即使对相同明文多次加密,也可以得到不同的密文。

Key:被一些如AES的对称加密算法使用

Ciphertext:加密后的数据

对于第一块密文:Ciphertext = Plaintext ^ IV

对于第二及剩下的组块:Ciphertext(N) = Ciphertext(N-1) ^ Plaintext

即前一块密文用来产生下一块密文,字节翻转攻击就是利用这一点

解密过程

对于第一块:Plaintext = Decrypt(Ciphertext) ^ IV

对于第二块及剩下的:Plaintext(N) = Decrypt(Ciphertext) ^ Ciphertext(N-1)

并且还要注意一点:在密文中改变的字节只会影响在下一明文中具有相同偏移量的字节,即如下图

我们构造的用户名admik账号序列化后为
a:2:{s:8:"username";s:5:"admik";s:8:"password";s:3:"123";}

我们的目标是将k改成n,因此第一件事就是把明文分成16个字节的块:

Block1: a:2:{s:8:"userna

Block2: me";s:5:"admik";

Block3: s:8:"password";s

Block4: :3:"123";}

我们可以看到我们的目标字符位于块2,偏移量为13,这就意味着我们要改变块一中偏移量为13的字符

第二块明文偏移量为13的字符(C) = 第一块密文偏移量为13的字符(A) ^ decrypt(第二块密文的偏移量为13的字符)(B)

即 C = A ^ B,这里我们知道C和A,因此B = A ^ C

假设我们修改A为A2,A2 = A ^ C ^ D(我们想要的字符,这里指n)

那么C = A2 ^ B = A ^ C ^ D ^ A ^ C = 0 ^ D  = D,即

$enc[13] = chr(ord($enc[13]) ^ ord("k") ^ ord ("n"))

这里还有一个问题要注意一下,因为我们修改了第一块的密文,如果我们继续用原来的iv去解密第一块密文,那么肯定是不成功的,是无法反序列化的,因此我们需要修改iv,使其解密第一块得到的是a:2:{s:8:"userna

如何修改iv呢

第一块错误明文 = decrypt(第一块原密文) ^ ord_iv

那么  decrypt(第一块原密文) = 第一块错误明文 ^ ord_iv

第一块正确明文 = decrypt(第一块原密文) ^ new_iv

那么  new_iv = decrypt(第一块原密文) ^ 第一块正确明文 =  第一块错误明文 ^ ord_iv ^ 第一块正确明文

将其url编码替换原来的iv得到flag

参考:http://wooyun.jozxing.cc/static/drops/tips-7828.html

作者水平有限,若有错误请指出Orz

你可能感兴趣的:(Bugku login4)