CVE-2021-41152 (Java, published 2021-10-18T21:15Z)
Description: value: OpenOlat is a web-based e-learning platform for teaching, learning, assessment and communication, an LMS, a learning management system. In affected versions by manipulating the HTTP request an attacker can modify the path of a requested file download in the folder component to point to anywhere on the target system. The attack could be used to read any file accessible in the web root folder or outside, depending on the configuration of the system and the properly configured permission of the application server user. The attack requires an OpenOlat user account or the enabled guest user feature together with the usage of the folder component in a course. The attack does not allow writing of arbitrary files, it allows only reading of files and also only ready of files that the attacker knows the exact path which is very unlikely at least for OpenOlat data files. The problem is fixed in version 15.5.8 and 16.0.1 It is advised to upgrade to version 16.0.x. There are no known workarounds to fix this problem, an upgrade is necessary.
Severity: MEDIUM (CVSS v3 base score: 7.7)
Weakness: CWE-22 \u2014 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
Repository: https://github.com/OpenOLAT/OpenOLAT
Files changed:
src/main/java/org/olat/core/commons/modules/bc/FileSelection.java
src/main/java/org/olat/core/commons/modules/bc/commands/CmdDelete.java
src/main/java/org/olat/core/commons/modules/bc/commands/CmdDownloadZip.java
src/main/java/org/olat/core/commons/modules/bc/commands/CmdMoveCopy.java
src/main/java/org/olat/core/commons/modules/bc/commands/CmdUnzip.java
src/main/java/org/olat/core/commons/modules/bc/commands/CmdZip.java
src/main/java/org/olat/core/util/mail/ui/SendDocumentsByEMailController.java
Commit message: OO-5696: validate file selections against current container

Vulnerable code:
import java.util.Arrays;
	private List<String> files = new ArrayList<>();
	private String currentContainerRelPath;
	public FileSelection(UserRequest ureq, String currentContainerRelPath) {
		if (sFiles == null || sFiles.length == 0) return;
		files = Arrays.asList(sFiles);
		this.fileSelection = new FileSelection(ureq, fc.getCurrentContainerPath());
		FileSelection selection = new FileSelection(ureq, folderComponent.getCurrentContainerPath());
			wControl.setWarning(trans.translate("warning.file.selection.empty"));
		this.fileSelection = new FileSelection(ureq, fc.getCurrentContainerPath());
		FileSelection selection = new FileSelection(ureq, folderComponent.getCurrentContainerPath());
		selection = new FileSelection(ureq, folderComponent.getCurrentContainerPath());
		FileSelection selection = new FileSelection(ureq, folderComponent.getCurrentContainerPath());

Fixed code:
import java.util.Set;
import java.util.stream.Collectors;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VFSItem;
	private final List<String> files = new ArrayList<>();
	private final String currentContainerRelPath;
	private final VFSContainer currentContainer;
	public FileSelection(UserRequest ureq, VFSContainer currentContainer, String currentContainerRelPath) {
		this.currentContainer = currentContainer;
		if (sFiles == null || sFiles.length == 0) {
			return;
		}
		List<VFSItem> items = currentContainer.getItems();
		if(items != null && !items.isEmpty()) {
			Set<String> itemNames =  items.stream()
					.map(VFSItem::getName)
					.collect(Collectors.toSet());
			for(String sFile:sFiles) {
				if(itemNames.contains(sFile)) {
					files.add(sFile);
				}
			}
		}
		this.fileSelection = new FileSelection(ureq, fc.getCurrentContainer(), fc.getCurrentContainerPath());
		FileSelection selection = new FileSelection(ureq, folderComponent.getCurrentContainer(), folderComponent.getCurrentContainerPath());
			wControl.setWarning(trans.translate("warning.file.selection.empty22"));
		this.fileSelection = new FileSelection(ureq, fc.getCurrentContainer(), fc.getCurrentContainerPath());
		FileSelection selection = new FileSelection(ureq, folderComponent.getCurrentContainer(), folderComponent.getCurrentContainerPath());
		selection = new FileSelection(ureq, folderComponent.getCurrentContainer(), folderComponent.getCurrentContainerPath());
		FileSelection selection = new FileSelection(ureq, folderComponent.getCurrentContainer(), folderComponent.getCurrentContainerPath());