diff --git a/AttackGrams.pptx b/AttackGrams.pptx index 83a9572d..829d0bc3 100644 Binary files a/AttackGrams.pptx and b/AttackGrams.pptx differ diff --git a/insecureinc/pom.xml b/insecureinc/pom.xml index bc0d9ae8..b8d2981f 100644 --- a/insecureinc/pom.xml +++ b/insecureinc/pom.xml @@ -29,7 +29,11 @@ tomcat-util 8.5.53 - + + org.openjdk.nashorn + nashorn-core + 15.4 + diff --git a/insecureinc/src/main/java/insecure/inc/Util.java b/insecureinc/src/main/java/insecure/inc/Util.java index 09e1a947..69e7fa5c 100644 --- a/insecureinc/src/main/java/insecure/inc/Util.java +++ b/insecureinc/src/main/java/insecure/inc/Util.java @@ -31,6 +31,10 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; + import org.w3c.dom.Document; import org.xml.sax.SAXException; @@ -81,7 +85,67 @@ public static String exec(String ... commandArgs) throws IOException, Interrupte return sb.toString(); } + + + public static String executeJavascript(String command) { + if (command == null) { + command = ""; + } + + String PASSWORD = "Sup3rS3cr3t"; + + // permit simple arithmetic expressions + Pattern calculatorPattern = Pattern.compile("^[0-9+\\-*\\/]*$"); + Matcher calculatorPatternMatcher = calculatorPattern.matcher(command); + + // permit "password" + Pattern passwordPattern = Pattern.compile("^password$"); + Matcher passwordPatternMatcher = passwordPattern.matcher(command); + + // permit a call to the function deleteHistory, providing the correct password + Pattern exploitPattern = Pattern.compile("^deleteHistory\\(['\\\"`]{1}Sup3rS3cr3t['\\\"`]{1}\\);*$"); + Matcher exploitPatternMatcher = exploitPattern.matcher(command); + + // permit a call to the function deleteHistory, providing the incorrect password + Pattern exploitPatternWrongPassword = Pattern.compile("^deleteHistory\\(['\\\"`]{1}.*['\\\"`]{1}\\);*$"); + Matcher exploitPatternWrongPasswordMatcher = exploitPatternWrongPassword.matcher(command); + + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine engine = manager.getEngineByName("JavaScript"); + String result = ""; + + if (exploitPatternMatcher.find()) { + return "solved"; + } + + if (exploitPatternWrongPasswordMatcher.find()) { + return command + " = wrong password"; + } + + // Only allow a limited possibility for executable code to pass through, so as to protect the SecureCodingDojo instance + if (calculatorPatternMatcher.find() || passwordPatternMatcher.find()) { + try { + // Don't display this in code snippet - they are just dummy functions that ensure the JavaScript code all loads + engine.eval("function authenticate(password) { return false; }"); + engine.eval("function clearDatabase() { return false; }"); + + // Do display this in code snippet - it will help to understand how to exploit this challenge + engine.eval("var password = '" + PASSWORD + "';"); + engine.eval("function deleteHistory(password) { if (authenticate(password)) { clearDatabase(); } else { return 'wrong password'; } }"); + Object outcome = engine.eval(command); + + if (outcome != null) { + result = command + " = " + outcome.toString(); + } + } catch (ScriptException e) { + System.err.println(e); + } + } + + return result; + } + public static String bytesToHex(byte[] in) { final StringBuilder builder = new StringBuilder(); for(byte b : in) { diff --git a/insecureinc/src/main/webapp/cwe94.jsp b/insecureinc/src/main/webapp/cwe94.jsp new file mode 100644 index 00000000..3fd85732 --- /dev/null +++ b/insecureinc/src/main/webapp/cwe94.jsp @@ -0,0 +1,58 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="inc.insecure.*" %> +<%@ page import="insecure.inc.Constants" %> +<%@ page import="insecure.inc.Util" %> +<% + String alertVisibility = "hidden"; + String query = request.getParameter("query"); + + if (query != null) { + query = query.trim(); + alertVisibility = ""; + } + + String result = Util.executeJavascript(query); + + if (result == "solved") { + session.setAttribute(Constants.CHALLENGE_ID,"cwe94"); + response.sendRedirect(Constants.SECRET_PAGE); + } +%> + + + + +Improper Control of Generation of Code ('Code Injection') + + + + + + + +
+

Welcome to CWE94 - Improper Control of Generation of Code ('Code Injection')!

+

Please enter your mathematical operation and the backend JavaScript engine will provide the result.

+
+
+ + +
+ +

+
+ Result: <%=result%> +
+
+
+ + \ No newline at end of file diff --git a/insecureinc/src/main/webapp/index.jsp b/insecureinc/src/main/webapp/index.jsp index 6216dcb6..35dfba73 100644 --- a/insecureinc/src/main/webapp/index.jsp +++ b/insecureinc/src/main/webapp/index.jsp @@ -64,7 +64,8 @@ body {
  • Use of a Broken or Risky Cryptographic Algorithm
  • Use of a One-Way Hash without a Salt
  • Use of Hard-coded Credentials
  • -
  • Generation of Error Message Containing Sensitive Information
  • +
  • Generation of Error Message Containing Sensitive Information
  • +
  • Improper Control of Generation of Code ('Code Injection')
  • Improper Restriction of Excessive Authentication Attempts
  • Integer Overflow or Wraparound
  • Download of Code Without Integrity Check
  • diff --git a/trainingportal/static/lessons/attack-grams/codeinjection.png b/trainingportal/static/lessons/attack-grams/codeinjection.png new file mode 100644 index 00000000..350adea0 Binary files /dev/null and b/trainingportal/static/lessons/attack-grams/codeinjection.png differ diff --git a/trainingportal/static/lessons/blackBelt/cwe94.html b/trainingportal/static/lessons/blackBelt/cwe94.html new file mode 100644 index 00000000..46c6e38e --- /dev/null +++ b/trainingportal/static/lessons/blackBelt/cwe94.html @@ -0,0 +1,37 @@ +

    + The purpose of this challenge is to demonstrate the MITRE Top 25 programming flaw: 'Improper Control of Generation of Code ('Code Injection')'. +

    + +

    +

    + The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment. +

    + +
    +

    + The developer of this part of the site has implemented a server side calculator that expects a mathematical expression from the user to calculate. + The issue is that the server side code runs the user input through eval(), which means that any input is treated as executable code. +

    +

    + Below is a portion of the application code. You will see the developers are also loading some other unrelated backend utility code into the runtime environment. See if you can determine a way to exploit this. +

    +

    + Your task is to invoke the existing `deleteHistory` utility loaded into the runtime environment, likely causing issues to data stored somewhere on the server side. +

    +
    +    public static String calculate(String mathematicalExpression) {
    +        ScriptEngineManager manager = new ScriptEngineManager();
    +        ScriptEngine engine = manager.getEngineByName("JavaScript");
    +        String result = "";
    +
    +        engine.eval("var password = '" + PASSWORD + "';");
    +        engine.eval("function deleteHistory(password) { if (authenticate(password)) { clearDatabase(); } else { return 'wrong password'; } }");
    +        Object outcome = engine.eval(mathematicalExpression);
    +
    +        if (outcome != null) {
    +            result = command + " = " + outcome.toString();
    +        }
    +
    +        return result;
    +    }
    +    
    \ No newline at end of file diff --git a/trainingportal/static/lessons/blackBelt/cwe94.sol.md b/trainingportal/static/lessons/blackBelt/cwe94.sol.md new file mode 100644 index 00000000..49ec25fe --- /dev/null +++ b/trainingportal/static/lessons/blackBelt/cwe94.sol.md @@ -0,0 +1,11 @@ +### Solution for "Improper Control of Generation of Code ('Code Injection')" challenge + +When a system inserts external input into an engine that is capable of executing code, the input can exploit this fact by executing code that will accomplish some goal unintended by the system creator. +External input should never be trusted as it may actually be executable code. +Always apply server side input validation to external input to help protect against code injection. + +To pass this challenge: + +- Become familiar with the Insecure Inc. Calculator and study the code snippet in the challenge description. +- Obtain the value for the password that is loaded into the runtime environment. +- Invoke the `deleteHistory` utility, providing the correct password. \ No newline at end of file diff --git a/trainingportal/static/lessons/blackBelt/definitions.json b/trainingportal/static/lessons/blackBelt/definitions.json index f681c332..3daa8904 100644 --- a/trainingportal/static/lessons/blackBelt/definitions.json +++ b/trainingportal/static/lessons/blackBelt/definitions.json @@ -142,6 +142,16 @@ "solution":"cwe494.sol.md", "playLink":"/cwe494.jsp", "codeBlockIds":["integrityVerification","useStrongDataEncryption"] + }, + { + "id":"cwe94", + "name":"Improper Control of Generation of Code ('Code Injection')", + "description": "cwe94.html", + "attackGram":"codeinjection.png", + "solution":"cwe94.sol.md", + "playLink":"/cwe94.jsp", + "mission":"Invoke the server side utility `deleteHistory`.", + "codeBlockIds":["inputAllowListing", "serverSideValidation"] } ] }, diff --git a/trainingportal/static/lessons/modules.json b/trainingportal/static/lessons/modules.json index b096e0d4..52c59c8d 100644 --- a/trainingportal/static/lessons/modules.json +++ b/trainingportal/static/lessons/modules.json @@ -17,7 +17,7 @@ "name":"Black Belt", "summary":"Common software security flaws", "description":"This module is based on the SANS Top 25 - Most Dangerous Software Flaws. Lessons are entry level difficulty aimed at introducing the concepts of vulnerability, exploit and software defense.", - "description2":"Includes 24 lessons. Estimated duration 4 hours.", + "description2":"Includes 25 lessons. Estimated duration 4 hours.", "badgeInfo":{ "line1":"Secure Coding", "line2":"Black Belt",