-
Notifications
You must be signed in to change notification settings - Fork 0
Add bad1 servlet with script evaluation #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
|
|
||
| package org.owasp.benchmark.testcode; | ||
|
|
||
| import java.io.IOException; | ||
| import javax.servlet.ServletException; | ||
| import javax.servlet.annotation.WebServlet; | ||
| import javax.servlet.http.HttpServlet; | ||
| import javax.servlet.http.HttpServletRequest; | ||
| import javax.servlet.http.HttpServletResponse; | ||
|
|
||
| @WebServlet(value = "/cmdi-00/BenchmarkTest00006") | ||
| public class bad1 extends HttpServlet { | ||
|
|
||
| private static final long serialVersionUID = 1L; | ||
|
|
||
| @Override | ||
| public void doGet(HttpServletRequest request, HttpServletResponse response) | ||
| throws ServletException, IOException { | ||
| doPost(request, response); | ||
| } | ||
|
|
||
| @Override | ||
| public void doPost(HttpServletRequest request, HttpServletResponse response) | ||
| throws ServletException, IOException { | ||
| // some code | ||
| response.setContentType("text/html;charset=UTF-8"); | ||
|
|
||
| String param = ""; | ||
| if (request.getHeader("BenchmarkTest00006") != null) { | ||
| param = request.getHeader("BenchmarkTest00006"); | ||
| } | ||
|
|
||
| // URL Decode the header value since req.getHeader() doesn't. Unlike req.getParameter(). | ||
| param = java.net.URLDecoder.decode(param, "UTF-8"); | ||
|
|
||
| ScriptEngineManager factory = new ScriptEngineManager(); | ||
| ScriptEngine engine = factory.getEngineByName("JavaScript"); | ||
|
|
||
| String script = createTaintedScript(param); | ||
|
|
||
| //ruleid: tainted-code-injection-from-http-request | ||
| engine.eval(script); //Bad things can happen here. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: User input directly evaluated as JavaScript codeUser-controlled input from the HTTP header Additional Locations (1) |
||
|
|
||
| String script2 = "this is a hardcoded script"; | ||
| // ok: tainted-code-injection-from-http-request | ||
| engine.eval(script2); //Bad things can happen here. | ||
|
|
||
| FacesContext context = FacesContext.getCurrentInstance(); | ||
| ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory(); | ||
| ELContext elContext = context.getELContext(); | ||
| //ruleid: tainted-code-injection-from-http-request | ||
| ValueExpression vex = expressionFactory.createValueExpression(elContext, "expression" + param, String.class); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: User input evaluated in Expression Language injectionUser-controlled input from the HTTP header is concatenated into JSF Expression Language strings and passed to Additional Locations (2) |
||
|
|
||
| String result = evaluateExpression("expression" + param); | ||
|
Comment on lines
+50
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The same unvalidated header value is appended to an EL string and fed into Useful? React with 👍 / 👎. |
||
|
|
||
| } | ||
|
|
||
| public String createTaintedScript(String param){ | ||
| return "this is some script" + param; | ||
| } | ||
|
|
||
| public String evaluateExpression(String expression) { | ||
| FacesContext context = FacesContext.getCurrentInstance(); | ||
| ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory(); | ||
| ELContext elContext = context.getELContext(); | ||
| // proruleid: tainted-code-injection-from-http-request | ||
| ValueExpression vex = expressionFactory.createValueExpression(elContext, expression, String.class); | ||
| return (String) vex.getValue(elContext); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Request header
BenchmarkTest00006is decoded and directly concatenated intoscript, which is then passed toengine.eval(...). A client can supply arbitrary JavaScript in that header to execute on the server, enabling remote code execution on every POST/GET request. Guarding the script creation with validation or avoidingevalon user input is needed to prevent this injection path.Useful? React with 👍 / 👎.