1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Gaetano Giunta |
4
|
|
|
* @copyright (C) 2005-2025 G. Giunta |
5
|
|
|
* @license code licensed under the BSD License: see file license.txt |
6
|
|
|
* |
7
|
|
|
* Parses GET/POST variables |
8
|
|
|
* |
9
|
|
|
* @todo switch params for http compression from 0,1,2 to values to be used directly |
10
|
|
|
* @todo do some more sanitization of received parameters |
11
|
|
|
* @todo move parameters away from global namespace |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
// handle class autoloading: |
15
|
|
|
if (file_exists(__DIR__.'/../vendor/autoload.php')) { |
16
|
|
|
// if the debugger's package is installed as top-level project, and dependencies via Composer, allow finding classes |
17
|
|
|
// from dependencies |
18
|
|
|
include_once(__DIR__.'/../vendor/autoload.php'); |
19
|
|
|
} else { |
20
|
|
|
// assume this is either a standalone install, or installed as Composer dependency |
21
|
|
|
/// @todo if the latter is true, should we just not skip using the custom Autoloader, and let a top-level |
22
|
|
|
/// debugger include this one, taking care of autoloading? |
23
|
|
|
include_once __DIR__ . "/../src/Autoloader.php"; |
24
|
|
|
PhpXmlRpc\Autoloader::register(); |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
// work around register globals - @see https://www.php.net/manual/en/faq.misc.php#faq.misc.registerglobals |
28
|
|
|
if (ini_get('register_globals')) { |
29
|
|
|
function unregister_globals() |
30
|
|
|
{ |
31
|
|
|
// Might want to change this perhaps to a nicer error |
32
|
|
|
if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS'])) { |
33
|
|
|
die('GLOBALS overwrite attempt detected'); |
|
|
|
|
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
// Variables that shouldn't be unset |
37
|
|
|
$noUnset = array('GLOBALS', '_GET', '_POST', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES'); |
38
|
|
|
|
39
|
|
|
$input = array_merge($_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_FILES, |
40
|
|
|
isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array() |
41
|
|
|
); |
42
|
|
|
|
43
|
|
|
foreach ($input as $k => $v) { |
44
|
|
|
if (!in_array($k, $noUnset) && isset($GLOBALS[$k])) { |
45
|
|
|
unset($GLOBALS[$k]); |
46
|
|
|
} |
47
|
|
|
} |
48
|
|
|
} |
49
|
|
|
unregister_globals(); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
// work around magic quotes |
53
|
|
|
if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) { |
54
|
|
|
function stripslashes_deep($value) |
55
|
|
|
{ |
56
|
|
|
$value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value); |
57
|
|
|
|
58
|
|
|
return $value; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
$_GET = array_map('stripslashes_deep', $_GET); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
if (function_exists('mb_detect_encoding')) { |
65
|
|
|
$preferredEncodings = 'UTF-8, ASCII, ISO-8859-1, UTF-7, EUC-JP, SJIS, eucJP-win, SJIS-win, JIS, ISO-2022-JP'; |
66
|
|
|
if (isset($_GET['usepost']) && $_GET['usepost'] === 'true') { |
67
|
|
|
$_GET = $_POST; |
68
|
|
|
$inputcharset = mb_detect_encoding(implode('', $_GET), $preferredEncodings); |
69
|
|
|
} else { |
70
|
|
|
$inputcharset = mb_detect_encoding(urldecode($_SERVER['REQUEST_URI']), $preferredEncodings); |
71
|
|
|
} |
72
|
|
|
} else { |
73
|
|
|
/// @todo do is there a better strategy? At least for the POST case, there is probably an http header to look at... |
74
|
|
|
$inputcharset = 'UTF8'; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/// @todo if $inputcharset is not UTF8, we should probably re-encode $_GET to make it UTF-8 |
78
|
|
|
|
79
|
|
|
// recover input parameters |
80
|
|
|
/// @todo instead of using globals, move them to an array. Also: use a class for this parsing... |
81
|
|
|
$debug = 0; |
82
|
|
|
$protocol = 0; |
83
|
|
|
$run = false; |
84
|
|
|
$hasjsonrpcclient = class_exists('\PhpXmlRpc\JsonRpc\Client'); |
85
|
|
|
$wstype = defined('DEFAULT_WSTYPE') ? DEFAULT_WSTYPE : 0; |
|
|
|
|
86
|
|
|
$id = ''; |
87
|
|
|
if (isset($_GET['action'])) { |
88
|
|
|
if (isset($_GET['wstype']) && ($_GET['wstype'] == '1' || $_GET['wstype'] == '0')) { |
89
|
|
|
$wstype = (int)$_GET['wstype']; |
90
|
|
|
if ($wstype === 1 && !$hasjsonrpcclient) { |
91
|
|
|
$wstype = 0; |
92
|
|
|
} |
93
|
|
|
if ($wstype === 1 && isset($_GET['id'])) { |
94
|
|
|
$id = $_GET['id']; |
95
|
|
|
} |
96
|
|
|
} |
97
|
|
|
$host = isset($_GET['host']) ? $_GET['host'] : 'localhost'; // using '' will trigger an xml-rpc error... |
98
|
|
|
if (isset($_GET['protocol']) && ($_GET['protocol'] == '1' || $_GET['protocol'] == '2' || $_GET['protocol'] == '3' |
99
|
|
|
|| $_GET['protocol'] == '4')) { |
100
|
|
|
$protocol = (int)$_GET['protocol']; |
101
|
|
|
} |
102
|
|
|
if (strpos($host, 'http://') === 0) { |
103
|
|
|
// NB: if protocol is https or h2, it will override http:// |
104
|
|
|
$host = substr($host, 7); |
105
|
|
|
} elseif (strpos($host, 'https://') === 0) { |
106
|
|
|
$host = substr($host, 8); |
107
|
|
|
// NB: otoh if protocol is http1.0 or http1.1, it will be overridden by https:// |
108
|
|
|
if ($protocol == 0 || $protocol = 1) { |
109
|
|
|
$protocol = 2; |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
$port = isset($_GET['port']) ? (int)$_GET['port'] : ''; |
113
|
|
|
if ($port === 0) { |
114
|
|
|
$port = ''; |
115
|
|
|
} |
116
|
|
|
$path = isset($_GET['path']) ? $_GET['path'] : ''; |
117
|
|
|
// in case user forgot initial '/' in xml-rpc server path, add it back |
118
|
|
|
if ($path && ($path[0]) != '/') { |
119
|
|
|
$path = '/' . $path; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
if (isset($_GET['debug']) && ($_GET['debug'] == '1' || $_GET['debug'] == '2')) { |
123
|
|
|
$debug = (int)$_GET['debug']; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
$verifyhost = (isset($_GET['verifyhost']) && ($_GET['verifyhost'] == '1' || $_GET['verifyhost'] == '2')) ? $_GET['verifyhost'] : 0; |
127
|
|
|
if (isset($_GET['verifypeer']) && $_GET['verifypeer'] == '1') { |
128
|
|
|
$verifypeer = true; |
129
|
|
|
} else { |
130
|
|
|
$verifypeer = false; |
131
|
|
|
} |
132
|
|
|
$cainfo = isset($_GET['cainfo']) ? $_GET['cainfo'] : ''; |
133
|
|
|
$proxy = isset($_GET['proxy']) ? $_GET['proxy'] : 0; |
134
|
|
|
if (strpos($proxy, 'http://') === 0) { |
135
|
|
|
$proxy = substr($proxy, 7); |
136
|
|
|
} |
137
|
|
|
/// @todo what about an https proxy? |
138
|
|
|
$proxyuser = isset($_GET['proxyuser']) ? $_GET['proxyuser'] : ''; |
139
|
|
|
$proxypwd = isset($_GET['proxypwd']) ? $_GET['proxypwd'] : ''; |
140
|
|
|
$timeout = isset($_GET['timeout']) ? (int)$_GET['timeout'] : 0; |
141
|
|
|
$action = $_GET['action']; |
142
|
|
|
|
143
|
|
|
$method = isset($_GET['method']) ? $_GET['method'] : ''; |
144
|
|
|
$methodsig = isset($_GET['methodsig']) ? $_GET['methodsig'] : 0; |
145
|
|
|
$payload = isset($_GET['methodpayload']) ? $_GET['methodpayload'] : ''; |
146
|
|
|
$alt_payload = isset($_GET['altmethodpayload']) ? $_GET['altmethodpayload'] : ''; |
147
|
|
|
|
148
|
|
|
if (isset($_GET['run']) && $_GET['run'] == 'now') { |
149
|
|
|
$run = true; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
$username = isset($_GET['username']) ? $_GET['username'] : ''; |
153
|
|
|
$password = isset($_GET['password']) ? $_GET['password'] : ''; |
154
|
|
|
|
155
|
|
|
$authtype = (isset($_GET['authtype']) && ($_GET['authtype'] == '2' || $_GET['authtype'] == '8')) ? (int)$_GET['authtype'] : 1; |
156
|
|
|
|
157
|
|
|
if (isset($_GET['requestcompression']) && ($_GET['requestcompression'] == '1' || $_GET['requestcompression'] == '2')) { |
158
|
|
|
(int)$requestcompression = $_GET['requestcompression']; |
159
|
|
|
} else { |
160
|
|
|
$requestcompression = 0; |
161
|
|
|
} |
162
|
|
|
if (isset($_GET['responsecompression']) && ($_GET['responsecompression'] == '1' || $_GET['responsecompression'] == '2' || $_GET['responsecompression'] == '3')) { |
163
|
|
|
$responsecompression = (int)$_GET['responsecompression']; |
164
|
|
|
} else { |
165
|
|
|
$responsecompression = 0; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
$clientcookies = isset($_GET['clientcookies']) ? $_GET['clientcookies'] : ''; |
169
|
|
|
} else { |
170
|
|
|
$host = ''; |
171
|
|
|
$port = ''; |
172
|
|
|
$path = ''; |
173
|
|
|
$action = ''; |
174
|
|
|
$method = ''; |
175
|
|
|
$methodsig = 0; |
176
|
|
|
$payload = ''; |
177
|
|
|
$alt_payload = ''; |
178
|
|
|
$username = ''; |
179
|
|
|
$password = ''; |
180
|
|
|
$authtype = 1; |
181
|
|
|
$verifyhost = 0; |
182
|
|
|
$verifypeer = false; |
183
|
|
|
$cainfo = ''; |
184
|
|
|
$proxy = ''; |
185
|
|
|
$proxyuser = ''; |
186
|
|
|
$proxypwd = ''; |
187
|
|
|
$timeout = 0; |
188
|
|
|
$requestcompression = 0; |
189
|
|
|
$responsecompression = 0; |
190
|
|
|
$clientcookies = ''; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
// check input for known attacks against this or other libs |
194
|
|
|
function payload_is_safe($input) |
|
|
|
|
195
|
|
|
{ |
196
|
|
|
return true; |
197
|
|
|
} |
198
|
|
|
|
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.