CVE-2022-2128 (published 2022-06-20T17:15Z)

Unrestricted Upload of File with Dangerous Type in GitHub repository polonel/trudesk prior to 1.2.4.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-434
cwe_name: Unrestricted Upload of File with Dangerous Type
description: The product allows the upload or transfer of dangerous file types that are automatically processed within its environment.
extended_description: 
            
            
            
            
            
         
         

Fix information:
repo_url: https://github.com/polonel/trudesk
commit_details: repo_url: https://github.com/polonel/trudesk
author: Chris Brame
author_date: 2022-06-18 12:58:22-04:00
msg: fix(attachments): file type security fix
repository: repo_url: https://github.com/polonel/trudesk
repo_name: polonel/trudesk
description:  :coffee: :seedling: Trudesk is an open-source help desk/ticketing solution.
repo_language: JavaScript
owner: polonel
file_changes: filename: IssuePartial.jsx
change_type: ModificationType.MODIFY
diff: @@ -99,10 +99,12 @@ class IssuePartial extends React.Component {
     const attachmentFile = e.target.files[0]
     formData.append('ticketId', this.ticketId)
     formData.append('attachment', attachmentFile)
+    const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
     axios
       .post(`/tickets/uploadattachment`, formData, {
         headers: {
-          'Content-Type': 'multipart/form-data'
+          'Content-Type': 'multipart/form-data',
+          'CSRF-TOKEN': token
         }
       })
       .then(() => {

programming_language: JavaScript
filename: tickets.js
change_type: ModificationType.MODIFY
diff: @@ -704,9 +704,33 @@ ticketsController.uploadAttachment = function (req, res) {
     let sanitizedFilename = filename.replace(/[^a-z0-9.]/gi, '_').toLowerCase()
 
     const ext = path.extname(sanitizedFilename)
+    const allowedExts = [
+      '.png',
+      '.jpg',
+      '.jpeg',
+      '.tif',
+      '.gif',
+      '.doc',
+      '.docx',
+      '.xlsx',
+      '.xls',
+      '.pdf',
+      '.zip',
+      '.rar',
+      '.7z',
+      '.mp3',
+      '.wav',
+      '.txt',
+      '.mp4',
+      '.avi',
+      '.mpeg',
+      '.eps',
+      '.ai',
+      '.psd'
+    ]
     const badExts = ['.html', '.htm', '.js', '.svg']
 
-    if (badExts.includes(ext)) {
+    if (!allowedExts.includes(ext)) {
       error = {
         status: 400,
         message: 'Invalid File Type'

programming_language: CoffeeScript
filename: index.js
change_type: ModificationType.MODIFY
diff: @@ -203,7 +203,12 @@ function mainRoutes (router, middleware, controllers) {
   router.get('/tickets/print/:uid', middleware.redirectToLogin, middleware.loadCommonData, controllers.tickets.print)
   router.get('/tickets/:id', middleware.redirectToLogin, middleware.loadCommonData, controllers.tickets.single)
   // router.post('/tickets/postcomment', middleware.redirectToLogin, controllers.tickets.postcomment);
-  router.post('/tickets/uploadattachment', middleware.redirectToLogin, controllers.tickets.uploadAttachment)
+  router.post(
+    '/tickets/uploadattachment',
+    middleware.redirectToLogin,
+    middleware.csrfCheck,
+    controllers.tickets.uploadAttachment
+  )
   router.post('/tickets/uploadmdeimage', middleware.redirectToLogin, controllers.tickets.uploadImageMDE)
 
   // Messages

programming_language: CoffeeScript