CVE-2016-2539 (published 2017-02-07T15:59Z)

Cross-site request forgery (CSRF) vulnerability in install_modules.php in ATutor before 2.2.2 allows remote attackers to hijack the authentication of users for requests that upload arbitrary files and execute arbitrary PHP code via vectors involving a crafted zip file.

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 8.8, HIGH (CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-352
cwe_name: Cross-Site Request Forgery (CSRF)
description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
extended_description: When a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
         

Fix information:
repo_url: https://github.com/atutor/ATutor
commit_details: repo_url: https://github.com/atutor/ATutor
author: Greg Gay
author_date: 2016-03-05 14:12:46-05:00
msg: 5632,5644 removed array_multisort to fix module install issues, and added csrftoken to fix postential CSRF attack
repository: repo_url: https://github.com/atutor/ATutor
repo_name: atutor/ATutor
description: NO LONGER USER LEVEL SUPPORTED. CONTRIBUTING DEVELOPERS INTERESTED IN MAINTAINING ATUTOR, SHOULD REQUEST COLLABORATOR ACCESS. : ATutor is an Open Source Web-based Learning Management System (LMS) used to develop and deliver online courses. Administrators can install or update ATutor in minutes, develop custom themes to give ATutor a new look, and easily extend its functionality with feature modules. Educators can quickly assemble, package, and redistribute standardized Web-based instructional content, easily import prepackaged content, and conduct their courses online. Students learn in an accessible, adaptive, social learning environment.
repo_language: PHP
owner: atutor
file_changes: filename: install_modules.php
change_type: ModificationType.MODIFY
diff: @@ -18,6 +18,8 @@ admin_authenticate(AT_ADMIN_PRIV_MODULES);
 require(AT_INCLUDE_PATH.'../mods/_core/modules/classes/ModuleListParser.class.php');
 require_once(AT_INCLUDE_PATH.'../mods/_core/file_manager/filemanager.inc.php');
 // delete all folders and files in $dir
+
+
 function clear_dir($dir)
 {
 	if ($dh = opendir($dir)) 
@@ -154,8 +156,15 @@ else if (isset($_POST['install']) || isset($_POST["download"]) || isset($_POST["
 
 			if (!$msg->containsErrors())
 			{
-				header('Location: module_install_step_1.php?mod='.urlencode($module_folder).SEP.'new=1');
-				exit;
+			        if($_POST['csrftoken'] != $_SESSION['token']){
+                        $msg->addError('ACCESS_DENIED');
+                    } else {
+                    
+                        header('Location: module_install_step_1.php?mod='.urlencode($module_folder).SEP.'new=1');                        
+                        exit;
+                    }
+				//header('Location: module_install_step_1.php?mod='.urlencode($module_folder).SEP.'new=1');
+				//exit;
 			}
 		}
 		
@@ -181,8 +190,13 @@ if (isset($_POST['mod'])) {
 	$dir_name = str_replace(array('.','..'), '', $_POST['mod']);
 
 	if (isset($_POST['install_manually'])) {
-		header('Location: '.AT_BASE_HREF.'mods/_core/modules/module_install_step_2.php?mod='.urlencode($dir_name).SEP.'new=1'.SEP.'mod_in=1');
-		exit;
+	// Check for potential  CSRF
+        if($_POST['csrftoken'] != $_SESSION['token']){
+                $msg->addError('ACCESS_DENIED');
+        } else {
+            header('Location: '.AT_BASE_HREF.'mods/_core/modules/module_install_step_2.php?mod='.urlencode($dir_name).SEP.'new=1'.SEP.'mod_in=1');
+            exit;
+        }
 	}
 
 } else if (isset($_POST['install_manually'])) {
@@ -255,16 +269,18 @@ $rows_installed_mods = queryDB($sql, array(TABLE_PREFIX));
 
     // Add $module_list_array as the last parameter, to sort by the common key
     // Sorts by original $module_list_array by reference, then returns true|false
-    $sort_by_version = array_multisort($version, SORT_DESC, $module_list_array);
+    //$sort_by_version = array_multisort($version, SORT_DESC, $module_list_array);
 
 // Create menu for filter ATutor versions
-function select_atversion(){ 
+function select_atversion($v=0){ 
     global $sort_versions;
     $menu = '<form action="'.$_SERVER['PHP_SELF'].'" method="post">'; 
     $menu.= '<select name="atversions">';
     $menu.= '<option value="0">'._AT("all").'</option>';
     foreach($sort_versions as $version){
-        if($version == VERSION){
+        if($version == $v){
+            $menu .= '<option value="'.$version.'" selected="selected">'.$version.'</option>';
+        }else if($version == VERSION){
             $menu .= '<option value="'.$version.'" selected="selected">'.$version.'</option>';
         }else{
             $menu .= '<option value="'.$version.'" >'.$version.'</option>';

programming_language: PHP
filename: install_modules.tmpl.php
change_type: ModificationType.MODIFY
diff: @@ -8,6 +8,7 @@ if ($this->enable_upload) {
 
 		<div class="row">
 			<input type="hidden" name="MAX_FILE_SIZE" value="52428800" />
+			<input type="hidden" name="csrftoken"  value="<?php echo $_SESSION['token'];?>" />
 			<input type="file" name="modulefile"  size="50" />
 		</div>
 		
@@ -26,6 +27,7 @@ if (count($this->keys) > 0)
 {
 ?>
 <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="installform">
+<input type="hidden" name="csrftoken"  value="<?php echo $_SESSION['token'];?>" />
 <table class="data" summary="">
 <thead>
 <tr>
@@ -82,10 +84,23 @@ if ($this->enable_remote_installation === true) {
     <div class="row">
     <?php echo _AT('old_module_notes'); ?>
     </div>
-<?php echo select_atversion(); ?>
+<?php 
+
+if(isset($_POST['atversions'])){
+    $v = htmlspecialchars($_POST['atversions']);
+    $_SESSION['atversion'] = $_POST['atversions'];
+} elseif(isset($_SESSION['atversion'] )){
+    $v = substr($_SESSION['atversion'], 0, 3);
+} else {
+    $v = substr(VERSION, 0, 3);
+}
+echo select_atversion($v); 
+
+?>
 </div>
 </fieldset>
 <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="form">
+<input type="hidden" name="csrftoken"  value="<?php echo $_SESSION['token'];?>" />
 <table class="data" summary="">
 <thead>
 	<tr>

programming_language: PHP