MDL-72486 core: Add unsafe log and fix options to proxy settings

This commit is contained in:
Brendan Heywood 2022-06-09 14:58:41 +10:00
parent b81fb00f25
commit 9fa26ed911
6 changed files with 89 additions and 0 deletions

View File

@ -172,6 +172,11 @@ if ($hassiteconfig) {
new lang_string('configproxypassword', 'admin'), ''));
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'),
new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
$temp->add(new admin_setting_configcheckbox('proxylogunsafe', new lang_string('proxylogunsafe', 'admin'),
new lang_string('configproxylogunsafe_help', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('proxyfixunsafe', new lang_string('proxyfixunsafe', 'admin'),
new lang_string('configproxyfixunsafe_help', 'admin'), 0));
$ADMIN->add('server', $temp);
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));

View File

@ -326,6 +326,8 @@ $string['configproxypassword'] = 'Password needed to access internet through pro
$string['configproxyport'] = 'If this server needs to use a proxy computer, then provide the proxy port here.';
$string['configproxytype'] = 'Type of web proxy (PHP5 and cURL extension required for SOCKS5 support).';
$string['configproxyuser'] = 'Username needed to access internet through proxy if required, empty if none (PHP cURL extension required).';
$string['configproxyfixunsafe_help'] = 'This attempts to fix internal calls which do not go through the proxy by adding the MoodleBot User Agent and using the proxy.';
$string['configproxylogunsafe_help'] = 'This attempts to log internal calls which do not go through the proxy and should.';
$string['configrecaptchaprivatekey'] = 'String of characters (secret key) used to communicate between your Moodle server and the recaptcha server. ReCAPTCHA keys can be obtained from <a target="_blank" href="https://www.google.com/recaptcha">Google reCAPTCHA</a>.';
$string['configrecaptchapublickey'] = 'String of characters (site key) used to display the reCAPTCHA element in the signup form and site support form. ReCAPTCHA keys can be obtained from <a target="_blank" href="https://www.google.com/recaptcha">Google reCAPTCHA</a>.';
$string['configrequestedstudentname'] = 'Word for student used in requested courses';
@ -1071,6 +1073,8 @@ $string['proxypassword'] = 'Proxy password';
$string['proxyport'] = 'Proxy port';
$string['proxytype'] = 'Proxy type';
$string['proxyuser'] = 'Proxy username';
$string['proxylogunsafe'] = 'Log unproxied calls';
$string['proxyfixunsafe'] = 'Fix unproxied calls';
$string['query'] = 'Query';
$string['question'] = 'Question';
$string['questionbehaviours'] = 'Question behaviours';

View File

@ -3052,6 +3052,38 @@ function file_is_svg_image_from_mimetype(string $mimetype): bool {
return preg_match('|^image/svg|', $mimetype);
}
/**
* Returns the moodle proxy configuration as a formatted url
*
* @return string the string to use for proxy settings.
*/
function get_moodle_proxy_url() {
global $CFG;
$proxy = '';
if (empty($CFG->proxytype)) {
return $proxy;
}
if (empty($CFG->proxyhost)) {
return $proxy;
}
if ($CFG->proxytype === 'SOCKS5') {
// If it is a SOCKS proxy, append the protocol info.
$protocol = 'socks5://';
} else {
$protocol = '';
}
$proxy = $CFG->proxyhost;
if (!empty($CFG->proxyport)) {
$proxy .= ':'. $CFG->proxyport;
}
if (!empty($CFG->proxyuser) && !empty($CFG->proxypassword)) {
$proxy = $protocol . $CFG->proxyuser . ':' . $CFG->proxypassword . '@' . $proxy;
}
return $proxy;
}
/**
* RESTful cURL class
*

View File

@ -828,6 +828,35 @@ if (empty($CFG->sessiontimeoutwarning)) {
}
\core\session\manager::start();
if (!empty($CFG->proxylogunsafe) || !empty($CFG->proxyfixunsafe)) {
if (!empty($CFG->proxyfixunsafe)) {
require_once($CFG->libdir.'/filelib.php');
$proxyurl = get_moodle_proxy_url();
// This fixes stream handlers inside php.
$defaults = stream_context_set_default([
'http' => [
'user_agent' => \core_useragent::get_moodlebot_useragent(),
'proxy' => $proxyurl
],
]);
// Attempt to tell other web clients to use the proxy too. This only
// works for clients written in php in the same process, it will not
// work for with requests done in another process from an exec call.
putenv('http_proxy=' . $proxyurl);
putenv('https_proxy=' . $proxyurl);
putenv('HTTPS_PROXY=' . $proxyurl);
} else {
$defaults = stream_context_get_default();
}
if (!empty($CFG->proxylogunsafe)) {
stream_context_set_params($defaults, ['notification' => 'proxy_log_callback']);
}
}
// Set default content type and encoding, developers are still required to use
// echo $OUTPUT->header() everywhere, anything that gets set later should override these headers.
// This is intended to mitigate some security problems.

View File

@ -2172,3 +2172,21 @@ class bootstrap_renderer {
return $html;
}
}
/**
* Add http stream instrumentation
*
* This detects which any reads or writes to a php stream which uses
* the 'http' handler. Ideally 100% of traffic uses the Moodle curl
* libraries which do not use php streams.
*
* @param array $code stream callback code
*/
function proxy_log_callback($code) {
if ($code == STREAM_NOTIFY_CONNECT) {
$trace = debug_backtrace();
$function = $trace[count($trace) - 1];
$error = "Unsafe internet IO detected: {$function['function']} with arguments " . join(', ', $function['args']) . "\n";
error_log($error . format_backtrace($trace, true)); // phpcs:ignore
}
}

View File

@ -21,6 +21,7 @@ information provided here is intended especially for developers.
Moodle version the plugin is incompatible with but the implemented logic for the check was the opposite. Plugins declaring this
attribute may encounter different behaviours between older Moodle versions (<v3.11.8, <v4.0.2) and the later ones. We recommend
plugin developers to not use this attribute for Moodle versions 4.0 and below in order to avoid this problem.
* Added $CFG->proxylogunsafe and proxyfixunsafe to detect code which doesn't honor the proxy config
=== 4.0 ===