Query to detect main method in servlets

This commit is contained in:
luchua-bc
2021-02-05 03:53:01 +00:00
parent 649bd03db6
commit a183b00166
10 changed files with 272 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
public class ServletMain implements Servlet {
// BAD - Implement a main method in servlet.
public static void main(String[] args) throws Exception {
// Connect to my server
URL url = new URL("https://www.example.com");
url.openConnection();
}
// GOOD - Not to have a main method in servlet.
}

View File

@@ -0,0 +1,31 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>Debug code can create unintended entry points in a deployed web application therefore should never make into production. There is no reason to have a main method in a web application. Having a main method in a web application increases the attack surface that an attacker can exploit to attack the application logic.</p>
</overview>
<recommendation>
<p>Remove the main method from web components including servlets, filters and listeners.</p>
</recommendation>
<example>
<p>The following example shows two ways of implementing web components. In the 'BAD' case, a main method is implemented. In the 'GOOD' case, no main method is implemented.</p>
<sample src="ServletMain.java" />
</example>
<references>
<li>
Fortify:
<a href="https://vulncat.fortify.com/en/detail?id=desc.structural.java.j2ee_badpractices_leftover_debug_code">J2EE Bad Practices: Leftover Debug Code</a>
</li>
<li>
SonarSource:
<a href="https://rules.sonarsource.com/java/tag/owasp/RSPEC-2653">Web applications should not have a "main" method</a>
</li>
<li>
Carnegie Mellon University:
<a href="https://wiki.sei.cmu.edu/confluence/display/java/ENV06-J.+Production+code+must+not+contain+debugging+entry+points">ENV06-J. Production code must not contain debugging entry points</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,49 @@
/**
* @name Main Method in Servlet
* @description Jave EE web applications with a main method.
* @kind problem
* @id java/main-method-in-servlet
* @tags security
* external/cwe-489
*/
import java
import semmle.code.java.frameworks.Servlets
/** The java type `javax.servlet.Filter` */
class ServletFilterClass extends Class {
ServletFilterClass() { this.getASupertype*().hasQualifiedName("javax.servlet", "Filter") }
}
/** Listener class in the package `javax.servlet` and `javax.servlet.http` */
class ServletListenerClass extends Class {
// Various listener classes of Java EE such as ServletContextListener. They all have a name ending with the word "Listener".
ServletListenerClass() {
this.getASupertype*()
.getQualifiedName()
.regexpMatch([
"javax\\.servlet\\.[a-zA-Z]+Listener", "javax\\.servlet\\.http\\.[a-zA-Z]+Listener"
])
}
}
/** The `main` method in `Servlet`. */
class ServletMainMethod extends Method {
ServletMainMethod() {
(
this.getDeclaringType() instanceof ServletClass or
this.getDeclaringType() instanceof ServletFilterClass or
this.getDeclaringType() instanceof ServletListenerClass
) and
this.hasName("main") and
this.isStatic() and
this.getReturnType() instanceof VoidType and
this.isPublic() and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType() instanceof Array and
not this.getDeclaringType().getName().matches("%Test%") // Simple check to exclude test classes to reduce FPs
}
}
from ServletMainMethod sm
select sm, "Web application has a main method."

View File

@@ -0,0 +1,25 @@
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.net.URL;
public class ServletContextListenerMain implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("listener starts to work!");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("listener stopped!");
}
// BAD - Implement a main method in servlet listener.
public static void main(String[] args) {
try {
URL url = new URL("https://www.example.com");
url.openConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,2 @@
| ServletContextListenerMain.java:17:21:17:24 | main | Web application has a main method. |
| ServletMain.java:28:21:28:24 | main | Web application has a main method. |

View File

@@ -0,0 +1,33 @@
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import java.io.IOException;
import java.net.URL;
public class ServletMain implements Servlet {
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
public void init(ServletConfig servletConfig) throws ServletException {
}
public ServletConfig getServletConfig() {
return null;
}
public String getServletInfo() {
return null;
}
public void destroy() {
}
// BAD - Implement a main method in servlet.
public static void main(String[] args) throws Exception {
// Connect to my server
URL url = new URL("https://www.example.com");
url.openConnection();
}
}

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-489/ServletMain.ql

View File

@@ -0,0 +1 @@
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved.
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.servlet;
/**
* This is the event class for notifications about changes to
* the servlet context of a web application.
* @see ServletContextListener
*
* @since Servlet 2.3
*/
public class ServletContextEvent extends java.util.EventObject {
/** Construct a ServletContextEvent from the given context.
*
* @param source - the ServletContext that is sending the event.
*/
public ServletContextEvent(ServletContext source) {
super(source);
}
/**
* Return the ServletContext that changed.
*
* @return the ServletContext that sent the event.
*/
public ServletContext getServletContext () {
return null;
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved.
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.servlet;
import java.util.EventListener;
/**
* Interface for receiving notification events about ServletContext
* lifecycle changes.
*
* <p>In order to receive these notification events, the implementation
* class must be either declared in the deployment descriptor of the web
* application, annotated with {@link javax.servlet.annotation.WebListener},
* or registered via one of the addListener methods defined on
* {@link ServletContext}.
*
* <p>Implementations of this interface are invoked at their
* {@link #contextInitialized} method in the order in which they have been
* declared, and at their {@link #contextDestroyed} method in reverse
* order.
*
* @see ServletContextEvent
*
* @since Servlet 2.3
*/
public interface ServletContextListener extends EventListener {
/**
* Receives notification that the web application initialization
* process is starting.
*
* <p>All ServletContextListeners are notified of context
* initialization before any filters or servlets in the web
* application are initialized.
*
* @param sce the ServletContextEvent containing the ServletContext
* that is being initialized
*
* @implSpec
* The default implementation takes no action.
*/
default public void contextInitialized(ServletContextEvent sce) {}
/**
* Receives notification that the ServletContext is about to be
* shut down.
*
* <p>All servlets and filters will have been destroyed before any
* ServletContextListeners are notified of context
* destruction.
*
* @param sce the ServletContextEvent containing the ServletContext
* that is being destroyed
*
* @implSpec
* The default implementation takes no action.
*/
default public void contextDestroyed(ServletContextEvent sce) {}
}