CVE-2022-1721: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') (CWE-22)
value: Path Traversal in WellKnownServlet in GitHub repository jgraph/drawio prior to 18.0.5. Read local files of the web application.
CWE description: 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.
CVSS v3 base score: 7.5
Published: 2022-05-16T15:15Z
Repository: https://github.com/jgraph/drawio
Language: Java
Files changed: src/main/java/com/mxgraph/online/WellKnownServlet.java
Commit date: 2022-05-15 11:13:37 +0100
Commit message: Limit wellknown servlet to serve single file
Diff: diff --git a/src/main/java/com/mxgraph/online/WellKnownServlet.java b/src/main/java/com/mxgraph/online/WellKnownServlet.java
index be0f0f25c..c702cecff 100644
--- a/src/main/java/com/mxgraph/online/WellKnownServlet.java
+++ b/src/main/java/com/mxgraph/online/WellKnownServlet.java
@@ -12,11 +12,11 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 /**
- * Servlet to fake a .well-known directory
+ * Servlet to fake a .well-known directory, GAE does not directly support . prefixed directories
  */
 @SuppressWarnings("serial")
 public class WellKnownServlet extends HttpServlet
 {
 	private static final Logger log = Logger
@@ -36,33 +36,43 @@ public class WellKnownServlet extends HttpServlet
 	protected void doGet(HttpServletRequest request,
 			HttpServletResponse response) throws ServletException, IOException
 	{
         // GAE can't serve dot prefixed folders
         String uri = request.getRequestURI().replace("/.", "/");
-
-        if (uri.toLowerCase().contains(".json"))
-        {
-        	response.setContentType("application/json");
-        }
-
-        // Serve whatever was requested from .well-known
-        try (InputStream in = getServletContext().getResourceAsStream(uri))
+        
+        // Currently, there is only one file that this servlet serves. This is only
+        // needed if you want OneDrive integration. 
+        if (uri != null && uri.equals("/well-known/microsoft-identity-association.json"))
         {
-            if (in == null)
+            if (uri.toLowerCase().contains(".json"))
             {
-            	response.sendError(404);
-                return;
+                response.setContentType("application/json");
             }
-            
-            byte[] buffer = new byte[8192];
-            int count;
 
-            while ((count = in.read(buffer)) > 0)
+            // Serve whatever was requested from .well-known
+            try (InputStream in = getServletContext().getResourceAsStream(uri))
             {
-            	response.getOutputStream().write(buffer, 0, count);
+                if (in == null)
+                {
+                    response.sendError(404);
+                    return;
+                }
+                
+                byte[] buffer = new byte[8192];
+                int count;
+
+                while ((count = in.read(buffer)) > 0)
+                {
+                    response.getOutputStream().write(buffer, 0, count);
+                }
+                
+                response.getOutputStream().flush();
+                response.getOutputStream().close();
             }
-            
-            response.getOutputStream().flush();
-            response.getOutputStream().close();
+        }
+        else
+        {
+            response.sendError(404);
+            return;
         }
     }
 }

Vulnerable code:  * Servlet to fake a .well-known directory

        if (uri.toLowerCase().contains(".json"))
        {
        	response.setContentType("application/json");
        }

        // Serve whatever was requested from .well-known
        try (InputStream in = getServletContext().getResourceAsStream(uri))
            if (in == null)
            	response.sendError(404);
                return;
            
            byte[] buffer = new byte[8192];
            int count;
            while ((count = in.read(buffer)) > 0)
            	response.getOutputStream().write(buffer, 0, count);
            
            response.getOutputStream().flush();
            response.getOutputStream().close();
Fixed code:  * Servlet to fake a .well-known directory, GAE does not directly support . prefixed directories
        
        // Currently, there is only one file that this servlet serves. This is only
        // needed if you want OneDrive integration. 
        if (uri != null && uri.equals("/well-known/microsoft-identity-association.json"))
            if (uri.toLowerCase().contains(".json"))
                response.setContentType("application/json");
            // Serve whatever was requested from .well-known
            try (InputStream in = getServletContext().getResourceAsStream(uri))
                if (in == null)
                {
                    response.sendError(404);
                    return;
                }
                
                byte[] buffer = new byte[8192];
                int count;

                while ((count = in.read(buffer)) > 0)
                {
                    response.getOutputStream().write(buffer, 0, count);
                }
                
                response.getOutputStream().flush();
                response.getOutputStream().close();
        }
        else
        {
            response.sendError(404);
            return;