Skip to content

Add File Extension Verification By MIME Type#13

Open
cjwetherington wants to merge 7 commits intoajnyga:masterfrom
cjwetherington:add-mime-type-validation
Open

Add File Extension Verification By MIME Type#13
cjwetherington wants to merge 7 commits intoajnyga:masterfrom
cjwetherington:add-mime-type-validation

Conversation

@cjwetherington
Copy link
Copy Markdown

Summary

This PR represents a substantial addition motivated by issues like #9. While not foolproof, it adds significant security enhancements that can prevent uploads of deceptive and malicious files. In addition to enhancing the effectiveness of the existing convenience features, this PR adds functionality to address several specific security concerns:

  • File type spoofing: Malicious executables disguised as documents
  • Extensionless file attacks: Executables uploaded without extensions to bypass filters
  • Multi-extension attacks: Files like malware.php.txt bypassing the existing extension check
  • Empty files: Files that may be empty due to corruption or as part of social engineering attacks

Backwards Compatability

New optional features introduced in this plugin will not disrupt current installations on upgrade. Plugin admins will need to opt-in to these added features via the settings panel.

MIME Type Validation

The major addition is verification of the file extension by MIME type. If a user has renamed a file in order to make it appear to be an allowed type ("spoofing"), the plugin should detect this and prevent the upload:

image

Multiple Extension Blocking

Multiple extensions are blocked unless explicitly added to the allowlist. E.g., example.php.txt will be blocked with the allowlist doc;php;txt but will be permitted with the allowlist doc;php;php.txt;txt. This is helpful for some common valid multi-extension file types such as .tar.gz.

image

Extensionless/Hidden File Blocking

Files with no extension or with hidden file naming are a significant security vulnerability in the existing plugin architecture. This PR adds logic to block them universally. If administrators have a legitimate need to accept extensionless or hidden files, submitters could be asked to append a specific, novel extension that the administrators have included in the allowlist.

image

Empty File Blocking

Empty files (i.e. files with 0 bytes) are a potential attack or nuisance vector and can be optionally blocked with an additional setting.

image

Incident Logging

Ordinary blocking of file uploads is not logged (e.g. attempted upload of .doc when only .docx is permitted), as we can generally assume this to stem from honest mistakes by users. Spoofing of file types, however, is indicative of deliberate deception, so these attempts and corresponding user account IDs are recorded to the OJS logs:
[Sun Nov 02 01:33:50.574610 2025] [php:notice] [pid 17:tid 17] [client XXX.XX.0.X:XXXXX] AllowedUploads: SECURITY - MIME type mismatch for user 1 in context 1: imagespoofed.txt (detected: image/jpeg, expected: text/plain), referer: http://localhost:8080/index.php/jambalaya/submission?id=1

Settings Panel

The two added options appear with checkbox functionality in the settings form. As above, these settings will default to values that will not change existing installations on update, so MIME typing will be OFF by default and empty file allowance ON.

image

MIME Detection Malfunction Failsafe

OJS 3.4+ requires versions of PHP that contain built-in MIME type detection functionality by default. If for some reason PHP's finfo methods fail, the plugin reverts to an older MIME detection methodology. Only on a very, very broken installation would neither method be available, but in the event that occurs, the MIME option will present an error if the admin attempts to enable the MIME validation option:

image

Locales

Translations for the existing languages supported by the plugin have been added for the new messages using Google Translate. They will almost certainly benefit from editing by native speakers, but what is supplied should hopefully provide a reasonable starting point.

Code

The code attempts to follow the existing architecture as best as possible. DocBlocks with annotations are supplied for all functions added by this PR. Some inline comments have been left in place to facilitate code review, but I'd be happy to remove them if desired. The file-extension-to-MIME-type mapping array attempts to accommodate many different academic journal submission needs, but I am happy to expand it if something has been overlooked. It doesn't map many of the more "dangerous" file types (e.g. .exe, .php) as it is assumed that any journal accepting such file types will probably not find much benefit from disallowing uploads on the basis of file extension.

README

Some basic description text has been added to the settings form, but I have not updated the README to reflect the features added. If this PR is accepted I will gladly update the main README to document the added features.

Please let me know you have any questions or suggestions. Cheers.

@cjwetherington
Copy link
Copy Markdown
Author

@ajnyga Just pinging you here because I know GitHub notifications don't always inform well about PRs.

@ajnyga
Copy link
Copy Markdown
Owner

ajnyga commented Nov 4, 2025

Thanks, I've seen this but doing a production upgrade of our services and will be busy for the next week at least

@cjwetherington
Copy link
Copy Markdown
Author

No problem at all! Cheers. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants