Bootstrap

【CTF-Events】R3CTF/YUANHENGCTF 2024 两道密码题记录一下

R3CTF2024 WP

Crypto

R0System

考点:代码审计 ECDH

打开代码后有两个小系统,看一下功能

image-20240611160303897

然后再看一下登录之后有哪些功能

image-20240611160827260

其实到这里就可以发现一个非常明显的漏洞点了, 重置密码,但是对用户名没有任何限制,这就导致任何用户,可以重置任何用户的密码

image-20240611162002831

这是泄露的内容,看到Alice和Bob,两个人在传输信息,并且涉及到公钥的交换,其实大体可以确定使用了非对称加密,进行密钥交换,既然是Alice发给Bob的消息,Alice用Bob的公钥进行加密,Bob想要解密必然需要使用自己的私钥进行解密,所以我们的目标是获得Bob的私钥

image-20240611162653898

这里是进行交换密钥的地方,逻辑比较简单

ecdhs是ECDH类的一个对象,调用A用户的该方法,与B的公钥进行交换,就可以得到AB之间的共享密钥

这样发给B之后,B只需要用自己的该方法,传入A的公钥进行交换,就能得到AB之间的共享密钥进行解密

共享密钥生成流程图大概如下:

image-20240611163557634

那么获取B的私钥是我们当前需要完成的,途径也很明确,登录上B的账号 直接让系统返回

步骤:

注册一个普通用户01

登录01

修改Bob的密码

退出01

登录Bob

获取私钥

拿到B的私钥后,我们需要恢复共享密钥是什么,这个在本地直接调用给出的代码就好,不过要仔细观察系统的传值形式

注册普通用户

image-20240611165053157

重置Bob的密码

image-20240611165140437

登录Bob拿私钥

image-20240611165221649

拿泄露数据

image-20240611165241935

因为可以看到flag的加密方式就是用共享密钥做了一个AES的简单加密

下面本地恢复共享密钥

image-20240611165437402

首先可以发现exchange_key传参的内容是一个二元组,但是我们获得的泄露的公钥信息只是一个长字符串,所以需要转换成二元组,同时题目已经给出我们转换的方法了

exp:

from hashlib import md5
from utils import *  #注意一定要在同文件夹下导包直接用给出的代码


B_private_key = 0xef7c7923ef85988c24c6f66c6799ccb285691ca9cbc0c4dfd259d84e6b4a2f90   #这是十六进制格式的
A_pub = 'e7e620bb5a43a7ac3a78f908f6e1f702fe4d9176adfe3e1efa22df1d636aa7ab08a32839893d6ed323aa01eefb2fc7393250299252ba96339f43cb40c658f28c'  #这个因为需要转化成二元组 所以是字符串


print(b2p(bytes.fromhex(A_pub)))
print(p2b(b2p(bytes.fromhex(A_pub))).hex())

#字符串转化为二元组
A_pub_ = b2p(bytes.fromhex(A_pub))

# pub_key =(85971966356924244980831307020457178590563197663408196712967537635077016642444, 79000431020590387084280106635416454953038752073893771961864570482154499521525)
class ECDH:
    def __init__(self):
        self.curve = Curve()
        self.private_key = B_private_key  #这是十六进制格式的
        self.public_key  = self.curve.mul(self.private_key, self.curve.G)  #根据私钥会自动生成公钥

    #进行密钥交换合成
    def exchange_key(self,others_publickey):
        print(self.public_key)
        return md5(str(self.curve.mul(self.private_key,others_publickey)).encode()).digest()
    

f = ECDH() #用户B和A进行交换
print("flag",f.exchange_key(A_pub_).hex())  #注意最后的格式 给出hex 作为AES的key

拿下:

image-20240611204330897

R1System

考点:代码审计 ECDH

首先要说一下 这个题非了,R2是他的修复版

image-20240611204954589

可以发现 开始的时候题目先自己注册了Alice的账号 那Bob呢

image-20240611205027002

这也就是说 如果没有用户登录,Bob是不会注册的

所以我们能不能先直接注册一个Bob的账号

image-20240611205109202

答案是可以的,因为这个限制只限制了Alice的账号不能注册 这也是非的点

这样先别登录 直接注册一个Bob的账号

拿到和R0的信息 相同的解法 就不赘述了


以上就是赛时做出来的题目,其他的期待复现见!

;