Low severityNVD Advisory· Published Mar 25, 2013· Updated Apr 29, 2026
CVE-2013-1835
CVE-2013-1835
Description
Moodle 2.x through 2.1.10, 2.2.x before 2.2.8, 2.3.x before 2.3.5, and 2.4.x before 2.4.2 allows remote authenticated administrators to obtain sensitive information from the external repositories of arbitrary users by leveraging the login_as feature.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
moodle/moodlePackagist | >= 2.0.0, < 2.2.8 | 2.2.8 |
moodle/moodlePackagist | >= 2.3.0, < 2.3.5 | 2.3.5 |
moodle/moodlePackagist | >= 2.4.0, < 2.4.2 | 2.4.2 |
Affected products
36cpe:2.3:a:moodle:moodle:2.0.0:*:*:*:*:*:*:*+ 35 more
- cpe:2.3:a:moodle:moodle:2.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.1:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.2:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.3:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.4:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.5:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.6:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.7:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.8:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.0.9:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.0:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.1:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.10:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.2:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.3:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.4:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.5:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.6:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.7:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.8:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.1.9:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.2.0:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.2.1:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.2.2:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.2.3:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.2.4:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.2.5:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.2.6:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.2.7:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.3.0:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.3.1:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.3.2:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.3.3:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.3.4:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.4.0:*:*:*:*:*:*:*
- cpe:2.3:a:moodle:moodle:2.4.1:*:*:*:*:*:*:*
Patches
3ded4050f1bb0MDL-36426 repository: Prevent login_as() users to access
2 files changed · +44 −9
lang/en/repository.php+1 −1 modified@@ -154,7 +154,7 @@ $string['nofilesavailable'] = 'No files available'; $string['nomorefiles'] = 'No more attachments allowed'; $string['nopathselected'] = 'No destination path select yet (double click tree node to select)'; -$string['nopermissiontoaccess'] = 'No permission to access this repository'; +$string['nopermissiontoaccess'] = 'No permission to access this repository.'; $string['noresult'] = 'No search result'; $string['norepositoriesavailable'] = 'Sorry, none of your current repositories can return files in the required format.'; $string['norepositoriesexternalavailable'] = 'Sorry, none of your current repositories can return external files.';
repository/lib.php+43 −8 modified@@ -487,6 +487,9 @@ abstract class repository { public $returntypes; /** @var stdClass repository instance database record */ public $instance; + /** @var string Type of repository (webdav, google_docs, dropbox, ...). */ + public $type; + /** * Constructor * @@ -519,6 +522,16 @@ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = a $this->name = $this->get_name(); $this->returntypes = $this->supported_returntypes(); $this->super_called = true; + + // Determining the type of repository if not set. + if (empty($this->type)) { + $matches = array(); + if (!preg_match("/^repository_(.*)$/", get_class($this), $matches)) { + throw new coding_exception('The class name of a repository should be repository_<typeofrepository>, '. + 'e.g. repository_dropbox'); + } + $this->type = $matches[1]; + } } /** @@ -620,19 +633,41 @@ public static function get_types($visible=null) { } /** - * Checks if user has a capability to view the current repository in current context + * Checks if user has a capability to view the current repository. * - * @return bool + * @return bool true when the user can, otherwise throws an exception. + * @throws repository_exception when the user does not meet the requirements. */ public final function check_capability() { - $capability = false; - if (preg_match("/^repository_(.*)$/", get_class($this), $matches)) { - $type = $matches[1]; - $capability = has_capability('repository/'.$type.':view', $this->context); + global $USER; + + // Ensure that the user can view the repository in the current context. + $can = has_capability('repository/'.$this->type.':view', $this->context); + + // Context in which the repository has been created. + $repocontext = context::instance_by_id($this->instance->contextid); + + // Prevent access to private repositories when logged in as. + if (session_is_loggedinas()) { + $can = false; + } + + // Ensure that the user can view the repository in the context of the repository. + // Ne need to perform the check when already disallowed. + if ($can) { + if ($repocontext->contextlevel == CONTEXT_USER && $repocontext->instanceid != $USER->id) { + // Prevent URL hijack to access someone else's repository. + $can = false; + } else { + $can = has_capability('repository/'.$this->type.':view', $repocontext); + } } - if (!$capability) { - throw new repository_exception('nopermissiontoaccess', 'repository'); + + if ($can) { + return true; } + + throw new repository_exception('nopermissiontoaccess', 'repository'); } /**
6153c8040dd6MDL-36426 repository: Prevent login_as() users to access
2 files changed · +44 −9
lang/en/repository.php+1 −1 modified@@ -154,7 +154,7 @@ $string['nofilesavailable'] = 'No files available'; $string['nomorefiles'] = 'No more attachments allowed'; $string['nopathselected'] = 'No destination path select yet (double click tree node to select)'; -$string['nopermissiontoaccess'] = 'No permission to access this repository'; +$string['nopermissiontoaccess'] = 'No permission to access this repository.'; $string['noresult'] = 'No search result'; $string['norepositoriesavailable'] = 'Sorry, none of your current repositories can return files in the required format.'; $string['norepositoriesexternalavailable'] = 'Sorry, none of your current repositories can return external files.';
repository/lib.php+43 −8 modified@@ -487,6 +487,9 @@ abstract class repository { public $returntypes; /** @var stdClass repository instance database record */ public $instance; + /** @var string Type of repository (webdav, google_docs, dropbox, ...). */ + public $type; + /** * Constructor * @@ -519,6 +522,16 @@ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = a $this->name = $this->get_name(); $this->returntypes = $this->supported_returntypes(); $this->super_called = true; + + // Determining the type of repository if not set. + if (empty($this->type)) { + $matches = array(); + if (!preg_match("/^repository_(.*)$/", get_class($this), $matches)) { + throw new coding_exception('The class name of a repository should be repository_<typeofrepository>, '. + 'e.g. repository_dropbox'); + } + $this->type = $matches[1]; + } } /** @@ -620,19 +633,41 @@ public static function get_types($visible=null) { } /** - * Checks if user has a capability to view the current repository in current context + * Checks if user has a capability to view the current repository. * - * @return bool + * @return bool true when the user can, otherwise throws an exception. + * @throws repository_exception when the user does not meet the requirements. */ public final function check_capability() { - $capability = false; - if (preg_match("/^repository_(.*)$/", get_class($this), $matches)) { - $type = $matches[1]; - $capability = has_capability('repository/'.$type.':view', $this->context); + global $USER; + + // Ensure that the user can view the repository in the current context. + $can = has_capability('repository/'.$this->type.':view', $this->context); + + // Context in which the repository has been created. + $repocontext = context::instance_by_id($this->instance->contextid); + + // Prevent access to private repositories when logged in as. + if (session_is_loggedinas()) { + $can = false; + } + + // Ensure that the user can view the repository in the context of the repository. + // Ne need to perform the check when already disallowed. + if ($can) { + if ($repocontext->contextlevel == CONTEXT_USER && $repocontext->instanceid != $USER->id) { + // Prevent URL hijack to access someone else's repository. + $can = false; + } else { + $can = has_capability('repository/'.$this->type.':view', $repocontext); + } } - if (!$capability) { - throw new repository_exception('nopermissiontoaccess', 'repository'); + + if ($can) { + return true; } + + throw new repository_exception('nopermissiontoaccess', 'repository'); } /**
31581ae65df0MDL-36426 repository: Prevent login_as() users to access private repositories
17 files changed · +212 −12
lang/en/repository.php+1 −1 modified@@ -158,7 +158,7 @@ $string['nofilesavailable'] = 'No files available'; $string['nomorefiles'] = 'No more attachments allowed'; $string['nopathselected'] = 'No destination path select yet (double click tree node to select)'; -$string['nopermissiontoaccess'] = 'No permission to access this repository'; +$string['nopermissiontoaccess'] = 'No permission to access this repository.'; $string['noresult'] = 'No search result'; $string['norepositoriesavailable'] = 'Sorry, none of your current repositories can return files in the required format.'; $string['norepositoriesexternalavailable'] = 'Sorry, none of your current repositories can return external files.';
repository/coursefiles/lib.php+9 −0 modified@@ -216,4 +216,13 @@ public function get_reference_file_lifetime($ref) { // this should be realtime return 0; } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/equella/lib.php+9 −0 modified@@ -437,4 +437,13 @@ public function get_reference_details($reference, $filestatus = 0) { return get_string('lostsource', 'repository', ''); } } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/filesystem/lib.php+9 −0 modified@@ -333,4 +333,13 @@ public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownlo send_file_not_found(); } } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/flickr_public/lib.php+9 −0 modified@@ -550,4 +550,13 @@ public function supported_returntypes() { public function get_file_source_info($photoid) { return $this->build_photo_url($photoid); } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/lib.php+79 −11 modified@@ -487,6 +487,9 @@ abstract class repository { public $returntypes; /** @var stdClass repository instance database record */ public $instance; + /** @var string Type of repository (webdav, google_docs, dropbox, ...). Read from $this->get_typename(). */ + protected $typename; + /** * Constructor * @@ -558,6 +561,24 @@ public static function get_repository_by_id($repositoryid, $context, $options = } } + /** + * Returns the type name of the repository. + * + * @return string type name of the repository. + * @since 2.5 + */ + public function get_typename() { + if (empty($this->typename)) { + $matches = array(); + if (!preg_match("/^repository_(.*)$/", get_class($this), $matches)) { + throw new coding_exception('The class name of a repository should be repository_<typeofrepository>, '. + 'e.g. repository_dropbox'); + } + $this->typename = $matches[1]; + } + return $this->typename; + } + /** * Get a repository type object by a given type name. * @@ -620,19 +641,43 @@ public static function get_types($visible=null) { } /** - * Checks if user has a capability to view the current repository in current context + * Checks if user has a capability to view the current repository. * - * @return bool + * @return bool true when the user can, otherwise throws an exception. + * @throws repository_exception when the user does not meet the requirements. */ public final function check_capability() { - $capability = false; - if (preg_match("/^repository_(.*)$/", get_class($this), $matches)) { - $type = $matches[1]; - $capability = has_capability('repository/'.$type.':view', $this->context); + global $USER; + + // Ensure that the user can view the repository in the current context. + $can = has_capability('repository/'.$this->get_typename().':view', $this->context); + + // Context in which the repository has been created. + $repocontext = context::instance_by_id($this->instance->contextid); + + // Prevent access to private repositories when logged in as. + if ($can && session_is_loggedinas()) { + if ($this->contains_private_data() || $repocontext->contextlevel == CONTEXT_USER) { + $can = false; + } } - if (!$capability) { - throw new repository_exception('nopermissiontoaccess', 'repository'); + + // Ensure that the user can view the repository in the context of the repository. + // We need to perform the check when already disallowed. + if ($can) { + if ($repocontext->contextlevel == CONTEXT_USER && $repocontext->instanceid != $USER->id) { + // Prevent URL hijack to access someone else's repository. + $can = false; + } else { + $can = has_capability('repository/'.$this->get_typename().':view', $repocontext); + } + } + + if ($can) { + return true; } + + throw new repository_exception('nopermissiontoaccess', 'repository'); } /** @@ -1767,13 +1812,36 @@ public function is_visible() { */ public function get_name() { global $DB; - if ( $name = $this->instance->name ) { + if ($name = $this->instance->name) { return $name; } else { - return get_string('pluginname', 'repository_' . $this->options['type']); + return get_string('pluginname', 'repository_' . $this->get_typename()); } } + /** + * Is this repository accessing private data? + * + * This function should return true for the repositories which access external private + * data from a user. This is the case for repositories such as Dropbox, Google Docs or Box.net + * which authenticate the user and then store the auth token. + * + * Of course, many repositories store 'private data', but we only want to set + * contains_private_data() to repositories which are external to Moodle and shouldn't be accessed + * to by the users having the capability to 'login as' someone else. For instance, the repository + * 'Private files' is not considered as private because it's part of Moodle. + * + * You should not set contains_private_data() to true on repositories which allow different types + * of instances as the levels other than 'user' are, by definition, not private. Also + * the user instances will be protected when they need to. + * + * @return boolean True when the repository accesses private external data. + * @since 2.5 + */ + public function contains_private_data() { + return true; + } + /** * What kind of files will be in this repository? * @@ -1806,7 +1874,7 @@ final public function get_meta() { $meta = new stdClass(); $meta->id = $this->id; $meta->name = format_string($this->get_name()); - $meta->type = $this->options['type']; + $meta->type = $this->get_typename(); $meta->icon = $OUTPUT->pix_url('icon', 'repository_'.$meta->type)->out(false); $meta->supported_types = file_get_typegroup('extension', $this->supported_filetypes()); $meta->return_types = $this->supported_returntypes();
repository/local/lib.php+9 −0 modified@@ -262,4 +262,13 @@ private function get_node_path(file_info $fileinfo) { 'name' => $fileinfo->get_visible_name() ); } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/merlot/lib.php+9 −0 modified@@ -161,5 +161,14 @@ public function supported_returntypes() { public function supported_filetypes() { return array('link'); } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/recent/lib.php+9 −0 modified@@ -203,4 +203,13 @@ public function file_is_accessible($source) { public function has_moodle_files() { return true; } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/s3/lib.php+9 −0 modified@@ -249,4 +249,13 @@ public static function type_config_form($mform, $classname = 'repository') { public function supported_returntypes() { return FILE_INTERNAL; } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/upgrade.txt+5 −0 modified@@ -8,6 +8,11 @@ http://docs.moodle.org/dev/Repository_API * repository::append_suffix() has been deprecated, use repository::get_unused_filename() if you need to get a file name which has not yet been used in the draft area. +* contains_private_data() is a new method to determine if a user 'logged in as' another user + can access the content of the repository. The default is to return True (no access). + +* get_typename() returns the type of repository: dropbox, googledocs, etc... + === 2.4 === * copy_to_area() can receive a new parameter called $areamaxbytes which controls the maximum
repository/upload/lib.php+9 −0 modified@@ -288,4 +288,13 @@ public function get_listing($path = '', $page = '') { public function supported_returntypes() { return FILE_INTERNAL; } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/url/lib.php+9 −0 modified@@ -237,4 +237,13 @@ public function get_file_source_info($url) { public function supported_filetypes() { return array('web_image'); } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/user/lib.php+9 −0 modified@@ -169,4 +169,13 @@ public function get_reference_file_lifetime($ref) { // this should be realtime return 0; } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/webdav/lib.php+10 −0 modified@@ -185,4 +185,14 @@ public static function instance_config_form($mform) { public function supported_returntypes() { return (FILE_INTERNAL | FILE_EXTERNAL); } + + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/wikimedia/lib.php+9 −0 modified@@ -189,4 +189,13 @@ public function supported_returntypes() { public function get_file_source_info($url) { return $url; } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
repository/youtube/lib.php+9 −0 modified@@ -202,4 +202,13 @@ public function supported_filetypes() { public function supported_returntypes() { return FILE_EXTERNAL; } + + /** + * Is this repository accessing private data? + * + * @return bool + */ + public function contains_private_data() { + return false; + } }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-cc94-hwj3-rf65ghsaADVISORY
- moodle.org/mod/forum/discuss.phpnvdVendor AdvisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2013-1835ghsaADVISORY
- lists.fedoraproject.org/pipermail/package-announce/2013-April/101310.htmlnvdWEB
- lists.fedoraproject.org/pipermail/package-announce/2013-April/101358.htmlnvdWEB
- openwall.com/lists/oss-security/2013/03/25/2nvdWEB
- github.com/moodle/moodle/commit/31581ae65df05ea64031ac24c8b8f817414f1379ghsaWEB
- github.com/moodle/moodle/commit/6153c8040dd6ecdf03070ad6b538845c263bf722ghsaWEB
- github.com/moodle/moodle/commit/ded4050f1bb050770df3bc8e78dcfadf815011eaghsaWEB
News mentions
0No linked articles in our index yet.