From fb24e30808ba053d826a4586c4a218e61e1b7dbc Mon Sep 17 00:00:00 2001 From: "Devashish [C] Rane" Date: Mon, 14 Jul 2025 15:35:34 +0530 Subject: [PATCH] Add PR_5_java for java --- PR_5_java/java/filtered_java/01_Utils.java | 445 +++++++++++++++++ .../java/filtered_java/02_DatabaseHelper.java | 391 +++++++++++++++ .../03_tainted_xpath_from_http_request.java | 258 ++++++++++ .../04_tainted_ldapi_from_http_request.java | 377 ++++++++++++++ .../filtered_java/05_VulnerabilityType.java | 55 +++ .../java/filtered_java/06_LDAPManager.java | 222 +++++++++ .../07_tainted_cmd_from_http_request.java | 333 +++++++++++++ .../08_desede_is_deprecated.java | 153 ++++++ .../09_tainted_sql_from_http_request.java | 299 +++++++++++ .../filtered_java/10_tainted_html_string.java | 236 +++++++++ .../11_dangerous_groovy_shell.java | 81 +++ .../12_no_direct_response_writer.java | 311 ++++++++++++ .../java/filtered_java/13_spring_sqli.java | 465 ++++++++++++++++++ .../14_tainted_system_command.java | 245 +++++++++ .../java/filtered_java/15_weak_random.java | 220 +++++++++ .../filtered_java/16_tainted_url_host.java | 104 ++++ .../java/filtered_java/17_session_sqli.java | 77 +++ .../18_UnrestrictedFileUpload.java | 382 ++++++++++++++ .../19_httpservlet_path_traversal.java | 122 +++++ .../filtered_java/20_crlf_injection_logs.java | 102 ++++ .../21_overly_permissive_file_permission.java | 49 ++ .../java/filtered_java/22_ldap_injection.java | 149 ++++++ .../filtered_java/23_permissive_cors.java | 150 ++++++ .../java/filtered_java/24_ognl_injection.java | 56 +++ .../java/filtered_java/25_use_of_md5.java | 52 ++ .../26_LambdaFunctionHandler.java | 85 ++++ .../filtered_java/27_tainted_file_path.java | 54 ++ PR_5_java/java/filtered_java/28_Driver.java | 39 ++ PR_5_java/java/filtered_java/29_Driver.java | 19 + .../java/filtered_java/30_LDAPServer.java | 324 ++++++++++++ .../filtered_java/31_PropertiesManager.java | 119 +++++ .../java/filtered_java/32_el_injection.java | 66 +++ .../33_script_engine_injection.java | 39 ++ .../34_jdbc_sql_formatted_string.java | 85 ++++ ..._CommandInjectionFormattedRuntimeCall.java | 51 ++ .../filtered_java/36_bad_hexa_conversion.java | 43 ++ .../java/filtered_java/37_use_of_sha1.java | 56 +++ .../38_insecure_hostname_verifier.java | 37 ++ PR_5_java/java/filtered_java/39_jpa_sqli.java | 103 ++++ PR_5_java/java/filtered_java/40_jdo_sqli.java | 153 ++++++ .../41_LambdaFunctionHandlerEx.java | 59 +++ .../42_unrestricted_request_mapping.java | 53 ++ .../43_HttpRequestDebugFilter.java | 72 +++ .../java/filtered_java/44_Constants.java | 16 + .../java/filtered_java/45_SourceUtils.java | 90 ++++ .../filtered_java/46_do_privileged_use.java | 57 +++ .../47_ldap_entry_poisoning.java | 52 ++ .../48_CommandInjectionProcessBuilder.java | 81 +++ .../49_tainted_session_from_http_request.java | 173 +++++++ .../50_formatted_sql_string.java | 187 +++++++ .../filtered_java/VULNERABILITY_SUMMARY.md | 56 +++ 51 files changed, 7503 insertions(+) create mode 100644 PR_5_java/java/filtered_java/01_Utils.java create mode 100644 PR_5_java/java/filtered_java/02_DatabaseHelper.java create mode 100644 PR_5_java/java/filtered_java/03_tainted_xpath_from_http_request.java create mode 100644 PR_5_java/java/filtered_java/04_tainted_ldapi_from_http_request.java create mode 100644 PR_5_java/java/filtered_java/05_VulnerabilityType.java create mode 100644 PR_5_java/java/filtered_java/06_LDAPManager.java create mode 100644 PR_5_java/java/filtered_java/07_tainted_cmd_from_http_request.java create mode 100644 PR_5_java/java/filtered_java/08_desede_is_deprecated.java create mode 100644 PR_5_java/java/filtered_java/09_tainted_sql_from_http_request.java create mode 100644 PR_5_java/java/filtered_java/10_tainted_html_string.java create mode 100644 PR_5_java/java/filtered_java/11_dangerous_groovy_shell.java create mode 100644 PR_5_java/java/filtered_java/12_no_direct_response_writer.java create mode 100644 PR_5_java/java/filtered_java/13_spring_sqli.java create mode 100644 PR_5_java/java/filtered_java/14_tainted_system_command.java create mode 100644 PR_5_java/java/filtered_java/15_weak_random.java create mode 100644 PR_5_java/java/filtered_java/16_tainted_url_host.java create mode 100644 PR_5_java/java/filtered_java/17_session_sqli.java create mode 100644 PR_5_java/java/filtered_java/18_UnrestrictedFileUpload.java create mode 100644 PR_5_java/java/filtered_java/19_httpservlet_path_traversal.java create mode 100644 PR_5_java/java/filtered_java/20_crlf_injection_logs.java create mode 100644 PR_5_java/java/filtered_java/21_overly_permissive_file_permission.java create mode 100644 PR_5_java/java/filtered_java/22_ldap_injection.java create mode 100644 PR_5_java/java/filtered_java/23_permissive_cors.java create mode 100644 PR_5_java/java/filtered_java/24_ognl_injection.java create mode 100644 PR_5_java/java/filtered_java/25_use_of_md5.java create mode 100644 PR_5_java/java/filtered_java/26_LambdaFunctionHandler.java create mode 100644 PR_5_java/java/filtered_java/27_tainted_file_path.java create mode 100644 PR_5_java/java/filtered_java/28_Driver.java create mode 100644 PR_5_java/java/filtered_java/29_Driver.java create mode 100644 PR_5_java/java/filtered_java/30_LDAPServer.java create mode 100644 PR_5_java/java/filtered_java/31_PropertiesManager.java create mode 100644 PR_5_java/java/filtered_java/32_el_injection.java create mode 100644 PR_5_java/java/filtered_java/33_script_engine_injection.java create mode 100644 PR_5_java/java/filtered_java/34_jdbc_sql_formatted_string.java create mode 100644 PR_5_java/java/filtered_java/35_CommandInjectionFormattedRuntimeCall.java create mode 100644 PR_5_java/java/filtered_java/36_bad_hexa_conversion.java create mode 100644 PR_5_java/java/filtered_java/37_use_of_sha1.java create mode 100644 PR_5_java/java/filtered_java/38_insecure_hostname_verifier.java create mode 100644 PR_5_java/java/filtered_java/39_jpa_sqli.java create mode 100644 PR_5_java/java/filtered_java/40_jdo_sqli.java create mode 100644 PR_5_java/java/filtered_java/41_LambdaFunctionHandlerEx.java create mode 100644 PR_5_java/java/filtered_java/42_unrestricted_request_mapping.java create mode 100644 PR_5_java/java/filtered_java/43_HttpRequestDebugFilter.java create mode 100644 PR_5_java/java/filtered_java/44_Constants.java create mode 100644 PR_5_java/java/filtered_java/45_SourceUtils.java create mode 100644 PR_5_java/java/filtered_java/46_do_privileged_use.java create mode 100644 PR_5_java/java/filtered_java/47_ldap_entry_poisoning.java create mode 100644 PR_5_java/java/filtered_java/48_CommandInjectionProcessBuilder.java create mode 100644 PR_5_java/java/filtered_java/49_tainted_session_from_http_request.java create mode 100644 PR_5_java/java/filtered_java/50_formatted_sql_string.java create mode 100644 PR_5_java/java/filtered_java/VULNERABILITY_SUMMARY.md diff --git a/PR_5_java/java/filtered_java/01_Utils.java b/PR_5_java/java/filtered_java/01_Utils.java new file mode 100644 index 0000000..78b9f82 --- /dev/null +++ b/PR_5_java/java/filtered_java/01_Utils.java @@ -0,0 +1,445 @@ +/** + * OWASP Benchmark Project + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Nick Sanidas + * @created 2015 + */ +package org.owasp.benchmark.helpers; + +import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.TrustSelfSignedStrategy; +import org.apache.hc.core5.ssl.SSLContexts; +import org.owasp.benchmark.service.pojo.XMLMessage; +import org.owasp.esapi.ESAPI; + +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import javax.net.ssl.SSLContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.*; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.PosixFilePermission; +import java.security.CodeSource; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.text.MessageFormat; +import java.util.*; + +public class Utils { + + // Properties used by the generated test suite + + public static final String USERDIR = System.getProperty("user.dir") + File.separator; + + // A 'test' directory that target test files are created in so test cases can use them + public static final String TESTFILES_DIR = USERDIR + "testfiles" + File.separator; + + // This constant is used by one of the sources for Benchmark 1.2, but not in 1.3+. + // It is used to filter out common headers. Whatever is left is considered the custom header + // name for header names test cases + public static final Set commonHeaders = + new HashSet<>( + Arrays.asList( + "accept", + "accept-encoding", + "accept-language", + "cache-control", + "connection", + "content-length", + "content-type", + "cookie", + "host", + "origin", + "pragma", + "referer", + "sec-ch-ua", + "sec-ch-ua-mobile", + "sec-ch-ua-platform", + "sec-fetch-dest", + "sec-fetch-mode", + "sec-fetch-site", + "user-agent", + "x-requested-with")); + + private static final DocumentBuilderFactory safeDocBuilderFactory = + DocumentBuilderFactory.newInstance(); + public static String testfileDir; + + static { + try { + // Make DBF safe from XXE by disabling doctype declarations (per OWASP XXE cheat sheet) + safeDocBuilderFactory.setFeature( + "http://apache.org/xml/features/disallow-doctype-decl", true); + } catch (ParserConfigurationException e) { + System.out.println( + "ERROR: couldn't set http://apache.org/xml/features/disallow-doctype-decl"); + e.printStackTrace(); + } + + File tempDir = new File(TESTFILES_DIR); + if (!tempDir.exists()) { + tempDir.mkdir(); + File testFile = new File(TESTFILES_DIR + "FileName"); + try { + PrintWriter out = new PrintWriter(testFile); + out.write("Test is a test file.\n"); + out.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + File testFile2 = new File(TESTFILES_DIR + "SafeText"); + try { + PrintWriter out = new PrintWriter(testFile2); + out.write("Test is a 'safe' test file.\n"); + out.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + File secreTestFile = new File(TESTFILES_DIR + "SecretFile"); + try { + PrintWriter out = new PrintWriter(secreTestFile); + out.write("Test is a 'secret' file that no one should find.\n"); + out.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + + // The target script is exploded out of the WAR file. When this occurs, the file + // loses its execute permissions. So this hack adds the required execute permissions back. + if (!System.getProperty("os.name").contains("Windows")) { + File script = getFileFromClasspath("insecureCmd.sh", Utils.class.getClassLoader()); + Set perms = new HashSet(); + perms.add(PosixFilePermission.OWNER_READ); + perms.add(PosixFilePermission.OWNER_WRITE); + perms.add(PosixFilePermission.OWNER_EXECUTE); + perms.add(PosixFilePermission.GROUP_READ); + perms.add(PosixFilePermission.GROUP_EXECUTE); + perms.add(PosixFilePermission.OTHERS_READ); + perms.add(PosixFilePermission.OTHERS_EXECUTE); + + try { + Files.setPosixFilePermissions(script.toPath(), perms); + } catch (IOException e) { + System.out.println( + "Problem while changing executable permissions: " + e.getMessage()); + } + } + } + + public static String getCookie(HttpServletRequest request, String paramName) { + Cookie[] values = request.getCookies(); + String param = "none"; + if (paramName != null) { + for (int i = 0; i < values.length; i++) { + if (values[i].getName().equals(paramName)) { + param = values[i].getValue(); + break; // break out of for loop when param found + } + } + } + return param; + } + + public static String getOSCommandString(String append) { + + String command = null; + String osName = System.getProperty("os.name"); + if (osName.indexOf("Windows") != -1) { + command = "cmd.exe /c " + append + " "; + } else { + command = append + " "; + } + + return command; + } + + public static String getInsecureOSCommandString(ClassLoader classLoader) { + String command = null; + String osName = System.getProperty("os.name"); + if (osName.indexOf("Windows") != -1) { + command = Utils.getFileFromClasspath("insecureCmd.bat", classLoader).getAbsolutePath(); + } else { + command = Utils.getFileFromClasspath("insecureCmd.sh", classLoader).getAbsolutePath(); + } + return command; + } + + public static List getOSCommandArray(String append) { + + ArrayList cmds = new ArrayList(); + + String osName = System.getProperty("os.name"); + if (osName.indexOf("Windows") != -1) { + cmds.add("cmd.exe"); + cmds.add("/c"); + if (append != null) { + cmds.add(append); + } + } else { + cmds.add("sh"); + cmds.add("-c"); + if (append != null) { + cmds.add(append); + } + } + + return cmds; + } + + // A method used by the Benchmark JAVA test cases to format OS Command Output + public static void printOSCommandResults(Process proc, HttpServletResponse response) + throws IOException { + PrintWriter out = response.getWriter(); + out.write( + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "

\n"); + + BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); + BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + + try { + // read the output from the command + // System.out.println("Here is the standard output of the + // command:\n"); + out.write("Here is the standard output of the command:
"); + String s = null; + while ((s = stdInput.readLine()) != null) { + out.write(ESAPI.encoder().encodeForHTML(s)); + out.write("
"); + } + + // read any errors from the attempted command + // System.out.println("Here is the standard error of the command (if + // any):\n"); + out.write("
Here is the std err of the command (if any):
"); + while ((s = stdError.readLine()) != null) { + out.write(ESAPI.encoder().encodeForHTML(s)); + out.write("
"); + } + } catch (IOException e) { + System.out.println("An error occurred while reading OSCommandResults"); + e.printStackTrace(); + } + } + + // A method used by the Benchmark JAVA test cases to format OS Command Output + // This version is only used by the Web Services test cases. + public static void printOSCommandResults(Process proc, List resp) { + + BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); + BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + + try { + // read the output from the command + resp.add(new XMLMessage("Here is the standard output of the command:")); + String s = null; + StringBuffer out = new StringBuffer(); + StringBuffer outError = new StringBuffer(); + + while ((s = stdInput.readLine()) != null) { + out.append(s).append("\n"); + } + resp.add(new XMLMessage(out.toString())); + // read any errors from the attempted command + resp.add(new XMLMessage("Here is the std err of the command (if any):")); + while ((s = stdError.readLine()) != null) { + outError.append(s).append("\n"); + } + + resp.add(new XMLMessage(outError.toString())); + } catch (IOException e) { + System.out.println("An error occurred while reading OSCommandResults"); + e.printStackTrace(); + } + } + + public static File getFileFromClasspath(String fileName, ClassLoader classLoader) { + URL url = classLoader.getResource(fileName); + if (url != null) { + try { + return new File(url.toURI().getPath()); + } catch (URISyntaxException e) { + System.out.println( + "The file '" + fileName + "' cannot be loaded from the classpath."); + e.printStackTrace(); + } + } else System.out.println("The file '" + fileName + "' cannot be found on the classpath."); + return null; + } + + public static List getLinesFromFile(File file) { + if (!file.exists()) { + try { + System.out.println("Can't find file to get lines from: " + file.getCanonicalFile()); + } catch (IOException e) { + System.out.println("Can't find file to get lines from."); + e.printStackTrace(); + } + return null; + } + + List sourceLines = new ArrayList(); + + try (FileReader fr = new FileReader(file); + BufferedReader br = new BufferedReader(fr); ) { + String line; + while ((line = br.readLine()) != null) { + sourceLines.add(line); + } + } catch (Exception e) { + try { + System.out.println("Problem reading contents of file: " + file.getCanonicalFile()); + } catch (IOException e2) { + System.out.println("Problem reading file to get lines from."); + e2.printStackTrace(); + } + e.printStackTrace(); + } + + return sourceLines; + } + + public static List getLinesFromFile(String filename) { + return getLinesFromFile(new File(filename)); + } + + /** + * Encodes the supplied parameter using ESAPI's encodeForHTML(). Only supports Strings and + * InputStreams. + * + * @param param - The String or InputStream to encode. + * @return - HTML Entity encoded version of input, or "objectTypeUnknown" if not a supported + * type. + */ + public static String encodeForHTML(Object param) { + + String value = "objectTypeUnknown"; + if (param instanceof String) { + value = (String) param; + } else if (param instanceof java.io.InputStream) { + byte[] buff = new byte[1000]; + int length = 0; + try { + java.io.InputStream stream = (java.io.InputStream) param; + stream.reset(); + length = stream.read(buff); + } catch (IOException e) { + buff[0] = (byte) '?'; + length = 1; + } + ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write(buff, 0, length); + value = b.toString(); + } + return ESAPI.encoder().encodeForHTML(value); + } + + public static boolean writeLineToFile(Path pathToFileDir, String completeName, String line) { + boolean result = true; + PrintStream os = null; + try { + Files.createDirectories(pathToFileDir); + File f = new File(completeName); + if (!f.exists()) { + f.createNewFile(); + } + FileOutputStream fos = new FileOutputStream(f, true); + os = new PrintStream(fos); + os.println(line); + } catch (IOException e1) { + result = false; + e1.printStackTrace(); + } finally { + os.close(); + } + + return result; + } + + /* + * A utility method used by the generated Java Cipher test cases. + */ + private static Cipher cipher = null; + + public static Cipher getCipher() { + if (cipher == null) { + try { + cipher = + Cipher.getInstance( + "RSA/ECB/OAEPWithSHA-512AndMGF1Padding", "SunJCE"); + // Prepare the cipher to encrypt + java.security.KeyPairGenerator keyGen = + java.security.KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(4096); + java.security.PublicKey publicKey = keyGen.genKeyPair().getPublic(); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + } catch (NoSuchAlgorithmException + | NoSuchProviderException + | NoSuchPaddingException + | InvalidKeyException e) { + e.printStackTrace(); + } + } + return cipher; + } + + public static SSLConnectionSocketFactory getSSLFactory() throws Exception { + SSLContext sslcontext = + SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(); + // Allow TLSv1 protocol only + SSLConnectionSocketFactory sslsf = + new SSLConnectionSocketFactory( + sslcontext, new String[] {"TLSv1"}, null, NoopHostnameVerifier.INSTANCE); + return sslsf; + } + + /** + * This method returns information about which library the supplied class came from. This is + * useful when determining what class a Factory instantiated, for example. Mainly used for XXE + * verification/debugging. + * + * @param The name of the class being passed in. + * @param The class to print information about. + * @return A string containing the Component Name, the name of the class, possibly the + * implementation vendor, spec version, implementation version, and the library it came from + * (or Java Runtime it came from). + */ + public static String getClassImplementationInfo(String componentName, Class componentClass) { + CodeSource source = componentClass.getProtectionDomain().getCodeSource(); + Package p = componentClass.getPackage(); + return MessageFormat.format( + "{0} implementation: {1} ({2}) version {3} ({4}) loaded from: {5}", + componentName, + componentClass.getName(), + p.getImplementationVendor(), + p.getSpecificationVersion(), + p.getImplementationVersion(), + source == null ? "Java_Runtime" : source.getLocation()); + } +} \ No newline at end of file diff --git a/PR_5_java/java/filtered_java/02_DatabaseHelper.java b/PR_5_java/java/filtered_java/02_DatabaseHelper.java new file mode 100644 index 0000000..5bc6a5f --- /dev/null +++ b/PR_5_java/java/filtered_java/02_DatabaseHelper.java @@ -0,0 +1,391 @@ +/** +* OWASP Benchmark Project +* +* This file is part of the Open Web Application Security Project (OWASP) +* Benchmark Project For details, please see +* https://www.owasp.org/index.php/Benchmark. +* +* The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms +* of the GNU General Public License as published by the Free Software Foundation, version 2. +* +* The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without +* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details +* +* @author Juan Gama Aspect Security +* @created 2015 +*/ + +package org.owasp.benchmark.helpers; + +import org.owasp.benchmark.service.pojo.StringMessage; +import org.owasp.esapi.ESAPI; + +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.http.HttpServletResponse; +import javax.sql.DataSource; +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.*; +import java.util.List; + +public class DatabaseHelper { + private static Statement stmt; + private static Connection conn; + public static org.springframework.jdbc.core.JdbcTemplate JDBCtemplate; + public static final boolean hideSQLErrors = false; // If we want SQL Exceptions to be suppressed from being displayed to the user of the web app. + + static { + + initDataBase(); + System.out.println("Spring context init() "); + @SuppressWarnings("resource") + org.springframework.context.ApplicationContext ac = + new org.springframework.context.support.ClassPathXmlApplicationContext("/context.xml", DatabaseHelper.class); + DataSource data = (DataSource) ac.getBean("dataSource"); + JDBCtemplate = new org.springframework.jdbc.core.JdbcTemplate(data); + System.out.println("Spring context loaded!"); + } + + public static void initDataBase(){ + try { + executeSQLCommand("DROP PROCEDURE IF EXISTS verifyUserPassword"); + executeSQLCommand("DROP PROCEDURE IF EXISTS verifyEmployeeSalary"); + executeSQLCommand("DROP TABLE IF EXISTS USERS"); + executeSQLCommand("DROP TABLE IF EXISTS EMPLOYEE"); + executeSQLCommand("DROP TABLE IF EXISTS CERTIFICATE"); + executeSQLCommand("DROP TABLE IF EXISTS SCORE"); + + executeSQLCommand("CREATE TABLE USERS (userid int NOT NULL GENERATED BY DEFAULT AS IDENTITY, username varchar(50), password varchar(50),PRIMARY KEY (userid));"); + executeSQLCommand("CREATE TABLE SCORE (userid int NOT NULL GENERATED BY DEFAULT AS IDENTITY, nick varchar(50), score INTEGER,PRIMARY KEY (userid));"); + executeSQLCommand("CREATE PROCEDURE verifyUserPassword(IN username_ varchar(50), IN password_ varchar(50))" + + " READS SQL DATA" + + " DYNAMIC RESULT SETS 1" + + " BEGIN ATOMIC" + + " DECLARE resultSet SCROLL CURSOR WITH HOLD WITH RETURN FOR SELECT * FROM USERS WHERE USERNAME = username_ AND PASSWORD = password_;" + + " OPEN resultSet;" + +"END;"); + + executeSQLCommand("create table EMPLOYEE (" + + " id INT NOT NULL GENERATED BY DEFAULT AS IDENTITY," + + " first_name VARCHAR(20) default NULL," + + " last_name VARCHAR(20) default NULL," + + " salary INT default NULL," + " PRIMARY KEY (id)" + + " );"); + + executeSQLCommand("create table CERTIFICATE (" + + " id INT NOT NULL GENERATED BY DEFAULT AS IDENTITY," + + " certificate_name VARCHAR(30) default NULL," + + " employee_id INT default NULL," + " PRIMARY KEY (id)" + + ");"); + + executeSQLCommand("CREATE PROCEDURE verifyEmployeeSalary(IN user_ varchar(50))" + + " READS SQL DATA" + + " DYNAMIC RESULT SETS 1" + + " BEGIN ATOMIC" + + " DECLARE resultSet SCROLL CURSOR WITH RETURN FOR SELECT * FROM EMPLOYEE WHERE FIRST_NAME = user_;" + + " OPEN resultSet;" + +"END;"); + conn.commit(); + initData(); + + System.out.println("DataBase tables/procedures created."); + } catch (Exception e1) { + System.out.println("Problem with database table/procedure creations: " + e1.getMessage()); + } + } + + + public static Statement getSqlStatement() { + if (conn == null) { + getSqlConnection(); + } + + if (stmt == null) { + try { + stmt = conn.createStatement(); + } catch (SQLException e) { + System.out.println("Problem with database init."); + } + } + + return stmt; + } + + public static void reset(){ + initData(); + } + + private static void initData() { + try { + executeSQLCommand("INSERT INTO USERS (username, password) VALUES('User01', 'P455w0rd')"); + executeSQLCommand("INSERT INTO USERS (username, password) VALUES('User02', 'B3nchM3rk')"); + executeSQLCommand("INSERT INTO USERS (username, password) VALUES('User03', 'a$c11')"); + executeSQLCommand("INSERT INTO USERS (username, password) VALUES('foo', 'bar')"); + + executeSQLCommand("INSERT INTO SCORE (nick, score) VALUES('User03', 155)"); + executeSQLCommand("INSERT INTO SCORE (nick, score) VALUES('foo', 40)"); + + executeSQLCommand("INSERT INTO EMPLOYEE (first_name, last_name, salary) VALUES('foo', 'bar', 100)"); + conn.commit(); + } catch (Exception e1) { + System.out.println("Problem with database init/reset: " + e1.getMessage()); + } + } + + public static Connection getSqlConnection() { + if (conn == null) { + try { + InitialContext ctx = new InitialContext(); + DataSource datasource = (DataSource)ctx.lookup("java:comp/env/jdbc/BenchmarkDB"); + conn = datasource.getConnection(); + conn.setAutoCommit(false); + } catch (SQLException | NamingException e) { + System.out.println("Problem with getSqlConnection."); + e.printStackTrace(); + } + } + return conn; + } + + public static void executeSQLCommand(String sql) throws Exception { + if (stmt == null) { + getSqlStatement(); + } + stmt.executeUpdate(sql); + } + + public static void outputUpdateComplete(String sql, HttpServletResponse response) throws SQLException, IOException { + + PrintWriter out = response.getWriter(); + + out.write("\n\n\n

"); + out.write("Update complete for query: " + ESAPI.encoder().encodeForHTML(sql) + "
\n"); + out.write("

\n\n"); + } + + public static void outputUpdateComplete(String sql, List resp) throws SQLException, IOException { + resp.add(new StringMessage("Message", + "Update complete for query: " + ESAPI.encoder().encodeForHTML(sql) + "
\n" + )); + } + + public static void printResults(Statement statement, String sql, HttpServletResponse response) throws SQLException, IOException { + + PrintWriter out = response.getWriter(); + out.write("\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "

\n"); + + try { + ResultSet rs = statement.getResultSet(); + if (rs == null) { + out.write("Results set is empty for query: " + ESAPI.encoder().encodeForHTML(sql)); + return; + } + ResultSetMetaData rsmd = rs.getMetaData(); + +// printColTypes(rsmd, out); +// out.write("
\n"); + + int numberOfColumns = rsmd.getColumnCount(); + +/* for (int i = 1; i <= numberOfColumns; i++) { + if (i > 1) out.write(", "); + String columnName = rsmd.getColumnName(i); + out.write(columnName); + } // end for + out.write("
\n"); +*/ + out.write("Your results are:
\n"); + //System.out.println("Your results are:
\n"); + while (rs.next()) { + for (int i = 1; i <= numberOfColumns; i++) { + if (i > 1){ out.write(", "); + //System.out.println(", "); + } + String columnValue = rs.getString(i); + out.write(ESAPI.encoder().encodeForHTML(columnValue)); + //System.out.println(columnValue); + } // end for + out.write("
\n"); + //System.out.println("
\n"); + } // end while + + } finally { + out.write("

\n\n"); + } + + } //end printResults + +public static void printResults(Statement statement, String sql, List resp) throws SQLException, IOException { + try { + ResultSet rs = statement.getResultSet(); + if (rs == null) { + resp.add(new StringMessage("Message", + "Results set is empty for query: " + ESAPI.encoder().encodeForHTML(sql) + )); + return; + } + ResultSetMetaData rsmd = rs.getMetaData(); + int numberOfColumns = rsmd.getColumnCount(); + resp.add(new StringMessage("Message", + "Your results are:
\n" + )); + while (rs.next()) { + for (int i = 1; i <= numberOfColumns; i++) { + if (i > 1){ + resp.add(new StringMessage("Message", + ", " + )); + //System.out.println(", "); + } + String columnValue = rs.getString(i); + resp.add(new StringMessage("Message", + ESAPI.encoder().encodeForHTML(columnValue) + )); + } // end for + resp.add(new StringMessage("Message", + "
\n" + )); + } // end while + + } finally { + resp.add(new StringMessage("Message", + "

\n\n" + )); + } + + } //end printResults + + public static void printResults(ResultSet rs, String sql, HttpServletResponse response) throws SQLException, IOException { + + PrintWriter out = response.getWriter(); + out.write("\n\n\n

"); + + try { + if (rs == null) { + out.write("Results set is empty for query: " + ESAPI.encoder().encodeForHTML(sql)); + return; + } + ResultSetMetaData rsmd = rs.getMetaData(); + int numberOfColumns = rsmd.getColumnCount(); + out.write("Your results are:
\n"); +// System.out.println("Your results are:
\n"); + while (rs.next()) { + for (int i = 1; i <= numberOfColumns; i++) { +// if (i > 1){ out.write(", "); System.out.println(", ");} + String columnValue = rs.getString(i); + out.write(ESAPI.encoder().encodeForHTML(columnValue)); +// System.out.println(columnValue); + } // end for + out.write("
\n"); +// System.out.println("
\n"); + } // end while + + } finally { + out.write("

\n\n"); + } + } //end printResults + +public static void printResults(ResultSet rs, String sql, List resp) throws SQLException, IOException { + try { + if (rs == null) { + resp.add(new StringMessage("Message", + "Results set is empty for query: " + ESAPI.encoder().encodeForHTML(sql) + )); + return; + } + ResultSetMetaData rsmd = rs.getMetaData(); + int numberOfColumns = rsmd.getColumnCount(); + resp.add(new StringMessage("Message", + "Your results are:
\n" + )); + while (rs.next()) { + for (int i = 1; i <= numberOfColumns; i++) { +// if (i > 1){ out.write(", "); System.out.println(", ");} + String columnValue = rs.getString(i); + resp.add(new StringMessage("Message", + ESAPI.encoder().encodeForHTML(columnValue) + )); + } // end for + resp.add(new StringMessage("Message", + "
\n" + )); + } // end while + + } finally { + resp.add(new StringMessage("Message", + "

\n\n" + )); + } + } //end printResults + + public static void printResults(String query, int[] counts, HttpServletResponse response) throws IOException{ + PrintWriter out = response.getWriter(); + out.write("\n\n\n

"); + out.write("For query: " + ESAPI.encoder().encodeForHTML(query) + "
"); + try { + if(counts.length > 0){ + if(counts[0] == Statement.SUCCESS_NO_INFO){ + out.write("The SQL query was processed successfully but the number of rows affected is unknown."); + System.out.println("The SQL query was processed successfully but the number of rows affected is unknown."); + }else if(counts[0] == Statement.EXECUTE_FAILED){ + out.write("The SQL query failed to execute successfully and occurs only if a driver continues to process commands after a command fails"); + System.out.println("The SQL query failed to execute successfully and occurs only if a driver continues to process commands after a command fails"); + }else{ + out.write("The number of affected rows are: " + counts[0]); + System.out.println("The number of affected rows are: " + counts[0]); + } + } + } finally { + out.write("

\n\n"); + } + } //end printResults + + public static void printResults(String query, int[] counts, List resp) throws IOException{ + resp.add(new StringMessage("Message", + "For query: " + ESAPI.encoder().encodeForHTML(query) + "
" + )); + try { + if(counts.length > 0){ + if(counts[0] == Statement.SUCCESS_NO_INFO){ + resp.add(new StringMessage("Message", + "The SQL query was processed successfully but the number of rows affected is unknown." + )); + System.out.println("The SQL query was processed successfully but the number of rows affected is unknown."); + }else if(counts[0] == Statement.EXECUTE_FAILED){ + resp.add(new StringMessage("Message", + "The SQL query failed to execute successfully and occurs only if a driver continues to process commands after a command fails" + )); + System.out.println("The SQL query failed to execute successfully and occurs only if a driver continues to process commands after a command fails"); + }else{ + resp.add(new StringMessage("Message", + "The number of affected rows are: " + counts[0] + )); + System.out.println("The number of affected rows are: " + counts[0]); + } + } + } finally { + resp.add(new StringMessage("Message", + "

\n\n" + )); + } + } //end printResults + + public static void printColTypes(ResultSetMetaData rsmd, PrintWriter out) throws SQLException { + int columns = rsmd.getColumnCount(); + for (int i = 1; i <= columns; i++) { + int jdbcType = rsmd.getColumnType(i); + String name = rsmd.getColumnTypeName(i); + out.write("Column " + i + " is JDBC type " + jdbcType); + out.write(", which the DBMS calls " + name + "
\n"); + } + } + +} diff --git a/PR_5_java/java/filtered_java/03_tainted_xpath_from_http_request.java b/PR_5_java/java/filtered_java/03_tainted_xpath_from_http_request.java new file mode 100644 index 0000000..177cddb --- /dev/null +++ b/PR_5_java/java/filtered_java/03_tainted_xpath_from_http_request.java @@ -0,0 +1,258 @@ +/** + * OWASP Benchmark Project v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Nick Sanidas + * @created 2015 + */ +package lang.security.audit; + +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 = "/xpathi-00/BenchmarkTest00207") + class BenchmarkTest00207 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 { + response.setContentType("text/html;charset=UTF-8"); + + String param = ""; + if (request.getHeader("BenchmarkTest00207") != null) { + param = request.getHeader("BenchmarkTest00207"); + } + + // URL Decode the header value since req.getHeader() doesn't. Unlike req.getParameter(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + String bar = ""; + if (param != null) { + bar = + new String( + org.apache.commons.codec.binary.Base64.decodeBase64( + org.apache.commons.codec.binary.Base64.encodeBase64( + param.getBytes()))); + } + + try { + java.io.FileInputStream file = + new java.io.FileInputStream( + org.owasp.benchmark.helpers.Utils.getFileFromClasspath( + "employees.xml", this.getClass().getClassLoader())); + javax.xml.parsers.DocumentBuilderFactory builderFactory = + javax.xml.parsers.DocumentBuilderFactory.newInstance(); + // Prevent XXE + builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder(); + org.w3c.dom.Document xmlDocument = builder.parse(file); + javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance(); + javax.xml.xpath.XPath xp = xpf.newXPath(); + + String expression = "/Employees/Employee[@emplid='" + bar + "']"; + // {fact rule=xpath-injection@v1.0 defects=1} + // ruleid: tainted-xpath-from-http-request + String result = xp.evaluate(expression, xmlDocument); + + response.getWriter().println("Your query results are: " + result + "
"); + + } catch (javax.xml.xpath.XPathExpressionException + | javax.xml.parsers.ParserConfigurationException + | org.xml.sax.SAXException e) { + response.getWriter() + .println( + "Error parsing XPath input: '" + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(bar) + + "'"); + throw new ServletException(e); + } + } + // {/fact} +} + +@WebServlet(value = "/xpathi-00/BenchmarkTest01223") +class BenchmarkTest01223 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 { + response.setContentType("text/html;charset=UTF-8"); + + String param = ""; + java.util.Enumeration headers = request.getHeaders("BenchmarkTest01223"); + + if (headers != null && headers.hasMoreElements()) { + param = headers.nextElement(); // just grab first element + } + + // URL Decode the header value since req.getHeaders() doesn't. Unlike req.getParameters(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + String bar = new Test().doSomething(request, param); + + try { + java.io.FileInputStream file = + new java.io.FileInputStream( + org.owasp.benchmark.helpers.Utils.getFileFromClasspath( + "employees.xml", this.getClass().getClassLoader())); + javax.xml.parsers.DocumentBuilderFactory builderFactory = + javax.xml.parsers.DocumentBuilderFactory.newInstance(); + // Prevent XXE + builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder(); + org.w3c.dom.Document xmlDocument = builder.parse(file); + javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance(); + javax.xml.xpath.XPath xp = xpf.newXPath(); + + String expression = "/Employees/Employee[@emplid='" + bar + "']"; + // {fact rule=xpath-injection@v1.0 defects=1} + // ruleid: tainted-xpath-from-http-request + org.w3c.dom.NodeList nodeList = (org.w3c.dom.NodeList) xp.compile(expression).evaluate(xmlDocument, javax.xml.xpath.XPathConstants.NODESET); + + response.getWriter().println("Your query results are:
"); + + for (int i = 0; i < nodeList.getLength(); i++) { + org.w3c.dom.Element value = (org.w3c.dom.Element) nodeList.item(i); + response.getWriter().println(value.getTextContent() + "
"); + } + } catch (javax.xml.xpath.XPathExpressionException + | javax.xml.parsers.ParserConfigurationException + | org.xml.sax.SAXException e) { + response.getWriter() + .println( + "Error parsing XPath input: '" + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(bar) + + "'"); + throw new ServletException(e); + } + // {/fact} + } // end doPost + + private class Test { + + public String doSomething(HttpServletRequest request, String param) + throws ServletException, IOException { + + String bar; + String guess = "ABC"; + char switchTarget = guess.charAt(2); + + // Simple case statement that assigns param to bar on conditions 'A', 'C', or 'D' + switch (switchTarget) { + case 'A': + bar = param; + break; + case 'B': + bar = "bobs_your_uncle"; + break; + case 'C': + case 'D': + bar = param; + break; + default: + bar = "bobs_your_uncle"; + break; + } + + return bar; + } + } // end innerclass Test +} // end DataflowThruInnerClass + +@WebServlet(value = "/xpathi-00/BenchmarkTest00207") + class BenchmarkTest00207Ex 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 { + response.setContentType("text/html;charset=UTF-8"); + + String param = ""; + if (request.getHeader("BenchmarkTest00207") != null) { + param = request.getHeader("BenchmarkTest00207"); + } + + // URL Decode the header value since req.getHeader() doesn't. Unlike req.getParameter(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + String bar = ""; + if (param != null) { + bar = + new String( + org.apache.commons.codec.binary.Base64.decodeBase64( + org.apache.commons.codec.binary.Base64.encodeBase64( + param.getBytes()))); + } + + try { + java.io.FileInputStream file = + new java.io.FileInputStream( + org.owasp.benchmark.helpers.Utils.getFileFromClasspath( + "employees.xml", this.getClass().getClassLoader())); + javax.xml.parsers.DocumentBuilderFactory builderFactory = + javax.xml.parsers.DocumentBuilderFactory.newInstance(); + // Prevent XXE + builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder(); + org.w3c.dom.Document xmlDocument = builder.parse(file); + javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance(); + javax.xml.xpath.XPath xp = xpf.newXPath(); + + String expression = "/Employees/Employee[@emplid='1234']"; + // {fact rule=xpath-injection@v1.0 defects=0} + // ok: tainted-xpath-from-http-request + String result = xp.evaluate(expression, xmlDocument); + + response.getWriter().println("Your query results are: " + result + "
"); + + } catch (javax.xml.xpath.XPathExpressionException + | javax.xml.parsers.ParserConfigurationException + | org.xml.sax.SAXException e) { + response.getWriter() + .println( + "Error parsing XPath input: '" + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(bar) + + "'"); + throw new ServletException(e); + } + } + // {/fact} +} diff --git a/PR_5_java/java/filtered_java/04_tainted_ldapi_from_http_request.java b/PR_5_java/java/filtered_java/04_tainted_ldapi_from_http_request.java new file mode 100644 index 0000000..cfae2ab --- /dev/null +++ b/PR_5_java/java/filtered_java/04_tainted_ldapi_from_http_request.java @@ -0,0 +1,377 @@ +/** + * OWASP Benchmark v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Dave Wichers + * @created 2015 + */ +package lang.security.audit; + +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 = "/ldapi-00/BenchmarkTest00012") +class BenchmarkTest00012 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 = ""; + java.util.Enumeration headers = request.getHeaders("BenchmarkTest00012"); + + if (headers != null && headers.hasMoreElements()) { + param = headers.nextElement(); // just grab first element + } + + // URL Decode the header value since req.getHeaders() doesn't. Unlike req.getParameters(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + org.owasp.benchmark.helpers.LDAPManager ads = new org.owasp.benchmark.helpers.LDAPManager(); + try { + response.setContentType("text/html;charset=UTF-8"); + String base = "ou=users,ou=system"; + javax.naming.directory.SearchControls sc = new javax.naming.directory.SearchControls(); + sc.setSearchScope(javax.naming.directory.SearchControls.SUBTREE_SCOPE); + String filter = "(&(objectclass=person))(|(uid=" + param + ")(street={0}))"; + Object[] filters = new Object[] {"The streetz 4 Ms bar"}; + + javax.naming.directory.DirContext ctx = ads.getDirContext(); + javax.naming.directory.InitialDirContext idc = + (javax.naming.directory.InitialDirContext) ctx; + boolean found = false; + javax.naming.NamingEnumeration results = + // {fact rule=ldap-injection@v1.0 defects=1} + // ruleid: tainted-ldapi-from-http-request + idc.search(base, filter, filters, sc); + while (results.hasMore()) { + javax.naming.directory.SearchResult sr = + (javax.naming.directory.SearchResult) results.next(); + javax.naming.directory.Attributes attrs = sr.getAttributes(); + + javax.naming.directory.Attribute attr = attrs.get("uid"); + javax.naming.directory.Attribute attr2 = attrs.get("street"); + if (attr != null) { + response.getWriter() + .println( + "LDAP query results:
" + + "Record found with name " + + attr.get() + + "
" + + "Address: " + + attr2.get() + + "
"); + // System.out.println("record found " + attr.get()); + found = true; + } + } + if (!found) { + response.getWriter() + .println( + "LDAP query results: nothing found for query: " + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(filter)); + } + } catch (javax.naming.NamingException e) { + throw new ServletException(e); + } finally { + try { + ads.closeDirContext(); + } catch (Exception e) { + throw new ServletException(e); + } + } + } + // {/fact} +} + +/** + * OWASP Benchmark v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Dave Wichers + * @created 2015 + */ + +@WebServlet(value = "/ldapi-00/BenchmarkTest00021") +class BenchmarkTest00021 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 = request.getParameter("BenchmarkTest00021"); + if (param == null) param = ""; + + org.owasp.benchmark.helpers.LDAPManager ads = new org.owasp.benchmark.helpers.LDAPManager(); + try { + response.setContentType("text/html;charset=UTF-8"); + javax.naming.directory.DirContext ctx = ads.getDirContext(); + String base = "ou=users,ou=system"; + javax.naming.directory.SearchControls sc = new javax.naming.directory.SearchControls(); + sc.setSearchScope(javax.naming.directory.SearchControls.SUBTREE_SCOPE); + String filter = "(&(objectclass=person))(|(uid=" + param + ")(street={0}))"; + Object[] filters = new Object[] {"The streetz 4 Ms bar"}; + // System.out.println("Filter " + filter); + boolean found = false; + javax.naming.NamingEnumeration results = + // {fact rule=ldap-injection@v1.0 defects=1} + // ruleid: tainted-ldapi-from-http-request + ctx.search(base, filter, filters, sc); + while (results.hasMore()) { + javax.naming.directory.SearchResult sr = + (javax.naming.directory.SearchResult) results.next(); + javax.naming.directory.Attributes attrs = sr.getAttributes(); + + javax.naming.directory.Attribute attr = attrs.get("uid"); + javax.naming.directory.Attribute attr2 = attrs.get("street"); + if (attr != null) { + response.getWriter() + .println( + "LDAP query results:
" + + "Record found with name " + + attr.get() + + "
" + + "Address: " + + attr2.get() + + "
"); + // System.out.println("record found " + attr.get()); + found = true; + } + } + if (!found) { + response.getWriter() + .println( + "LDAP query results: nothing found for query: " + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(filter)); + } + } catch (javax.naming.NamingException e) { + throw new ServletException(e); + } finally { + try { + ads.closeDirContext(); + } catch (Exception e) { + throw new ServletException(e); + } + } + } + // {/fact} +} + +@WebServlet(value = "/ldapi-00/BenchmarkTest00630") +class BenchmarkTest00630 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 { + response.setContentType("text/html;charset=UTF-8"); + + org.owasp.benchmark.helpers.SeparateClassRequest scr = + new org.owasp.benchmark.helpers.SeparateClassRequest(request); + String param = scr.getTheParameter("BenchmarkTest00630"); + if (param == null) param = ""; + + String bar; + String guess = "ABC"; + char switchTarget = guess.charAt(2); + + // Simple case statement that assigns param to bar on conditions 'A', 'C', or 'D' + switch (switchTarget) { + case 'A': + bar = param; + break; + case 'B': + bar = "bobs_your_uncle"; + break; + case 'C': + case 'D': + bar = param; + break; + default: + bar = "bobs_your_uncle"; + break; + } + + org.owasp.benchmark.helpers.LDAPManager ads = new org.owasp.benchmark.helpers.LDAPManager(); + try { + response.setContentType("text/html;charset=UTF-8"); + String base = "ou=users,ou=system"; + javax.naming.directory.SearchControls sc = new javax.naming.directory.SearchControls(); + sc.setSearchScope(javax.naming.directory.SearchControls.SUBTREE_SCOPE); + String filter = "(&(objectclass=person)(uid=" + bar + "))"; + + javax.naming.directory.DirContext ctx = ads.getDirContext(); + javax.naming.directory.InitialDirContext idc = + (javax.naming.directory.InitialDirContext) ctx; + boolean found = false; + javax.naming.NamingEnumeration results = + // {fact rule=ldap-injection@v1.0 defects=1} + // ruleid: tainted-ldapi-from-http-request + idc.search(base, filter, sc); + + while (results.hasMore()) { + javax.naming.directory.SearchResult sr = + (javax.naming.directory.SearchResult) results.next(); + javax.naming.directory.Attributes attrs = sr.getAttributes(); + + javax.naming.directory.Attribute attr = attrs.get("uid"); + javax.naming.directory.Attribute attr2 = attrs.get("street"); + if (attr != null) { + response.getWriter() + .println( + "LDAP query results:
" + + "Record found with name " + + attr.get() + + "
" + + "Address: " + + attr2.get() + + "
"); + // System.out.println("record found " + attr.get()); + found = true; + } + } + if (!found) { + response.getWriter() + .println( + "LDAP query results: nothing found for query: " + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(filter)); + } + } catch (javax.naming.NamingException e) { + throw new ServletException(e); + } finally { + try { + ads.closeDirContext(); + } catch (Exception e) { + throw new ServletException(e); + } + } + } + // {/fact} +} + +@WebServlet(value = "/ldapi-00/BenchmarkTest00021") +class BenchmarkTest00021Ex 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 = request.getParameter("BenchmarkTest00021"); + if (param == null) param = ""; + + org.owasp.benchmark.helpers.LDAPManager ads = new org.owasp.benchmark.helpers.LDAPManager(); + try { + response.setContentType("text/html;charset=UTF-8"); + javax.naming.directory.DirContext ctx = ads.getDirContext(); + String base = "ou=users,ou=system"; + javax.naming.directory.SearchControls sc = new javax.naming.directory.SearchControls(); + sc.setSearchScope(javax.naming.directory.SearchControls.SUBTREE_SCOPE); + String filter = "(&(objectclass=person))(|(uid=" + "param" + ")(street={0}))"; + Object[] filters = new Object[] {"The streetz 4 Ms bar"}; + // System.out.println("Filter " + filter); + boolean found = false; + javax.naming.NamingEnumeration results = + // {fact rule=ldap-injection@v1.0 defects=0} + // ok: tainted-ldapi-from-http-request + ctx.search(base, filter, filters, sc); + while (results.hasMore()) { + javax.naming.directory.SearchResult sr = + (javax.naming.directory.SearchResult) results.next(); + javax.naming.directory.Attributes attrs = sr.getAttributes(); + + javax.naming.directory.Attribute attr = attrs.get("uid"); + javax.naming.directory.Attribute attr2 = attrs.get("street"); + if (attr != null) { + response.getWriter() + .println( + "LDAP query results:
" + + "Record found with name " + + attr.get() + + "
" + + "Address: " + + attr2.get() + + "
"); + // System.out.println("record found " + attr.get()); + found = true; + } + } + if (!found) { + response.getWriter() + .println( + "LDAP query results: nothing found for query: " + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(filter)); + } + } catch (javax.naming.NamingException e) { + throw new ServletException(e); + } finally { + try { + ads.closeDirContext(); + } catch (Exception e) { + throw new ServletException(e); + } + } + } + // {/fact} +} + diff --git a/PR_5_java/java/filtered_java/05_VulnerabilityType.java b/PR_5_java/java/filtered_java/05_VulnerabilityType.java new file mode 100644 index 0000000..0ff01ba --- /dev/null +++ b/PR_5_java/java/filtered_java/05_VulnerabilityType.java @@ -0,0 +1,55 @@ +package org.sasanlabs.vulnerability.types; + +/** @author KSASAN preetkaran20@gmail.com */ +public enum VulnerabilityType { + + // Sample Vulnerability type, should not be used for real vulnerability. + SAMPLE_VULNERABILITY(-1, -1), + + // SQL Injection + BLIND_SQL_INJECTION(89, 19), + + ERROR_BASED_SQL_INJECTION(89, 19), + UNION_BASED_SQL_INJECTION(89, 19), + + // XSS + REFLECTED_XSS(79, 8), + PERSISTENT_XSS(79, 8), + DOM_BASED_XSS(79, 8), + + // JWT Related + CLIENT_SIDE_VULNERABLE_JWT(null, null), + SERVER_SIDE_VULNERABLE_JWT(null, null), + INSECURE_CONFIGURATION_JWT(null, null), + + PATH_TRAVERSAL(22, 33), + + COMMAND_INJECTION(77, 31), + + UNRESTRICTED_FILE_UPLOAD(434, null), + + OPEN_REDIRECT_3XX_STATUS_CODE(601, 38), + + // SSRF Vulnerability + SIMPLE_SSRF(918, 15), + BLIND_SSRF(918, 15), + + // XXE Vulnerability + XXE(611, 43); + + private Integer cweID; + private Integer wascID; + + VulnerabilityType(Integer cweID, Integer wascID) { + this.cweID = cweID; + this.wascID = wascID; + } + + public Integer getCweID() { + return cweID; + } + + public Integer getWascID() { + return wascID; + } +} \ No newline at end of file diff --git a/PR_5_java/java/filtered_java/06_LDAPManager.java b/PR_5_java/java/filtered_java/06_LDAPManager.java new file mode 100644 index 0000000..80feed9 --- /dev/null +++ b/PR_5_java/java/filtered_java/06_LDAPManager.java @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.owasp.benchmark.helpers; + +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.*; +import java.util.Hashtable; + +/** + * A simple example exposing how to embed Apache Directory Server version 1.5.7 + * into an application. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class LDAPManager { + + private DirContext ctx; + + public LDAPManager() { + try { + ctx = getDirContext(); + } catch (NamingException e) { + System.out.println("Failed to get Directory Context: "+ e.getMessage()); + } + /* + String dir = Utils.getFileFromClasspath("benchmark.properties", EmbeddedADS.class.getClassLoader()).getParent(); + //File workDir = new File(dir + "/../../ldap"); + File workDir = new File(dir + "/../../ldap"); + // File workDir = new File(System.getProperty("user.dir") + + // "/benchmark/ldap"); + workDir.mkdirs(); + + // Create the server + // ads = new EmbeddedADS( workDir ); + try { + initDirectoryService(workDir); + } catch (Exception e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } +*/ + + // LDAPHelper lH = new LDAPHelper(); + + + } + + protected Hashtable createEnv() { + Hashtable env = new Hashtable(); + env.put(Context.PROVIDER_URL, "ldap://localhost:10389"); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + return env; + } + + public boolean insert(LDAPPerson person) { + Attributes matchAttrs = new BasicAttributes(true); + matchAttrs.put(new BasicAttribute("uid", person.getName())); + matchAttrs.put(new BasicAttribute("cn", person.getName())); + matchAttrs.put(new BasicAttribute("street", person.getAddress())); + matchAttrs.put(new BasicAttribute("sn", person.getName())); + matchAttrs.put(new BasicAttribute("userpassword", person.getPassword())); + matchAttrs.put(new BasicAttribute("objectclass", "top")); + matchAttrs.put(new BasicAttribute("objectclass", "person")); + matchAttrs.put(new BasicAttribute("objectclass", "organizationalPerson")); + matchAttrs.put(new BasicAttribute("objectclass", "inetorgperson")); + String name = "uid=" + person.getName() + ",ou=users,ou=system"; + InitialDirContext iniDirContext = (InitialDirContext) ctx; + + try { + iniDirContext.bind(name, ctx, matchAttrs); + } catch (NamingException e) { + if(!e.getMessage().contains("ENTRY_ALREADY_EXISTS")){ + System.out.println("Record already exist or an error ocurred: " + e.getMessage()); + } + }finally{ + if(iniDirContext != null){ + /* + try { + iniDirContext.close(); + } catch (NamingException e) { + System.out.println("Error when closing initial context: " + e.getMessage()); + } + */ + } + } + +// System.out.println("inserted"); + return true; + + } + + /** + * Search LDAPPerson by name + * + * @param person + * to search + * @return true if record found + */ + @SuppressWarnings("unused") + private boolean search(LDAPPerson person) { + try { + + DirContext ctx = getDirContext(); + String base = "ou=users,ou=system"; + + SearchControls sc = new SearchControls(); + sc.setSearchScope(SearchControls.SUBTREE_SCOPE); + + String filter = "(&(objectclass=person)(uid=" + person.getName() + "))"; + + NamingEnumeration results = ctx.search(base, filter, sc); + + while (results.hasMore()) { + SearchResult sr = (SearchResult) results.next(); + Attributes attrs = sr.getAttributes(); + + Attribute attr = attrs.get("uid"); + if (attr != null) { + // logger.debug("record found " + attr.get()); + // System.out.println("record found " + attr.get()); + } + } + ctx.close(); + + return true; + } catch (Exception e) { + System.out.println("LDAP error search: "); + // logger.error(e, e); + e.printStackTrace(); + return false; + } + } + + public DirContext getDirContext() throws NamingException { + if (ctx == null) { + return new InitialDirContext(createEnv()); + } + return ctx; + } + + public void closeDirContext() throws NamingException { + if (ctx != null) + ctx.close(); + } + + /** + * Main class. + * + * @param args + * Not used. + */ + public static void main(String[] args){ + /* + try { + + // ads.search(new LDAPPerson("foo","bar","ztretz")); + System.out.println("antes de la busqueda"); + + try { + + DirContext ctx = ads.getDirContext(); + String base = "ou=users,ou=system"; + javax.naming.directory.SearchControls sc = new javax.naming.directory.SearchControls(); + sc.setSearchScope(SearchControls.SUBTREE_SCOPE); + String filter = "(&(objectclass=person)(uid=" + "*" + "))"; + + javax.naming.NamingEnumeration results = ctx.search(base, filter, + sc); + while (results.hasMore()) { + javax.naming.directory.SearchResult sr = (javax.naming.directory.SearchResult) results.next(); + javax.naming.directory.Attributes attrs = sr.getAttributes(); + + javax.naming.directory.Attribute attr = attrs.get("uid"); + if (attr != null) { + // response.getWriter().write("LDAP query results: + // record found " + attr.get() + "
"); + System.out.println("record found " + attr.get()); + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + + } + + System.out.println("despues de la busqueda"); + + // lH.insert(ldapP); + + } catch (Exception e) { + // Ok, we have something wrong going on ... + e.printStackTrace(); + } finally { + try { + ads.closeDirContext(); + ads.stopServer(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }*/ + } +} diff --git a/PR_5_java/java/filtered_java/07_tainted_cmd_from_http_request.java b/PR_5_java/java/filtered_java/07_tainted_cmd_from_http_request.java new file mode 100644 index 0000000..476d341 --- /dev/null +++ b/PR_5_java/java/filtered_java/07_tainted_cmd_from_http_request.java @@ -0,0 +1,333 @@ +/** + * OWASP Benchmark v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Dave Wichers + * @created 2015 + */ +package lang.security.audit; + +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") +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"); + + java.util.List argList = new java.util.ArrayList(); + + String osName = System.getProperty("os.name"); + if (osName.indexOf("Windows") != -1) { + argList.add("cmd.exe"); + argList.add("/c"); + } else { + argList.add("sh"); + argList.add("-c"); + } + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: tainted-cmd-from-http-request + argList.add("echo " + param); + + ProcessBuilder pb = new ProcessBuilder(); + + pb.command(argList); + + try { + Process p = pb.start(); + org.owasp.benchmark.helpers.Utils.printOSCommandResults(p, response); + } catch (IOException e) { + System.out.println( + "Problem executing cmdi - java.lang.ProcessBuilder(java.util.List) Test Case"); + throw new ServletException(e); + } + // {/fact} + } +} + +@WebServlet(value = "/cmdi-00/BenchmarkTest00007") +class bad2 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("BenchmarkTest00007") != null) { + param = request.getHeader("BenchmarkTest00007"); + } + + // URL Decode the header value since req.getHeader() doesn't. Unlike req.getParameter(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + String cmd = + org.owasp.benchmark.helpers.Utils.getInsecureOSCommandString( + this.getClass().getClassLoader()); + String[] args = {cmd}; + String[] argsEnv = {param}; + + Runtime r = Runtime.getRuntime(); + + try { + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: tainted-cmd-from-http-request + Process p = r.exec(args, argsEnv); + org.owasp.benchmark.helpers.Utils.printOSCommandResults(p, response); + } catch (IOException e) { + System.out.println("Problem executing cmdi - TestCase"); + response.getWriter() + .println(org.owasp.esapi.ESAPI.encoder().encodeForHTML(e.getMessage())); + return; + } + // {/fact} + } +} + +@WebServlet(value = "/cmdi-00/BenchmarkTest00091") +class bad3 extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + javax.servlet.http.Cookie userCookie = + new javax.servlet.http.Cookie("BenchmarkTest00091", "FOO%3Decho+Injection"); + userCookie.setMaxAge(60 * 3); // Store cookie for 3 minutes + userCookie.setSecure(true); + userCookie.setPath(request.getRequestURI()); + userCookie.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost()); + response.addCookie(userCookie); + javax.servlet.RequestDispatcher rd = + request.getRequestDispatcher("/cmdi-00/BenchmarkTest00091.html"); + rd.include(request, response); + } + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + + javax.servlet.http.Cookie[] theCookies = request.getCookies(); + + String param = "noCookieValueSupplied"; + if (theCookies != null) { + for (javax.servlet.http.Cookie theCookie : theCookies) { + if (theCookie.getName().equals("BenchmarkTest00091")) { + param = java.net.URLDecoder.decode(theCookie.getValue(), "UTF-8"); + break; + } + } + } + + String bar = param; + + String cmd = + org.owasp.benchmark.helpers.Utils.getInsecureOSCommandString( + this.getClass().getClassLoader()); + String[] args = {cmd}; + String[] argsEnv = {bar}; + + Runtime r = Runtime.getRuntime(); + + try { + // ruleid: tainted-cmd-from-http-request + Process p = r.exec(args, argsEnv); + org.owasp.benchmark.helpers.Utils.printOSCommandResults(p, response); + } catch (IOException e) { + System.out.println("Problem executing cmdi - TestCase"); + response.getWriter() + .println(org.owasp.esapi.ESAPI.encoder().encodeForHTML(e.getMessage())); + return; + } + } +} + +@WebServlet(value = "/cmdi-00/BenchmarkTest00077") +class bad4 extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + javax.servlet.http.Cookie userCookie = + new javax.servlet.http.Cookie("BenchmarkTest00077", "ECHOOO"); + userCookie.setMaxAge(60 * 3); // Store cookie for 3 minutes + userCookie.setSecure(true); + userCookie.setPath(request.getRequestURI()); + userCookie.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost()); + response.addCookie(userCookie); + javax.servlet.RequestDispatcher rd = + request.getRequestDispatcher("/cmdi-00/BenchmarkTest00077.html"); + rd.include(request, response); + } + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + + javax.servlet.http.Cookie[] theCookies = request.getCookies(); + + String param = "noCookieValueSupplied"; + if (theCookies != null) { + for (javax.servlet.http.Cookie theCookie : theCookies) { + if (theCookie.getName().equals("BenchmarkTest00077")) { + param = java.net.URLDecoder.decode(theCookie.getValue(), "UTF-8"); + break; + } + } + } + + String bar; + String guess = "ABC"; + char switchTarget = guess.charAt(2); + + // Simple case statement that assigns param to bar on conditions 'A', 'C', or 'D' + switch (switchTarget) { + case 'A': + bar = param; + break; + case 'B': + bar = "bobs_your_uncle"; + break; + case 'C': + case 'D': + bar = param; + break; + default: + bar = "bobs_your_uncle"; + break; + } + + java.util.List argList = new java.util.ArrayList(); + + String osName = System.getProperty("os.name"); + if (osName.indexOf("Windows") != -1) { + argList.add("cmd.exe"); + argList.add("/c"); + } else { + argList.add("sh"); + argList.add("-c"); + } + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: tainted-cmd-from-http-request + argList.add("echo " + bar); + + + // deepruleid: tainted-cmd-from-http-request + ProcessBuilder pb = new ProcessBuilder(argList); + // {/fact} + try { + // deepruleid: tainted-cmd-from-http-request + Process p = pb.start(); + org.owasp.benchmark.helpers.Utils.printOSCommandResults(p, response); + } catch (IOException e) { + System.out.println( + "Problem executing cmdi - java.lang.ProcessBuilder(java.util.List) Test Case"); + throw new ServletException(e); + } + } +} + +@WebServlet(value = "/cmdi-00/BenchmarkTest00006") +class ok1 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"); + + java.util.List argList = new java.util.ArrayList(); + + String osName = System.getProperty("os.name"); + if (osName.indexOf("Windows") != -1) { + argList.add("cmd.exe"); + argList.add("/c"); + } else { + argList.add("sh"); + argList.add("-c"); + } + // {fact rule=os-command-injection@v1.0 defects=0} + // ok: tainted-cmd-from-http-request + argList.add("echo " + "param"); + + ProcessBuilder pb = new ProcessBuilder(); + + pb.command(argList); + + try { + Process p = pb.start(); + org.owasp.benchmark.helpers.Utils.printOSCommandResults(p, response); + } catch (IOException e) { + System.out.println( + "Problem executing cmdi - java.lang.ProcessBuilder(java.util.List) Test Case"); + throw new ServletException(e); + } + } + // {/fact} +} diff --git a/PR_5_java/java/filtered_java/08_desede_is_deprecated.java b/PR_5_java/java/filtered_java/08_desede_is_deprecated.java new file mode 100644 index 0000000..89a28c3 --- /dev/null +++ b/PR_5_java/java/filtered_java/08_desede_is_deprecated.java @@ -0,0 +1,153 @@ +package lang.security.audit.crypto; + +import jboss.security.Register; +import org.apache.log4j.Logger; + +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.security.*; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +class ClsEX extends HttpServlet +{ + private static Logger log = Logger.getLogger(Register.class); + + +// {fact rule=cryptographic-key-generator@v1.0 defects=1} + // cf. https://find-sec-bugs.github.io/bugs.htm#TDES_USAGE + protected void danger(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeyException { + // ruleid: desede-is-deprecated + Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding"); + Key k = null; + AlgorithmParameters iv = null; + c.init(Cipher.ENCRYPT_MODE, k, iv); + byte[] plainText = new byte[0]; + byte[] cipherText = c.doFinal(plainText); + } +// {/fact} + +// {fact rule=cryptographic-key-generator@v1.0 defects=0} + protected void ok(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeyException { + // ok: desede-is-deprecated + Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); + Key k = null; + AlgorithmParameters iv = null; + c.init(Cipher.ENCRYPT_MODE, k, iv); + ByteBuffer plainText = null; + byte[] cipherText = c.doFinal(plainText.array()); + } +} +// {/fact} + +/** + * OWASP Benchmark v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Dave Wichers + * @created 2015 + */ +@WebServlet(value = "/crypto-00/BenchmarkTest00019") +class BenchmarkTest00019 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 { + response.setContentType("text/html;charset=UTF-8"); + + java.io.InputStream param = request.getInputStream(); + + +// {fact rule=cryptographic-key-generator@v1.0 defects=1} + + try { + java.util.Properties benchmarkprops = new java.util.Properties(); + benchmarkprops.load( + this.getClass().getClassLoader().getResourceAsStream("benchmark.properties")); + String algorithm = benchmarkprops.getProperty("cryptoAlg1", "DESede/ECB/PKCS5Padding"); + Cipher c = Cipher.getInstance(algorithm); + + // Prepare the cipher to encrypt + // ruleid: desede-is-deprecated + javax.crypto.SecretKey key = javax.crypto.KeyGenerator.getInstance("DES").generateKey(); + c.init(Cipher.ENCRYPT_MODE, key); + + // encrypt and store the results + byte[] input = {(byte) '?'}; + Object inputParam = param; + if (inputParam instanceof String) input = ((String) inputParam).getBytes(); + if (inputParam instanceof java.io.InputStream) { + byte[] strInput = new byte[1000]; + int i = ((java.io.InputStream) inputParam).read(strInput); + if (i == -1) { + response.getWriter() + .println( + "This input source requires a POST, not a GET. Incompatible UI for the InputStream source."); + return; + } + input = java.util.Arrays.copyOf(strInput, i); + } + byte[] result = c.doFinal(input); + + File fileTarget = + new File( + new File(org.owasp.benchmark.helpers.Utils.TESTFILES_DIR), + "passwordFile.txt"); + java.io.FileWriter fw = + new java.io.FileWriter(fileTarget, true); // the true will append the new data + fw.write( + "secret_value=" + + org.owasp.esapi.ESAPI.encoder().encodeForBase64(result, true) + + "\n"); + fw.close(); + response.getWriter() + .println( + "Sensitive value: '" + + org.owasp + .esapi + .ESAPI + .encoder() + .encodeForHTML(new String(input)) + + "' encrypted and stored
"); + + } catch (NoSuchAlgorithmException + | NoSuchPaddingException + | IllegalBlockSizeException + | BadPaddingException + | InvalidKeyException e) { + response.getWriter() + .println( + "Problem executing crypto - javax.crypto.Cipher.getInstance(java.lang.String,java.security.Provider) Test Case"); + e.printStackTrace(response.getWriter()); + throw new ServletException(e); + } + } +} +// {/fact} diff --git a/PR_5_java/java/filtered_java/09_tainted_sql_from_http_request.java b/PR_5_java/java/filtered_java/09_tainted_sql_from_http_request.java new file mode 100644 index 0000000..442ac77 --- /dev/null +++ b/PR_5_java/java/filtered_java/09_tainted_sql_from_http_request.java @@ -0,0 +1,299 @@ +/** + * OWASP Benchmark v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Dave Wichers + * @created 2015 + */ +package lang.security.audit.sqli; + +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 = "/sqli-00/BenchmarkTest00008") +class bad1Ex 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("BenchmarkTest00008") != null) { + param = request.getHeader("BenchmarkTest00008"); + } + + // URL Decode the header value since req.getHeader() doesn't. Unlike req.getParameter(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + String sql = "{call " + param + "}"; + + try { + java.sql.Connection connection = + org.owasp.benchmark.helpers.DatabaseHelper.getSqlConnection(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: tainted-sql-from-http-request + java.sql.CallableStatement statement = connection.prepareCall(sql); + java.sql.ResultSet rs = statement.executeQuery(); + org.owasp.benchmark.helpers.DatabaseHelper.printResults(rs, sql, response); + + } catch (java.sql.SQLException e) { + if (org.owasp.benchmark.helpers.DatabaseHelper.hideSQLErrors) { + response.getWriter().println("Error processing request."); + return; + } else throw new ServletException(e); + } + // {/fact} + } +} + +@WebServlet(value = "/sqli-00/BenchmarkTest00018") +class bad2 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 = ""; + java.util.Enumeration headers = request.getHeaders("BenchmarkTest00018"); + + if (headers != null && headers.hasMoreElements()) { + param = headers.nextElement(); // just grab first element + } + + // URL Decode the header value since req.getHeaders() doesn't. Unlike req.getParameters(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + String sql = "INSERT INTO users (username, password) VALUES ('foo','" + param + "')"; + + try { + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: tainted-sql-from-http-request + java.sql.Statement statement = + org.owasp.benchmark.helpers.DatabaseHelper.getSqlStatement(); + int count = statement.executeUpdate(sql); + org.owasp.benchmark.helpers.DatabaseHelper.outputUpdateComplete(sql, response); + } catch (java.sql.SQLException e) { + if (org.owasp.benchmark.helpers.DatabaseHelper.hideSQLErrors) { + response.getWriter().println("Error processing request."); + return; + } else throw new ServletException(e); + } + // {/fact} + } +} + +@WebServlet(value = "/sqli-00/BenchmarkTest00024") +class bad3 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 = request.getParameter("BenchmarkTest00024"); + if (param == null) param = ""; + + String sql = "SELECT * from USERS where USERNAME=? and PASSWORD='" + param + "'"; + + try { + java.sql.Connection connection = + org.owasp.benchmark.helpers.DatabaseHelper.getSqlConnection(); + // ruleid: tainted-sql-from-http-request + java.sql.PreparedStatement statement = + connection.prepareStatement( + sql, + java.sql.ResultSet.TYPE_FORWARD_ONLY, + java.sql.ResultSet.CONCUR_READ_ONLY, + java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT); + statement.setString(1, "foo"); + statement.execute(); + org.owasp.benchmark.helpers.DatabaseHelper.printResults(statement, sql, response); + } catch (java.sql.SQLException e) { + if (org.owasp.benchmark.helpers.DatabaseHelper.hideSQLErrors) { + response.getWriter().println("Error processing request."); + return; + } else throw new ServletException(e); + } + } +} + +@WebServlet(value = "/sqli-00/BenchmarkTest00025") +class bad4 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 = request.getParameter("BenchmarkTest00025"); + if (param == null) param = ""; + + String sql = "SELECT userid from USERS where USERNAME='foo' and PASSWORD='" + param + "'"; + try { + // Long results = + // org.owasp.benchmark.helpers.DatabaseHelper.JDBCtemplate.queryForLong(sql); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: tainted-sql-from-http-request + Long results = + org.owasp.benchmark.helpers.DatabaseHelper.JDBCtemplate.queryForObject( + sql, Long.class); + response.getWriter().println("Your results are: " + String.valueOf(results)); + } catch (org.springframework.dao.EmptyResultDataAccessException e) { + response.getWriter() + .println( + "No results returned for query: " + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(sql)); + } catch (org.springframework.dao.DataAccessException e) { + if (org.owasp.benchmark.helpers.DatabaseHelper.hideSQLErrors) { + response.getWriter().println("Error processing request."); + } else throw new ServletException(e); + } + // {/fact} + } +} + +@WebServlet(value = "/sqli-00/BenchmarkTest00026") +class bad5 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 = request.getParameter("BenchmarkTest00026"); + if (param == null) param = ""; + + String sql = "SELECT * from USERS where USERNAME='foo' and PASSWORD='" + param + "'"; + try { + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: tainted-sql-from-http-request + org.springframework.jdbc.support.rowset.SqlRowSet results = + org.owasp.benchmark.helpers.DatabaseHelper.JDBCtemplate.queryForRowSet(sql); + response.getWriter().println("Your results are: "); + + // System.out.println("Your results are"); + while (results.next()) { + response.getWriter() + .println( + org.owasp + .esapi + .ESAPI + .encoder() + .encodeForHTML(results.getString("USERNAME")) + + " "); + // System.out.println(results.getString("USERNAME")); + } + } catch (org.springframework.dao.EmptyResultDataAccessException e) { + response.getWriter() + .println( + "No results returned for query: " + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(sql)); + } catch (org.springframework.dao.DataAccessException e) { + if (org.owasp.benchmark.helpers.DatabaseHelper.hideSQLErrors) { + response.getWriter().println("Error processing request."); + } else throw new ServletException(e); + } + // {/fact} + } +} + +@WebServlet(value = "/sqli-00/BenchmarkTest00008") +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 = "test"; + + String sql = "{call " + param + "}"; + + try { + java.sql.Connection connection = + org.owasp.benchmark.helpers.DatabaseHelper.getSqlConnection(); + // {fact rule=sql-injection@v1.0 defects=0} + // ok: tainted-sql-from-http-request + java.sql.CallableStatement statement = connection.prepareCall(sql); + java.sql.ResultSet rs = statement.executeQuery(); + org.owasp.benchmark.helpers.DatabaseHelper.printResults(rs, sql, response); + + } catch (java.sql.SQLException e) { + if (org.owasp.benchmark.helpers.DatabaseHelper.hideSQLErrors) { + response.getWriter().println("Error processing request."); + return; + } else throw new ServletException(e); + } + // {/fact} + } +} diff --git a/PR_5_java/java/filtered_java/10_tainted_html_string.java b/PR_5_java/java/filtered_java/10_tainted_html_string.java new file mode 100644 index 0000000..6fc6c1e --- /dev/null +++ b/PR_5_java/java/filtered_java/10_tainted_html_string.java @@ -0,0 +1,236 @@ +package spring.security.injection; + +import java.util.HashSet; +import java.util.Set; +import org.apache.commons.text.StringEscapeUtils; +import org.sasanlabs.internal.utility.LevelConstants; +import org.sasanlabs.internal.utility.Variant; +import org.sasanlabs.internal.utility.annotations.AttackVector; +import org.sasanlabs.internal.utility.annotations.VulnerableAppRequestMapping; +import org.sasanlabs.internal.utility.annotations.VulnerableAppRestController; +import org.sasanlabs.vulnerability.types.VulnerabilityType; +import org.sasanlabs.vulnerability.utils.Constants; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.util.HtmlUtils; + +/** + * This class contains XSS vulnerabilities which are present in Image Tag attribute. + * + * @author KSASAN preetkaran20@gmail.com + * @author jpralle janpralle@gmail.com + * @author t0bel1x t0bel1x.git@gmail.com + * @author pdelmonego philipp.delmonego@live.de + */ +@VulnerableAppRestController(descriptionLabel = "XSS_VULNERABILITY", value = "XSSInImgTagAttribute") +class XSSInImgTagAttribute { + + private static final String OWASP_IMAGE = "images/owasp.png"; + private static final String ZAP_IMAGE = "images/ZAP.png"; + private static final String PARAMETER_NAME = "src"; + public static final String IMAGE_RESOURCE_PATH = "/VulnerableApp/images/"; + public static final String FILE_EXTENSION = ".png"; + + private final Set allowedValues = new HashSet<>(); + + public XSSInImgTagAttribute() { + allowedValues.add(OWASP_IMAGE); + allowedValues.add(ZAP_IMAGE); + } + + // Just adding User defined input(Untrusted Data) into Src tag is not secure. + // Can be broken by various ways + // {fact rule=reflected-cross-site-scripting@v1.0 defects=1} + @AttackVector( + vulnerabilityExposed = VulnerabilityType.REFLECTED_XSS, + description = "XSS_DIRECT_INPUT_SRC_ATTRIBUTE_IMG_TAG") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_1, htmlTemplate = "LEVEL_1/XSS") + public ResponseEntity getVulnerablePayloadLevel1( + @RequestParam(PARAMETER_NAME) String imageLocation) { + + String vulnerablePayloadWithPlaceHolder = ""; + + return new ResponseEntity<>( + +// ruleid: tainted-html-string + String.format(vulnerablePayloadWithPlaceHolder, imageLocation), HttpStatus.OK); + } + +// {/fact} + + // Adding Untrusted Data into Src tag between quotes is beneficial but not + // without escaping the input + // {fact rule=reflected-cross-site-scripting@v1.0 defects=1} + @AttackVector( + vulnerabilityExposed = VulnerabilityType.REFLECTED_XSS, + description = "XSS_QUOTES_ON_INPUT_SRC_ATTRIBUTE_IMG_TAG") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_2, htmlTemplate = "LEVEL_1/XSS") + public ResponseEntity getVulnerablePayloadLevel2( + @RequestParam(PARAMETER_NAME) String imageLocation) { + + String vulnerablePayloadWithPlaceHolder = ""; + + + // ruleid: tainted-html-string + String payload = String.format(vulnerablePayloadWithPlaceHolder, imageLocation); + + return new ResponseEntity<>(payload, HttpStatus.OK); + } + // {/fact} + + // Good way for HTML escapes so hacker cannot close the tags but can use event + // handlers like onerror etc. eg:- ''onerror='alert(1);' + // {fact rule=reflected-cross-site-scripting@v1.0 defects=0} + @AttackVector( + vulnerabilityExposed = VulnerabilityType.REFLECTED_XSS, + description = "XSS_HTML_ESCAPE_ON_DIRECT_INPUT_SRC_ATTRIBUTE_IMG_TAG") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_3, htmlTemplate = "LEVEL_1/XSS") + public ResponseEntity getVulnerablePayloadLevel3( + @RequestParam(PARAMETER_NAME) String imageLocation) { + + String vulnerablePayloadWithPlaceHolder = ""; + + String payload = + +// ruleid: tainted-html-string + String.format( + vulnerablePayloadWithPlaceHolder, + StringEscapeUtils.escapeHtml4(imageLocation)); + + return new ResponseEntity<>(payload, HttpStatus.OK); + } +// {/fact} + + // Good way for HTML escapes so hacker cannot close the tags and also cannot pass brackets but + // can use event + // handlers like onerror etc. eg:- onerror=alert`1` (backtick operator) + // {fact rule=reflected-cross-site-scripting@v1.0 defects=0} + @AttackVector( + vulnerabilityExposed = VulnerabilityType.REFLECTED_XSS, + description = + "XSS_HTML_ESCAPE_ON_DIRECT_INPUT_AND_REMOVAL_OF_VALUES_WITH_PARENTHESIS_SRC_ATTRIBUTE_IMG_TAG") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_4, htmlTemplate = "LEVEL_1/XSS") + public ResponseEntity getVulnerablePayloadLevel4( + @RequestParam(PARAMETER_NAME) String imageLocation) { + + String vulnerablePayloadWithPlaceHolder = ""; + StringBuilder payload = new StringBuilder(); + + if (!imageLocation.contains("(") || !imageLocation.contains(")")) { + payload.append( + +// ruleid: tainted-html-string + String.format( + vulnerablePayloadWithPlaceHolder, + StringEscapeUtils.escapeHtml4(imageLocation))); + } + + return new ResponseEntity<>(payload.toString(), HttpStatus.OK); + } + // {/fact} + + // Assume here that there is a validator vulnerable to Null Byte which validates the file name + // only till null byte + // {fact rule=reflected-cross-site-scripting@v1.0 defects=0} + @AttackVector( + vulnerabilityExposed = VulnerabilityType.REFLECTED_XSS, + description = + "XSS_HTML_ESCAPE_PLUS_FILTERING_ON_INPUT_SRC_ATTRIBUTE_IMG_TAG_BUT_NULL_BYTE_VULNERABLE") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_5, htmlTemplate = "LEVEL_1/XSS") + public ResponseEntity getVulnerablePayloadLevel5( + @RequestParam(PARAMETER_NAME) String imageLocation) { + + String vulnerablePayloadWithPlaceHolder = ""; + StringBuilder payload = new StringBuilder(); + + String validatedFileName = imageLocation; + + // Behavior of Null Byte Vulnerable Validator for filename + if (imageLocation.contains(Constants.NULL_BYTE_CHARACTER)) { + validatedFileName = + imageLocation.substring( + 0, imageLocation.indexOf(Constants.NULL_BYTE_CHARACTER)); + } + + if (allowedValues.contains(validatedFileName)) { + payload.append( + +// ruleid: tainted-html-string + String.format( + vulnerablePayloadWithPlaceHolder, + StringEscapeUtils.escapeHtml4(imageLocation))); + } + + return new ResponseEntity<>(payload.toString(), HttpStatus.OK); + } + +// {/fact} + + // Good way and can protect against attacks but it is better to have check on + // the input values provided if possible. + // {fact rule=reflected-cross-site-scripting@v1.0 defects=0} + @AttackVector( + vulnerabilityExposed = VulnerabilityType.REFLECTED_XSS, + description = "XSS_QUOTES_AND_WITH_HTML_ESCAPE_ON_INPUT_SRC_ATTRIBUTE_IMG_TAG") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_6, + variant = Variant.SECURE, + htmlTemplate = "LEVEL_1/XSS") + public ResponseEntity getVulnerablePayloadLevel6( + @RequestParam(PARAMETER_NAME) String imageLocation) { + + String vulnerablePayloadWithPlaceHolder = ""; + + if (allowedValues.contains(imageLocation)) { + String payload = + + // ruleid: tainted-html-string + String.format( + vulnerablePayloadWithPlaceHolder, + StringEscapeUtils.escapeHtml4(imageLocation)); + + return new ResponseEntity<>(payload, HttpStatus.OK); + } + + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } +// {/fact} + + // Escape all special characters to their corresponding HTML hex format + // and validate input. + // Would be even better if Content Security Policy (CSP) is set. + // {fact rule=reflected-cross-site-scripting@v1.0 defects=1} + @AttackVector( + vulnerabilityExposed = VulnerabilityType.REFLECTED_XSS, + description = + "XSS_QUOTES_AND_WITH_HTML_ESCAPE_PLUS_FILTERING_ON_INPUT_SRC_ATTRIBUTE_IMG_TAG") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_7, + variant = Variant.SECURE, + htmlTemplate = "LEVEL_1/XSS") + public ResponseEntity getVulnerablePayloadLevelSecure( + @RequestParam(PARAMETER_NAME) String imageLocation) { + String vulnerablePayloadWithPlaceHolder = ""; + + if ((imageLocation.startsWith(IMAGE_RESOURCE_PATH) + && imageLocation.endsWith(FILE_EXTENSION)) + || allowedValues.contains(imageLocation)) { + + String payload = + +// ruleid: tainted-html-string + String.format( + vulnerablePayloadWithPlaceHolder, + HtmlUtils.htmlEscapeHex(imageLocation)); + + return new ResponseEntity<>(payload, HttpStatus.OK); + + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } +} + +// {/fact} + diff --git a/PR_5_java/java/filtered_java/11_dangerous_groovy_shell.java b/PR_5_java/java/filtered_java/11_dangerous_groovy_shell.java new file mode 100644 index 0000000..c0bc70b --- /dev/null +++ b/PR_5_java/java/filtered_java/11_dangerous_groovy_shell.java @@ -0,0 +1,81 @@ +package lang.security.audit; + +import groovy.lang.GroovyClassLoader; +import groovy.lang.GroovyCodeSource; +import groovy.lang.GroovyShell; +import org.springframework.web.bind.annotation.RequestParam; + +import java.io.*; +import java.net.URI; +import java.net.URISyntaxException; + +class GroovyShellUsage { + + public static void test1(@RequestParam("uri") String uri,@RequestParam("file") String file,@RequestParam("script") String script) throws URISyntaxException, IOException { + GroovyShell shell = new GroovyShell(); + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid:dangerous-groovy-shell + shell.evaluate(new File(file)); + // ruleid:dangerous-groovy-shell + shell.evaluate(new InputStreamReader(new FileInputStream(file)), "script1.groovy"); + // ruleid:dangerous-groovy-shell + shell.evaluate(script); + // ruleid:dangerous-groovy-shell + shell.evaluate(script, "script1.groovy", "test"); + // ruleid:dangerous-groovy-shell + shell.evaluate(String.valueOf(new URI(uri))); + // {/fact} + // {fact rule=code-injection@v1.0 defects=0} + // ok:dangerous-groovy-shell + shell.evaluate("hardcoded script"); + // {/fact} + } + + public static void test2(@RequestParam("uri") String uri,@RequestParam("file") String file,@RequestParam("script") String script) throws URISyntaxException, IOException { + GroovyShell shell = new GroovyShell(); + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid:dangerous-groovy-shell + shell.parse(new File(file)); + // ruleid:dangerous-groovy-shell + shell.parse(new InputStreamReader(new FileInputStream(file)), "test.groovy"); + // ruleid:dangerous-groovy-shell + shell.parse(new InputStreamReader(new FileInputStream(file))); + // ruleid:dangerous-groovy-shell + shell.parse(script); + // ruleid:dangerous-groovy-shell + shell.parse(script, "test.groovy"); + // ruleid:dangerous-groovy-shell + shell.parse(String.valueOf(new URI(uri))); + // {/fact} + + String hardcodedScript = "test.groovy"; + // {fact rule=code-injection@v1.0 defects=0} + // ok:dangerous-groovy-shell + shell.parse(hardcodedScript); + // {/fact} + } + + public static void test3(@RequestParam("uri") String uri,@RequestParam("file") String file,@RequestParam("script") String script, ClassLoader loader) throws URISyntaxException, IOException { + GroovyClassLoader groovyLoader = (GroovyClassLoader) loader; + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid:dangerous-groovy-shell + groovyLoader.parseClass(new GroovyCodeSource(new File(file)),false); + // ruleid:dangerous-groovy-shell + groovyLoader.parseClass(String.valueOf(new InputStreamReader(new FileInputStream(file))), "test.groovy"); + // ruleid:dangerous-groovy-shell + groovyLoader.parseClass(script); + // ruleid:dangerous-groovy-shell + groovyLoader.parseClass(script,"test.groovy"); + // {/fact} + + String hardcodedScript = "test.groovy"; + // {fact rule=code-injection@v1.0 defects=0} + // ok:dangerous-groovy-shell + GroovyShell shell = new GroovyShell(); + shell.parse(hardcodedScript); + // {/fact} + } +} diff --git a/PR_5_java/java/filtered_java/12_no_direct_response_writer.java b/PR_5_java/java/filtered_java/12_no_direct_response_writer.java new file mode 100644 index 0000000..21759c1 --- /dev/null +++ b/PR_5_java/java/filtered_java/12_no_direct_response_writer.java @@ -0,0 +1,311 @@ +/** +* OWASP Benchmark Project v1.2 +* +* This file is part of the Open Web Application Security Project (OWASP) +* Benchmark Project. For details, please see +* https://www.owasp.org/index.php/Benchmark. +* +* The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms +* of the GNU General Public License as published by the Free Software Foundation, version 2. +* +* The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without +* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* @author Nick Sanidas Aspect Security +* @created 2015 +*/ + +package lang.security.audit.xss; + +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="/xss-04/BenchmarkTest02229") +class BenchmarkTest02229 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 { + response.setContentType("text/html;charset=UTF-8"); + + java.util.Map map = request.getParameterMap(); + String param = ""; + if (!map.isEmpty()) { + String[] values = map.get("BenchmarkTest02229"); + if (values != null) param = values[0]; + } + + + String bar = doSomething(request, param); + +response.setHeader("X-XSS-Protection", "0"); + Object[] obj = { "a", bar}; + // {fact rule=cross-site-scripting@v1.0 defects=1} + // ruleid: no-direct-response-writer + response.getWriter().printf(java.util.Locale.US,"Formatted like: %1$s and %2$s.",obj); + } // end doPost + // {/fact} + + + private static String doSomething(HttpServletRequest request, String param) throws ServletException, IOException { + + String bar = "safe!"; + java.util.HashMap map26903 = new java.util.HashMap(); + map26903.put("keyA-26903", "a_Value"); // put some stuff in the collection + map26903.put("keyB-26903", param); // put it in a collection + map26903.put("keyC", "another_Value"); // put some stuff in the collection + bar = (String)map26903.get("keyB-26903"); // get it back out + bar = (String)map26903.get("keyA-26903"); // get safe value back out + + return bar; + } +} + + +@WebServlet(value="/hash-02/BenchmarkTest02388") +class BenchmarkTest02388 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 { + response.setContentType("text/html;charset=UTF-8"); + + org.owasp.benchmark.helpers.SeparateClassRequest scr = new org.owasp.benchmark.helpers.SeparateClassRequest( request ); + String param = scr.getTheParameter("BenchmarkTest02388"); + if (param == null) param = ""; + + String bar = doSomething(request, param); + + try { + java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); + byte[] input = { (byte)'?' }; + Object inputParam = bar; + if (inputParam instanceof String) input = ((String) inputParam).getBytes(); + if (inputParam instanceof java.io.InputStream) { + byte[] strInput = new byte[1000]; + int i = ((java.io.InputStream) inputParam).read(strInput); + if (i == -1) { + // {fact rule=cross-site-scripting@v1.0 defects=0} + // ok: no-direct-response-writer + response.getWriter().println( +"This input source requires a POST, not a GET. Incompatible UI for the InputStream source." +); + return; + } + // {/fact} + input = java.util.Arrays.copyOf(strInput, i); + } + md.update(input); + + byte[] result = md.digest(); + java.io.File fileTarget = new java.io.File( + new java.io.File(org.owasp.benchmark.helpers.Utils.testfileDir),"passwordFile.txt"); + java.io.FileWriter fw = new java.io.FileWriter(fileTarget,true); //the true will append the new data + fw.write("hash_value=" + org.owasp.esapi.ESAPI.encoder().encodeForBase64(result, true) + "\n"); + fw.close(); + // {fact rule=cross-site-scripting@v1.0 defects=1} + // ruleid: no-direct-response-writer + response.getWriter().println( + + "Sensitive value '" + org.owasp.esapi.ESAPI.encoder().encodeForHTML(new String(input)) + "' hashed and stored
" +); +// {/fact} + } catch (java.security.NoSuchAlgorithmException e) { + System.out.println("Problem executing hash - TestCase"); + throw new ServletException(e); + } + + // {fact rule=cross-site-scripting@v1.0 defects=0} + // OK because constant string + // ok: no-direct-response-writer + response.getWriter().println( +"Hash Test java.security.MessageDigest.getInstance(java.lang.String) executed" +); + } // end doPost + // {/fact} + + + private static String doSomething(HttpServletRequest request, String param) throws ServletException, IOException { + + String bar = "safe!"; + java.util.HashMap map94322 = new java.util.HashMap(); + map94322.put("keyA-94322", "a_Value"); // put some stuff in the collection + map94322.put("keyB-94322", param); // put it in a collection + map94322.put("keyC", "another_Value"); // put some stuff in the collection + bar = (String)map94322.get("keyB-94322"); // get it back out + bar = (String)map94322.get("keyA-94322"); // get safe value back out + + return bar; + } +} + + +@WebServlet(value = "/xss-04/BenchmarkTest02229Ex") +class BenchmarkTest02229Ex 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 { + response.setContentType("text/html;charset=UTF-8"); + + java.util.Map map = request.getParameterMap(); + String param = ""; + if (!map.isEmpty()) { + String[] values = map.get("BenchmarkTest02229"); + if (values != null) param = values[0]; + } + + String bar = doSomething(request, param); + + response.setHeader("X-XSS-Protection", "0"); + Object[] obj = {"a", bar}; + // {fact rule=cross-site-scripting@v1.0 defects=1} + // ruleid: no-direct-response-writer + response.getWriter().printf(java.util.Locale.US, "Formatted like: %1$s and %2$s.", obj); + } // end doPost + // {/fact} + + private static String doSomething(HttpServletRequest request, String param) + throws ServletException, IOException { + + String bar = "safe!"; + java.util.HashMap map26903 = new java.util.HashMap(); + map26903.put("keyA-26903", "a_Value"); // put some stuff in the collection + map26903.put("keyB-26903", param); // put it in a collection + map26903.put("keyC", "another_Value"); // put some stuff in the collection + bar = (String) map26903.get("keyB-26903"); // get it back out + bar = (String) map26903.get("keyA-26903"); // get safe value back out + + return bar; + } +} + +@WebServlet(value = "/xss-00/BenchmarkTest00013") +class BenchmarkTest00013 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 = ""; + java.util.Enumeration headers = request.getHeaders("Referer"); + + if (headers != null && headers.hasMoreElements()) { + param = headers.nextElement(); // just grab first element + } + + // URL Decode the header value since req.getHeaders() doesn't. Unlike req.getParameters(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + response.setHeader("X-XSS-Protection", "0"); + Object[] obj = {"a", "b"}; + // {fact rule=cross-site-scripting@v1.0 defects=1} + // ruleid: no-direct-response-writer + response.getWriter().format(java.util.Locale.US, param, obj); + } + // {/fact} +} + +/** + * OWASP Benchmark Project v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Nick Sanidas + * @created 2015 + */ + +@WebServlet(value = "/xss-04/BenchmarkTest02221") +class BenchmarkTest02221 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 { + response.setContentType("text/html;charset=UTF-8"); + + java.util.Map map = request.getParameterMap(); + String param = ""; + if (!map.isEmpty()) { + String[] values = map.get("BenchmarkTest02221"); + if (values != null) param = values[0]; + } + + String bar = doSomething(request, param); + + response.setHeader("X-XSS-Protection", "0"); + Object[] obj = {"a", bar}; + java.io.PrintWriter out = response.getWriter(); + out.write("\n\n\n

"); + // {fact rule=cross-site-scripting@v1.0 defects=1} + // ruleid: no-direct-response-writer + out.format(java.util.Locale.US, "Formatted like: %1$s and %2$s.", obj); + out.write("\n

\n\n"); + } // end doPost + // {/fact} + + private static String doSomething(HttpServletRequest request, String param) + throws ServletException, IOException { + + String bar = param; + if (param != null && param.length() > 1) { + StringBuilder sbxyz71523 = new StringBuilder(param); + bar = sbxyz71523.replace(param.length() - "Z".length(), param.length(), "Z").toString(); + } + + return bar; + } +} + diff --git a/PR_5_java/java/filtered_java/13_spring_sqli.java b/PR_5_java/java/filtered_java/13_spring_sqli.java new file mode 100644 index 0000000..707fa84 --- /dev/null +++ b/PR_5_java/java/filtered_java/13_spring_sqli.java @@ -0,0 +1,465 @@ +package spring.security.audit; + +import org.springframework.jdbc.core.BatchUpdateUtils; +import org.springframework.jdbc.core.JdbcTemplate; +import lang.security.audit.sqli.UserEntity; +import org.springframework.jdbc.core.PreparedStatementCreatorFactory; +import org.springframework.jdbc.core.SqlParameter; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.*; +import org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.sql.*; +import java.util.ArrayList; +import java.util.Arrays; + +class SpringPreparedStatementCreatorFactory { + public void queryUnsafe(String input) { + String sql = "select * from Users where name = '" + input + "' id=?"; + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + new PreparedStatementCreatorFactory(sql); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + new PreparedStatementCreatorFactory(sql, new int[] {Types.INTEGER}); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + new PreparedStatementCreatorFactory(sql, new ArrayList()); + } // {/fact} + +} + +class SpringJdbcTemplate { + + public void query1(JdbcTemplate jdbcTemplate, String input) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.execute("select * from Users where name = '"+input+"'"); + } + // {/fact} + + + public void query2(JdbcTemplate jdbcTemplate, String input) throws DataAccessException { + String sql = "select * from Users where name = '" + input + "'"; + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.execute(sql); + } + // {/fact} + + + public void query3(JdbcTemplate jdbcTemplate, String input) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.execute(String.format("select * from Users where name = '%s'",input)); + } + // {/fact} + + + public void query4(JdbcTemplate jdbcTemplate, String input) throws DataAccessException { + String sql = "select * from Users where name = '%s'"; + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.execute(String.format(sql,input)); + } + // {/fact} + + + public void querySafe(JdbcTemplate jdbcTemplate, String input) throws DataAccessException { + String sql = "select * from Users where name = '1'"; + + // {fact rule=sql-injection@v1.0 defects=0} + // ok:spring-sqli + jdbcTemplate.execute(sql); + } + // {/fact} + + + public void queryExecute(JdbcTemplate jdbcTemplate, String sql) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.execute(sql); + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + // Not finding a suitable example + //jdbcTemplate.execute(new StoredProcCall(sql), new TestCallableStatementCallback()); + // ruleid:spring-sqli + jdbcTemplate.execute(sql, (PreparedStatementCallback) new TestCallableStatementCallback()); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.execute(sql, new TestCallableStatementCallback()); + } + // {/fact} + + + public void queryBatchUpdate(JdbcTemplate jdbcTemplate, String sql, String taintedString) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.batchUpdate(sql); + // {/fact} + + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.batchUpdate(sql, sql); + // {/fact} + + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.batchUpdate("select * from dual", sql); + // {/fact} + + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.batchUpdate(sql, "select * from dual"); + // {/fact} + + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.batchUpdate(sql, new TestBatchPreparedStatementSetter()); + // {/fact} + + + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.batchUpdate(sql, Arrays.asList(new UserEntity()), 11, new TestParameterizedPreparedStatementSetter()); + // {/fact} + + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.batchUpdate(sql, new ArrayList()); + // {/fact} + + + + // {fact rule=sql-injection@v1.0 defects=0} + // ok:spring-sqli + jdbcTemplate.batchUpdate("SELECT foo FROM bar WHERE baz = 'biz'", new ArrayList(Arrays.asList(new Object[] {taintedString}))); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.batchUpdate(sql, new ArrayList(), new int[]{Types.INTEGER, Types.VARCHAR, Types.VARCHAR}); + } + // {/fact} + + + public void queryForObject(JdbcTemplate jdbcTemplate, String sql) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForObject(sql, new TestRowMapper()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForObject(sql, new TestRowMapper(), "", ""); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForObject(sql, UserEntity.class); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForObject(sql, UserEntity.class, "", ""); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForObject(sql, new Object[0], UserEntity.class); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForObject(sql, new Object[0], new int[]{Types.INTEGER, Types.VARCHAR, Types.VARCHAR}, UserEntity.class); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForObject(sql, new Object[0], new int[]{Types.INTEGER, Types.VARCHAR, Types.VARCHAR}, new TestRowMapper()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForObject(sql, new Object[0], new TestRowMapper()); + } + // {/fact} + + + public void querySamples(JdbcTemplate jdbcTemplate, @RequestParam("sql") String sql) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new TestResultSetExtractor()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new TestRowCallbackHandler()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new TestRowMapper()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new TestPreparedStatementSetter(), new TestResultSetExtractor()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new TestPreparedStatementSetter(), new TestRowCallbackHandler()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new TestPreparedStatementSetter(), new TestRowMapper()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new Object[0], new TestRowMapper()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new Object[0], new TestRowCallbackHandler()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new Object[0], new TestResultSetExtractor()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new Object[0], new int[]{Types.VARCHAR}, new TestResultSetExtractor()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new Object[0], new int[]{Types.VARCHAR}, new TestRowMapper()); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.query(sql, new Object[0], new int[]{Types.VARCHAR}, new TestRowCallbackHandler()); + } + // {/fact} + + + public void queryForList(JdbcTemplate jdbcTemplate, String sql) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForList(sql); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForList(sql, UserEntity.class); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForList(sql, new Object[0], UserEntity.class); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForList(sql, new Object[0], new int[]{Types.VARCHAR}); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForList(sql, new Object[0], new int[]{Types.VARCHAR}, UserEntity.class); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForList(sql, new Object[0]); + } + // {/fact} + + + public void queryForMap(JdbcTemplate jdbcTemplate, String sql) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForMap(sql); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForMap(sql, new Object[0]); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForMap(sql, new Object[0], new int[]{Types.VARCHAR}); + } + // {/fact} + + + public void queryForRowSet(JdbcTemplate jdbcTemplate, @RequestParam("sql") String sql) throws DataAccessException { + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForRowSet(sql); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForRowSet(sql, new Object[0]); + + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + jdbcTemplate.queryForRowSet(sql, new Object[0], new int[]{Types.VARCHAR}); + } + // {/fact} + + + /** + * https://stackoverflow.com/questions/15661313/jdbctemplate-queryforint-long-is-deprecated-in-spring-3-2-2-what-should-it-be-r + */ + +/* public void queryForInt(JdbcTemplate jdbcTemplate, String sql) throws DataAccessException { + // ruleid:spring-sqli + jdbcTemplate.queryForInt(sql); + // ruleid:spring-sqli + jdbcTemplate.queryForInt(sql, new Object[0]); + // ruleid:spring-sqli + jdbcTemplate.queryForInt(sql, new Object[0], new int[]{Types.VARCHAR}); + }*/ + +/* public void queryForLong(JdbcTemplate jdbcTemplate, String sql) throws DataAccessException { + // ruleid:spring-sqli + jdbcTemplate.queryForLong(sql); + // ruleid:spring-sqli + jdbcTemplate.queryForLong(sql, new Object[0]); + // ruleid:spring-sqli + jdbcTemplate.queryForLong(sql, new Object[0], new int[]{Types.VARCHAR}); + }*/ + +} + +class SpringBatchUpdateUtils { + + JdbcOperations jdbcOperations; + + public void queryBatchUpdateUnsafe(@RequestParam("input") String input) { + String sql = "UPDATE Users SET name = '"+input+"' where id = 1"; + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + BatchUpdateUtils.executeBatchUpdate(sql, new ArrayList(),new int[] {Types.INTEGER}, jdbcOperations); + } + // {/fact} + + + public void queryBatchUpdateSafe() { + String sql = "UPDATE Users SET name = 'safe' where id = 1"; + + // {fact rule=sql-injection@v1.0 defects=0} + // ok:spring-sqli + BatchUpdateUtils.executeBatchUpdate(sql, new ArrayList(),new int[] {Types.INTEGER}, jdbcOperations); + } + // {/fact} + + + public void queryNamedParamBatchUpdateUnsafe(@RequestParam("input") String input) { + String sql = "UPDATE Users SET name = '"+input+"' where id = 1"; + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:spring-sqli + NamedParameterBatchUpdateUtils.executeBatchUpdate(sql, new ArrayList(),new int[] {Types.INTEGER}, jdbcOperations); + } + // {/fact} + + + public void queryNamedParameterBatchUpdateUtilsSafe() { + String sql = "UPDATE Users SET name = 'safe' where id = 1"; + + // {fact rule=sql-injection@v1.0 defects=0} + // ok:spring-sqli + NamedParameterBatchUpdateUtils.executeBatchUpdate(sql, new ArrayList(), new int[]{Types.INTEGER}, jdbcOperations); + } + // {/fact} + +} + + +class Test { + @GetMapping + public void drive(@RequestParam("input") String userInput) { + // Spring SQL Injection + SpringPreparedStatementCreatorFactory factory = new SpringPreparedStatementCreatorFactory(); + factory.queryUnsafe(userInput); + new SpringJdbcTemplate().query1(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().query2(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().query3(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().query4(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().querySafe(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().queryExecute(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().queryBatchUpdate(new JdbcTemplate(), userInput, userInput); + new SpringJdbcTemplate().queryForObject(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().querySamples(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().queryForList(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().queryForMap(new JdbcTemplate(), userInput); + new SpringJdbcTemplate().queryForRowSet(new JdbcTemplate(), userInput); + new SpringBatchUpdateUtils().queryBatchUpdateUnsafe(userInput); + new SpringBatchUpdateUtils().queryBatchUpdateSafe(); + new SpringBatchUpdateUtils().queryNamedParamBatchUpdateUnsafe(userInput); + new SpringBatchUpdateUtils().queryNamedParameterBatchUpdateUtilsSafe(); + + } +} diff --git a/PR_5_java/java/filtered_java/14_tainted_system_command.java b/PR_5_java/java/filtered_java/14_tainted_system_command.java new file mode 100644 index 0000000..a940ec9 --- /dev/null +++ b/PR_5_java/java/filtered_java/14_tainted_system_command.java @@ -0,0 +1,245 @@ +package spring.security.injection; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.function.Supplier; +import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; +import org.sasanlabs.internal.utility.LevelConstants; +import org.sasanlabs.internal.utility.Variant; +import org.sasanlabs.internal.utility.annotations.AttackVector; +import org.sasanlabs.internal.utility.annotations.VulnerableAppRequestMapping; +import org.sasanlabs.internal.utility.annotations.VulnerableAppRestController; +import org.sasanlabs.service.exception.ServiceApplicationException; +import org.sasanlabs.service.vulnerability.bean.GenericVulnerabilityResponseBean; +import org.sasanlabs.vulnerability.types.VulnerabilityType; +import org.springframework.http.HttpStatus; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * This class contains vulnerabilities related to Command Injection. For More information + * + * @author KSASAN preetkaran20@gmail.com + */ +@VulnerableAppRestController( + descriptionLabel = "COMMAND_INJECTION_VULNERABILITY", + value = "CommandInjection") +class CommandInjection { + + private static final String IP_ADDRESS = "ipaddress"; + private static final Pattern SEMICOLON_SPACE_LOGICAL_AND_PATTERN = Pattern.compile("[;& ]"); + private static final Pattern IP_ADDRESS_PATTERN = + Pattern.compile("\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4}\\b"); + + StringBuilder getResponseFromPingCommand(String ipAddress, boolean isValid) throws IOException { + boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); + StringBuilder stringBuilder = new StringBuilder(); + if (isValid) { + Process process; + if (!isWindows) { + process = + +// {fact rule=os-command-injection@v1.0 defects=1} + +// deepruleid: tainted-system-command + new ProcessBuilder(new String[] {"sh", "-c", "ping -c 2 " + ipAddress}) + .redirectErrorStream(true) + .start(); + } else { + process = + +// {/fact} + + +// {fact rule=os-command-injection@v1.0 defects=1} + +// deepruleid: tainted-system-command + new ProcessBuilder(new String[] {"cmd", "/c", "ping -n 2 " + ipAddress}) + .redirectErrorStream(true) + .start(); + } + try (BufferedReader bufferedReader = + new BufferedReader(new InputStreamReader(process.getInputStream()))) { + bufferedReader.lines().forEach(val -> stringBuilder.append(val).append("\n")); + } + } + return stringBuilder; + } + + @AttackVector( + vulnerabilityExposed = VulnerabilityType.COMMAND_INJECTION, + description = "COMMAND_INJECTION_URL_PARAM_DIRECTLY_EXECUTED") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_1, htmlTemplate = "LEVEL_1/CI_Level1") + public ResponseEntity> getVulnerablePayloadLevel1( + @RequestParam(IP_ADDRESS) String ipAddress, boolean isValid) throws IOException { + Supplier validator = () -> StringUtils.isNotBlank(ipAddress); + boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); + StringBuilder stringBuilder = new StringBuilder(); + if (isValid) { + Process process; + if (!isWindows) { + process = + +// {/fact} + + +// {fact rule=os-command-injection@v1.0 defects=1} + +// ruleid: tainted-system-command + new ProcessBuilder(new String[] {"sh", "-c", "ping -c 2 " + ipAddress}) + .redirectErrorStream(true) + .start(); + } else { + process = + +// {/fact} + + +// {fact rule=os-command-injection@v1.0 defects=1} + +// ruleid: tainted-system-command + new ProcessBuilder(new String[] {"cmd", "/c", "ping -n 2 " + ipAddress}) + .redirectErrorStream(true) + .start(); + } + try (BufferedReader bufferedReader = + new BufferedReader(new InputStreamReader(process.getInputStream()))) { + bufferedReader.lines().forEach(val -> stringBuilder.append(val).append("\n")); + } + } + return new ResponseEntity>( + new GenericVulnerabilityResponseBean( + stringBuilder.toString(), + true), + HttpStatus.OK); + } + + @AttackVector( + vulnerabilityExposed = VulnerabilityType.COMMAND_INJECTION, + description = + "COMMAND_INJECTION_URL_PARAM_DIRECTLY_EXECUTED_IF_SEMICOLON_SPACE_LOGICAL_AND_NOT_PRESENT") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_2, htmlTemplate = "LEVEL_1/CI_Level1") + public ResponseEntity> getVulnerablePayloadLevel2( + @RequestParam(IP_ADDRESS) String ipAddress, RequestEntity requestEntity) + throws ServiceApplicationException, IOException { + + Supplier validator = + () -> + StringUtils.isNotBlank(ipAddress) + && !SEMICOLON_SPACE_LOGICAL_AND_PATTERN + .matcher(requestEntity.getUrl().toString()) + .find(); + return new ResponseEntity>( + new GenericVulnerabilityResponseBean( + // todoruleid: tainted-system-command + // Indirection, needs interproc taint + this.getResponseFromPingCommand(ipAddress, validator.get()).toString(), + true), + HttpStatus.OK); + } + + // Case Insensitive + @AttackVector( + vulnerabilityExposed = VulnerabilityType.COMMAND_INJECTION, + description = + "COMMAND_INJECTION_URL_PARAM_DIRECTLY_EXECUTED_IF_SEMICOLON_SPACE_LOGICAL_AND_%26_%3B_NOT_PRESENT") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_3, htmlTemplate = "LEVEL_1/CI_Level1") + public ResponseEntity> getVulnerablePayloadLevel3( + @RequestParam(IP_ADDRESS) String ipAddress, RequestEntity requestEntity) + throws ServiceApplicationException, IOException { + + Supplier validator = + () -> + StringUtils.isNotBlank(ipAddress) + && !SEMICOLON_SPACE_LOGICAL_AND_PATTERN + .matcher(requestEntity.getUrl().toString()) + .find() + && !requestEntity.getUrl().toString().contains("%26") + && !requestEntity.getUrl().toString().contains("%3B"); + return new ResponseEntity>( + new GenericVulnerabilityResponseBean( + this.getResponseFromPingCommand(ipAddress, validator.get()).toString(), + true), + HttpStatus.OK); + } + + // e.g Attack + // http://localhost:9090/vulnerable/CommandInjectionVulnerability/LEVEL_3?ipaddress=192.168.0.1%20%7c%20cat%20/etc/passwd + @AttackVector( + vulnerabilityExposed = VulnerabilityType.COMMAND_INJECTION, + description = + "COMMAND_INJECTION_URL_PARAM_DIRECTLY_EXECUTED_IF_SEMICOLON_SPACE_LOGICAL_AND_%26_%3B_CASE_INSENSITIVE_NOT_PRESENT") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_4, htmlTemplate = "LEVEL_1/CI_Level1") + public ResponseEntity> getVulnerablePayloadLevel4( + @RequestParam(IP_ADDRESS) String ipAddress, RequestEntity requestEntity) + throws ServiceApplicationException, IOException { + + Supplier validator = + () -> + StringUtils.isNotBlank(ipAddress) + && !SEMICOLON_SPACE_LOGICAL_AND_PATTERN + .matcher(requestEntity.getUrl().toString()) + .find() + && !requestEntity.getUrl().toString().toUpperCase().contains("%26") + && !requestEntity.getUrl().toString().toUpperCase().contains("%3B"); + return new ResponseEntity>( + new GenericVulnerabilityResponseBean( + this.getResponseFromPingCommand(ipAddress, validator.get()).toString(), + true), + HttpStatus.OK); + } + // Payload: 127.0.0.1%0Als + @AttackVector( + vulnerabilityExposed = VulnerabilityType.COMMAND_INJECTION, + description = + "COMMAND_INJECTION_URL_PARAM_DIRECTLY_EXECUTED_IF_SEMICOLON_SPACE_LOGICAL_AND_%26_%3B_%7C_CASE_INSENSITIVE_NOT_PRESENT") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_5, htmlTemplate = "LEVEL_1/CI_Level1") + public ResponseEntity> getVulnerablePayloadLevel5( + @RequestParam(IP_ADDRESS) String ipAddress, RequestEntity requestEntity) + throws IOException { + Supplier validator = + () -> + StringUtils.isNotBlank(ipAddress) + && !SEMICOLON_SPACE_LOGICAL_AND_PATTERN + .matcher(requestEntity.getUrl().toString()) + .find() + && !requestEntity.getUrl().toString().toUpperCase().contains("%26") + && !requestEntity.getUrl().toString().toUpperCase().contains("%3B") + & !requestEntity + .getUrl() + .toString() + .toUpperCase() + .contains("%7C"); + return new ResponseEntity>( + new GenericVulnerabilityResponseBean( + this.getResponseFromPingCommand(ipAddress, validator.get()).toString(), + true), + HttpStatus.OK); + } + + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_6, + htmlTemplate = "LEVEL_1/CI_Level1", + variant = Variant.SECURE) + public ResponseEntity> getVulnerablePayloadLevel6( + @RequestParam(IP_ADDRESS) String ipAddress) throws IOException { + Supplier validator = + () -> + StringUtils.isNotBlank(ipAddress) + && (IP_ADDRESS_PATTERN.matcher(ipAddress).matches() + || ipAddress.contentEquals("localhost")); + + return new ResponseEntity>( + new GenericVulnerabilityResponseBean( + this.getResponseFromPingCommand(ipAddress, validator.get()).toString(), + true), + HttpStatus.OK); + } +} +// {/fact} + + diff --git a/PR_5_java/java/filtered_java/15_weak_random.java b/PR_5_java/java/filtered_java/15_weak_random.java new file mode 100644 index 0000000..1f6d44b --- /dev/null +++ b/PR_5_java/java/filtered_java/15_weak_random.java @@ -0,0 +1,220 @@ +/** + * OWASP Benchmark v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Dave Wichers + * @created 2015 + */ +package lang.security.audit.crypto; + +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 = "/weakrand-00/BenchmarkTest00023") +class BenchmarkTest00023 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 = request.getParameter("BenchmarkTest00023"); + if (param == null) param = ""; + + // ruleid: weak-random + float rand = new java.util.Random().nextFloat(); + + // ruleid: weak-random + new java.util.Random().nextInt(); + String rememberMeKey = Float.toString(rand).substring(2); // Trim off the 0. at the front. + + String user = "Floyd"; + String fullClassName = this.getClass().getName(); + String testCaseNumber = + fullClassName.substring( + fullClassName.lastIndexOf('.') + 1 + "BenchmarkTest".length()); + user += testCaseNumber; + + String cookieName = "rememberMe" + testCaseNumber; + + boolean foundUser = false; + javax.servlet.http.Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (int i = 0; !foundUser && i < cookies.length; i++) { + javax.servlet.http.Cookie cookie = cookies[i]; + if (cookieName.equals(cookie.getName())) { + if (cookie.getValue().equals(request.getSession().getAttribute(cookieName))) { + foundUser = true; + } + } + } + } + + if (foundUser) { + response.getWriter().println("Welcome back: " + user + "
"); + } else { + javax.servlet.http.Cookie rememberMe = + new javax.servlet.http.Cookie(cookieName, rememberMeKey); + rememberMe.setSecure(true); + rememberMe.setHttpOnly(true); + rememberMe.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost()); + rememberMe.setPath(request.getRequestURI()); // i.e., set path to JUST this servlet + // e.g., /benchmark/sql-01/BenchmarkTest01001 + request.getSession().setAttribute(cookieName, rememberMeKey); + response.addCookie(rememberMe); + response.getWriter() + .println( + user + + " has been remembered with cookie: " + + rememberMe.getName() + + " whose value is: " + + rememberMe.getValue() + + "
"); + } + + response.getWriter().println("Weak Randomness Test java.util.Random.nextFloat() executed"); + } +} + +/** + * OWASP Benchmark Project v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Nick Sanidas + * @created 2015 + */ +@WebServlet(value = "/weakrand-00/BenchmarkTest00066") +class BenchmarkTest00066 extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + javax.servlet.http.Cookie userCookie = + new javax.servlet.http.Cookie("BenchmarkTest00066", "anything"); + userCookie.setMaxAge(60 * 3); // Store cookie for 3 minutes + userCookie.setSecure(true); + userCookie.setPath(request.getRequestURI()); + userCookie.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost()); + response.addCookie(userCookie); + javax.servlet.RequestDispatcher rd = + request.getRequestDispatcher("/weakrand-00/BenchmarkTest00066.html"); + rd.include(request, response); + } + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + + javax.servlet.http.Cookie[] theCookies = request.getCookies(); + + String param = "noCookieValueSupplied"; + if (theCookies != null) { + for (javax.servlet.http.Cookie theCookie : theCookies) { + if (theCookie.getName().equals("BenchmarkTest00066")) { + param = java.net.URLDecoder.decode(theCookie.getValue(), "UTF-8"); + break; + } + } + } + + String bar; + + // Simple if statement that assigns constant to bar on true condition + int num = 86; + if ((7 * 42) - num > 200) bar = "This_should_always_happen"; + else bar = param; + + // ruleid: weak-random + double value = Math.random(); + + // ok: weak-random + + // Dependencies not resolved here. + // double value2 = java.security.SecureRandom(); + String rememberMeKey = Double.toString(value).substring(2); // Trim off the 0. at the front. + + String user = "Doug"; + String fullClassName = this.getClass().getName(); + String testCaseNumber = + fullClassName.substring( + fullClassName.lastIndexOf('.') + 1 + "BenchmarkTest".length()); + user += testCaseNumber; + + String cookieName = "rememberMe" + testCaseNumber; + + boolean foundUser = false; + javax.servlet.http.Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (int i = 0; !foundUser && i < cookies.length; i++) { + javax.servlet.http.Cookie cookie = cookies[i]; + if (cookieName.equals(cookie.getName())) { + if (cookie.getValue().equals(request.getSession().getAttribute(cookieName))) { + foundUser = true; + } + } + } + } + + if (foundUser) { + response.getWriter().println("Welcome back: " + user + "
"); + + } else { + javax.servlet.http.Cookie rememberMe = + new javax.servlet.http.Cookie(cookieName, rememberMeKey); + rememberMe.setSecure(true); + rememberMe.setHttpOnly(true); + rememberMe.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost()); + rememberMe.setPath(request.getRequestURI()); // i.e., set path to JUST this servlet + // e.g., /benchmark/sql-01/BenchmarkTest01001 + request.getSession().setAttribute(cookieName, rememberMeKey); + response.addCookie(rememberMe); + response.getWriter() + .println( + user + + " has been remembered with cookie: " + + rememberMe.getName() + + " whose value is: " + + rememberMe.getValue() + + "
"); + } + response.getWriter().println("Weak Randomness Test java.lang.Math.random() executed"); + } +} + diff --git a/PR_5_java/java/filtered_java/16_tainted_url_host.java b/PR_5_java/java/filtered_java/16_tainted_url_host.java new file mode 100644 index 0000000..aa70d07 --- /dev/null +++ b/PR_5_java/java/filtered_java/16_tainted_url_host.java @@ -0,0 +1,104 @@ +package spring.security.injection; + +import com.nimbusds.jose.util.StandardCharset; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.sasanlabs.internal.utility.LevelConstants; +import org.sasanlabs.internal.utility.annotations.AttackVector; +import org.sasanlabs.internal.utility.annotations.VulnerableAppRequestMapping; +import org.sasanlabs.internal.utility.annotations.VulnerableAppRestController; +import org.sasanlabs.service.vulnerability.bean.GenericVulnerabilityResponseBean; +import org.sasanlabs.vulnerability.types.VulnerabilityType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.*; +import org.springframework.util.StreamUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.RestTemplate; + + +@VulnerableAppRestController(descriptionLabel = "SSRF_VULNERABILITY", value = "SSRFVulnerability") +class SSRFVulnerability { + + private static final String IMAGE_URL = "imageurl"; + private static final transient Logger LOGGER = LogManager.getLogger(SSRFVulnerability.class); + + @AttackVector( + vulnerabilityExposed = VulnerabilityType.SIMPLE_SSRF, + description = "IMAGE_URL_PASSED_TO_REQUEST") + @VulnerableAppRequestMapping(value = LevelConstants.LEVEL_1, htmlTemplate = "LEVEL_1/SSRF") + public ResponseEntity> getVulnerablePayloadLevel1( + @RequestParam(IMAGE_URL) String urlImage) { + try { + +// {fact rule=server-side-request-forgery@v1.0 defects=1} + +// ruleid: tainted-url-host + URL u = new URL(urlImage); + URLConnection urlConnection = u.openConnection(); + byte[] bytes; + try (InputStream in = urlConnection.getInputStream()) { + bytes = StreamUtils.copyToByteArray(urlConnection.getInputStream()); + } + return new ResponseEntity<>( + new GenericVulnerabilityResponseBean<>(bytes, true), HttpStatus.OK); + } catch (Exception e) { + LOGGER.error( + "Following exception occurred while opening the connection to {}", urlImage, e); + } + return new ResponseEntity<>( + new GenericVulnerabilityResponseBean<>( + ("Failed to fetch image from URL " + urlImage) + .getBytes(StandardCharset.UTF_8), + false), + HttpStatus.BAD_REQUEST); + } +} + +// {/fact} + + + +@RestController +@RequestMapping("/user03") +class User03Controller { + + @Autowired + private RestTemplate restTemplate; + + @GetMapping("/get") + public UserDTO get(@RequestParam("id") Integer id) { + +// {fact rule=server-side-request-forgery@v1.0 defects=0} + +// ok: tainted-url-host + String url = String.format("http://%s/user/get?id=%d", "demo-provider", id); + return restTemplate.getForObject(url, UserDTO.class); + } + +// {/fact} + + + + /** + * Not finding a proper dependency for JSON + */ + /* @PostMapping("/add") + public Integer add(UserAddDTO addDTO) { + // 请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + // 请求体 + String body = JSON.toJSONString(addDTO); + // 创建 HttpEntity 对象 + HttpEntity entity = new HttpEntity<>(body, headers); + // 执行请求 + // ok: tainted-url-host + String url = String.format("http://%s/user/add", "demo-provider"); + return restTemplate.postForObject(url, entity, Integer.class); + }*/ + +} + diff --git a/PR_5_java/java/filtered_java/17_session_sqli.java b/PR_5_java/java/filtered_java/17_session_sqli.java new file mode 100644 index 0000000..9e9b4d7 --- /dev/null +++ b/PR_5_java/java/filtered_java/17_session_sqli.java @@ -0,0 +1,77 @@ +// package jboss.security; + +// import java.io.File; +// import java.io.IOException; +// import java.io.PrintWriter; + +// import javax.servlet.ServletException; +// import javax.servlet.http.HttpServlet; +// import javax.servlet.http.HttpServletRequest; +// import javax.servlet.http.HttpServletResponse; +// import javax.servlet.http.HttpSession; + +// import org.apache.commons.io.FilenameUtils; + +// class Cls extends HttpServlet +// { +// private static org.apache.log4j.Logger log = Logger.getLogger(Register.class); + +// // {ex-fact rule=sql-injection@v1.0 defects=1} +// // ruleid:find-sql-string-concatenation +// protected void danger(String ean) { +// Session session = this.sessionFactory.openSession(); + +// String query = "select foo from bar where" + ean + " limit 1"; +// try { +// PreparedStatement ps = session.connection().prepareStatement(query); +// ResultSet rs = ps.executeQuery(); +// while (rs.next()) { +// Integer item = rs.getInt("foo"); +// } +// } catch (SQLException e) { +// logger.error("Error!", e); +// } finally { +// session.close(); +// } +// } +// // {/ex-fact} + +// // {ex-fact rule=sql-injection@v1.0 defects=1} +// // ruleid:find-sql-string-concatenation +// protected void danger2(String biz) { +// String query = "select foo from bar where" + biz + " limit 1"; +// Session session = this.sessionFactory.openSession(); +// try { +// PreparedStatement ps = session.connection().prepareStatement(query); +// ResultSet rs = ps.executeQuery(); +// while (rs.next()) { +// Integer item = rs.getInt("foo"); +// } +// } catch (SQLException e) { +// logger.error("Error!", e); +// } finally { +// session.close(); +// } +// } +// // {/ex-fact} + +// // {ex-fact rule=sql-injection@v1.0 defects=0} +// // ok:find-sql-string-concatenation +// protected void ok(String foo) throws ServletException, IOException { +// String query = "select foo from bar where ? limit 1"; +// Session session = this.sessionFactory.openSession(); +// try { +// PreparedStatement ps = session.connection().prepareStatement(query); +// ps.setString(1,foo); +// ResultSet rs = ps.executeQuery(); +// while (rs.next()) { +// return rs.getInt("foo"); +// } +// } catch (SQLException e) { +// logger.error("Error!", e); +// } finally { +// session.close(); +// } +// } +// // {/ex-fact} +// } diff --git a/PR_5_java/java/filtered_java/18_UnrestrictedFileUpload.java b/PR_5_java/java/filtered_java/18_UnrestrictedFileUpload.java new file mode 100644 index 0000000..12641f5 --- /dev/null +++ b/PR_5_java/java/filtered_java/18_UnrestrictedFileUpload.java @@ -0,0 +1,382 @@ +package org.sasanlabs.service.vulnerability.fileupload; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.FileSystemException; +import java.nio.file.FileSystemNotFoundException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Date; +import java.util.Random; +import java.util.function.Supplier; +import java.util.regex.Pattern; +import org.apache.commons.text.StringEscapeUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.sasanlabs.internal.utility.FrameworkConstants; +import org.sasanlabs.internal.utility.LevelConstants; +import org.sasanlabs.internal.utility.Variant; +import org.sasanlabs.internal.utility.annotations.AttackVector; +import org.sasanlabs.internal.utility.annotations.VulnerableAppRequestMapping; +import org.sasanlabs.internal.utility.annotations.VulnerableAppRestController; +import org.sasanlabs.service.exception.ServiceApplicationException; +import org.sasanlabs.service.vulnerability.bean.GenericVulnerabilityResponseBean; +import org.sasanlabs.vulnerability.types.VulnerabilityType; +import org.sasanlabs.vulnerability.utils.Constants; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author KSASAN preetkaran20@gmail.com + *

Special Thanks + *

https://bezkoder.com/spring-boot-file-upload/ + *

https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects + *

https://www.youtube.com/watch?v=CmF9sEyKZNo + */ +@VulnerableAppRestController( + descriptionLabel = "UNRESTRICTED_FILE_UPLOAD_VULNERABILITY", + value = "UnrestrictedFileUpload") +public class UnrestrictedFileUpload { + private Path root; + private Path contentDispositionRoot; + + private static final String STATIC_FILE_LOCATION = "upload"; + public static final String CONTENT_DISPOSITION_STATIC_FILE_LOCATION = "contentDispositionUpload"; + private static final String BASE_PATH = "static"; + private static final String REQUEST_PARAMETER = "file"; + private static final Random RANDOM = new Random(new Date().getTime()); + private static final Pattern ENDS_WITH_HTML_PATTERN = Pattern.compile("^.+\\.html$"); + private static final Pattern ENDS_WITH_HTML_OR_HTM_PATTERN = + Pattern.compile("^.+\\.(html|htm)$"); + + private static final String CONTAINS_PNG_JPEG_REGEX = "^.+\\.(png|jpeg)"; + private static final Pattern CONTAINS_PNG_OR_JPEG_PATTERN = + Pattern.compile(CONTAINS_PNG_JPEG_REGEX); + private static final Pattern ENDS_WITH_PNG_OR_JPEG_PATTERN = + Pattern.compile(CONTAINS_PNG_JPEG_REGEX + "$"); + private static final transient Logger LOGGER = + LogManager.getLogger(UnrestrictedFileUpload.class); + + public UnrestrictedFileUpload() throws IOException, URISyntaxException { + URI uploadDirectoryURI; + try { + uploadDirectoryURI = + new URI( + Thread.currentThread() + .getContextClassLoader() + .getResource(BASE_PATH) + .toURI() + + FrameworkConstants.SLASH + + STATIC_FILE_LOCATION); + root = Paths.get(uploadDirectoryURI); + if (!root.toFile().exists()) { + Files.createDirectory(root); + } + contentDispositionRoot = + Paths.get( + FrameworkConstants.SLASH + + CONTENT_DISPOSITION_STATIC_FILE_LOCATION + + FrameworkConstants.SLASH); + if (!contentDispositionRoot.toFile().exists()) { + Files.createDirectory(contentDispositionRoot); + } + } catch (FileSystemNotFoundException | FileSystemException e) { + // Temporary Fix, FileUpload is not working in jar. + LOGGER.error( + "If you are running vulnerableApp as a Jar then UnrestrictedFileUpload will not work. " + + "For more information: https://github.com/SasanLabs/VulnerableApp/issues/255", + e); + if (root != null) { + root = Files.createTempDirectory(null); + } + if (contentDispositionRoot != null) { + contentDispositionRoot = Files.createTempDirectory(null); + } + } + } + + private static final ResponseEntity> + genericFileUploadUtility( + Path root, + String fileName, + Supplier validator, + MultipartFile file, + boolean htmlEncode, + boolean isContentDisposition) + throws IOException { + if (validator.get()) { + Files.copy( + file.getInputStream(), + root.resolve(fileName), + StandardCopyOption.REPLACE_EXISTING); + String uploadedFileLocation; + if (htmlEncode) { + uploadedFileLocation = + StringEscapeUtils.escapeHtml4( + FrameworkConstants.VULNERABLE_APP + + FrameworkConstants.SLASH + + (isContentDisposition + ? CONTENT_DISPOSITION_STATIC_FILE_LOCATION + : STATIC_FILE_LOCATION) + + FrameworkConstants.SLASH + + fileName); + } else { + uploadedFileLocation = + FrameworkConstants.VULNERABLE_APP + + FrameworkConstants.SLASH + + (isContentDisposition + ? CONTENT_DISPOSITION_STATIC_FILE_LOCATION + : STATIC_FILE_LOCATION) + + FrameworkConstants.SLASH + + fileName; + } + return new ResponseEntity>( + new GenericVulnerabilityResponseBean(uploadedFileLocation, true), + HttpStatus.OK); + } + return new ResponseEntity>( + new GenericVulnerabilityResponseBean("Input is invalid", false), + HttpStatus.OK); + } + + public Path getContentDispositionRoot() { + return contentDispositionRoot; + } + + // file name reflected and stored is there. + @AttackVector( + vulnerabilityExposed = { + VulnerabilityType.UNRESTRICTED_FILE_UPLOAD, + VulnerabilityType.PERSISTENT_XSS, + VulnerabilityType.REFLECTED_XSS, + VulnerabilityType.PATH_TRAVERSAL + }, + description = "UNRESTRICTED_FILE_UPLOAD_NO_VALIDATION_FILE_NAME", + payload = "UNRESTRICTED_FILE_UPLOAD_PAYLOAD_LEVEL_1") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_1, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel1( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException, URISyntaxException { + return genericFileUploadUtility( + root, file.getOriginalFilename(), () -> true, file, false, false); + } + + // file name reflected and stored is there. + @AttackVector( + vulnerabilityExposed = { + VulnerabilityType.UNRESTRICTED_FILE_UPLOAD, + VulnerabilityType.PERSISTENT_XSS, + VulnerabilityType.REFLECTED_XSS + }, + description = "UNRESTRICTED_FILE_UPLOAD_NO_VALIDATION_FILE_NAME", + payload = "UNRESTRICTED_FILE_UPLOAD_PAYLOAD_LEVEL_2") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_2, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel2( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException { + String fileName = RANDOM.nextInt() + "_" + file.getOriginalFilename(); + return genericFileUploadUtility(root, fileName, () -> true, file, false, false); + } + + // .htm extension breaks the file upload vulnerability + @AttackVector( + vulnerabilityExposed = { + VulnerabilityType.UNRESTRICTED_FILE_UPLOAD, + VulnerabilityType.PERSISTENT_XSS, + VulnerabilityType.REFLECTED_XSS + }, + description = "UNRESTRICTED_FILE_UPLOAD_IF_NOT_HTML_FILE_EXTENSION", + payload = "UNRESTRICTED_FILE_UPLOAD_PAYLOAD_LEVEL_3") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_3, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel3( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException { + Supplier validator = + () -> !ENDS_WITH_HTML_PATTERN.matcher(file.getOriginalFilename()).matches(); + return genericFileUploadUtility( + root, + RANDOM.nextInt() + "_" + file.getOriginalFilename(), + validator, + file, + false, + false); + } + + @AttackVector( + vulnerabilityExposed = { + VulnerabilityType.UNRESTRICTED_FILE_UPLOAD, + VulnerabilityType.PERSISTENT_XSS, + VulnerabilityType.REFLECTED_XSS + }, + description = "UNRESTRICTED_FILE_UPLOAD_IF_NOT_HTML_NOT_HTM_FILE_EXTENSION", + payload = "UNRESTRICTED_FILE_UPLOAD_PAYLOAD_LEVEL_4") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_4, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel4( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException { + Supplier validator = + () -> !ENDS_WITH_HTML_OR_HTM_PATTERN.matcher(file.getOriginalFilename()).matches(); + return genericFileUploadUtility( + root, + RANDOM.nextInt() + "_" + file.getOriginalFilename(), + validator, + file, + false, + false); + } + + @AttackVector( + vulnerabilityExposed = { + VulnerabilityType.UNRESTRICTED_FILE_UPLOAD, + VulnerabilityType.PERSISTENT_XSS, + VulnerabilityType.REFLECTED_XSS + }, + description = + "UNRESTRICTED_FILE_UPLOAD_IF_NOT_HTML_NOT_HTM_FILE_EXTENSION_CASE_INSENSITIVE", + payload = "UNRESTRICTED_FILE_UPLOAD_PAYLOAD_LEVEL_5") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_5, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel5( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException { + Supplier validator = + () -> + !ENDS_WITH_HTML_OR_HTM_PATTERN + .matcher(file.getOriginalFilename().toLowerCase()) + .matches(); + return genericFileUploadUtility( + root, + RANDOM.nextInt() + "_" + file.getOriginalFilename(), + validator, + file, + false, + false); + } + + // WhiteList approach + @AttackVector( + vulnerabilityExposed = { + VulnerabilityType.UNRESTRICTED_FILE_UPLOAD, + VulnerabilityType.PERSISTENT_XSS, + VulnerabilityType.REFLECTED_XSS + }, + description = + "UNRESTRICTED_FILE_UPLOAD_IF_FILE_NAME_NOT_CONTAINS_.PNG_OR_.JPEG_CASE_INSENSITIVE", + payload = "UNRESTRICTED_FILE_UPLOAD_PAYLOAD_LEVEL_6") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_6, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel6( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException { + + Supplier validator = + () -> CONTAINS_PNG_OR_JPEG_PATTERN.matcher(file.getOriginalFilename()).find(); + return genericFileUploadUtility( + root, + RANDOM.nextInt() + "_" + file.getOriginalFilename(), + validator, + file, + false, + false); + } + + // Null Byte Attack + @AttackVector( + vulnerabilityExposed = { + VulnerabilityType.UNRESTRICTED_FILE_UPLOAD, + VulnerabilityType.PERSISTENT_XSS, + VulnerabilityType.REFLECTED_XSS + }, + description = + "UNRESTRICTED_FILE_UPLOAD_IF_FILE_NAME_NOT_ENDS_WITH_.PNG_OR_.JPEG_CASE_INSENSITIVE_AND_FILE_NAMES_CONSIDERED_BEFORE_NULL_BYTE", + payload = "UNRESTRICTED_FILE_UPLOAD_PAYLOAD_LEVEL_7") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_7, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel7( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException { + String originalFileName; + if (file.getOriginalFilename().contains(Constants.NULL_BYTE_CHARACTER)) { + originalFileName = + file.getOriginalFilename() + .substring( + 0, + file.getOriginalFilename() + .indexOf(Constants.NULL_BYTE_CHARACTER)); + } else { + originalFileName = file.getOriginalFilename(); + } + Supplier validator = + () -> ENDS_WITH_PNG_OR_JPEG_PATTERN.matcher(file.getOriginalFilename()).matches(); + return genericFileUploadUtility( + root, RANDOM.nextInt() + "_" + originalFileName, validator, file, false, false); + } + + @AttackVector( + vulnerabilityExposed = {VulnerabilityType.PATH_TRAVERSAL}, + description = "UNRESTRICTED_FILE_UPLOAD_NO_VALIDATION_FILE_NAME", + payload = "UNRESTRICTED_FILE_UPLOAD_PAYLOAD_LEVEL_8") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_8, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel9( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException { + return genericFileUploadUtility( + contentDispositionRoot, file.getOriginalFilename(), () -> true, file, true, true); + } + + // I think below vulnerability is not exploitable. Need to check again after running Owasp + // ZAP FileUpload Addon. + @AttackVector( + vulnerabilityExposed = { + VulnerabilityType.UNRESTRICTED_FILE_UPLOAD, + VulnerabilityType.PERSISTENT_XSS + }, + description = + "UNRESTRICTED_FILE_UPLOAD_IF_FILE_NAME_NOT_ENDS_WITH_.PNG_OR_.JPEG_CASE_INSENSITIVE") + @VulnerableAppRequestMapping( + value = LevelConstants.LEVEL_9, + variant = Variant.SECURE, + htmlTemplate = "LEVEL_1/FileUpload", + requestMethod = RequestMethod.POST) + public ResponseEntity> getVulnerablePayloadLevel8( + @RequestParam(REQUEST_PARAMETER) MultipartFile file) + throws ServiceApplicationException, IOException { + String fileName = file.getOriginalFilename(); + Supplier validator = + () -> ENDS_WITH_PNG_OR_JPEG_PATTERN.matcher(fileName).matches(); + return genericFileUploadUtility( + root, + RANDOM.nextInt() + "_" + file.getOriginalFilename(), + validator, + file, + true, + false); + } +} \ No newline at end of file diff --git a/PR_5_java/java/filtered_java/19_httpservlet_path_traversal.java b/PR_5_java/java/filtered_java/19_httpservlet_path_traversal.java new file mode 100644 index 0000000..00c29c7 --- /dev/null +++ b/PR_5_java/java/filtered_java/19_httpservlet_path_traversal.java @@ -0,0 +1,122 @@ +package lang.security; + +import java.io.File; +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; + +import jboss.security.Register; +import org.apache.commons.io.FilenameUtils; +import org.apache.log4j.Logger; + + class Cls extends HttpServlet +{ + private static Logger log = Logger.getLogger(Register.class); + + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + String image = request.getParameter("image"); + // {fact rule=path-traversal@v1.0 defects=1} + // ruleid:httpservlet-path-traversal + File file = new File("static/images/", image); + + if (!file.exists()) { + log.info(image + " could not be created."); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + + response.sendRedirect("/index.html"); + } + // {/fact} + + public void ok(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + // {fact rule=path-traversal@v1.0 defects=0} + // ok:httpservlet-path-traversal + String image = request.getParameter("image"); + File file = new File("static/images/", FilenameUtils.getName(image)); + + if (!file.exists()) { + log.info(image + " could not be created."); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + + response.sendRedirect("/index.html"); + } + // {/fact} +} + +/** + * OWASP Benchmark v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Dave Wichers + * @created 2015 + */ + + + +@WebServlet(value = "/pathtraver-00/BenchmarkTest00045") +class BenchmarkTest00045 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[] values = request.getParameterValues("BenchmarkTest00045"); + String param; + if (values != null && values.length > 0) param = values[0]; + else param = ""; + + String fileName = org.owasp.benchmark.helpers.Utils.TESTFILES_DIR + param; + + try ( + // Create the file first so the test won't throw an exception if it doesn't exist. + // Note: Don't actually do this because this method signature could cause a tool to find + // THIS file constructor + // as a vuln, rather than the File signature we are trying to actually test. + // If necessary, just run the benchmark twice. The 1st run should create all the necessary + // files. + // new java.io.File(org.owasp.benchmark.helpers.Utils.TESTFILES_DIR + + // param).createNewFile(); + + // {fact rule=path-traversal@v1.0 defects=1} + // ruleid: httpservlet-path-traversal + java.io.FileOutputStream fos = new java.io.FileOutputStream(new java.io.FileInputStream(fileName).getFD()); ) { + response.getWriter() + .println( + "Now ready to write to file: " + + org.owasp.esapi.ESAPI.encoder().encodeForHTML(fileName)); + + } catch (Exception e) { + System.out.println("Couldn't open FileOutputStream on file: '" + fileName + "'"); + } + // {/fact} + } +} diff --git a/PR_5_java/java/filtered_java/20_crlf_injection_logs.java b/PR_5_java/java/filtered_java/20_crlf_injection_logs.java new file mode 100644 index 0000000..b8f606a --- /dev/null +++ b/PR_5_java/java/filtered_java/20_crlf_injection_logs.java @@ -0,0 +1,102 @@ +package lang.security.audit; + +import java.io.IOException; +import java.util.logging.Logger; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +class TestLog1 { + private final static Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // {fact rule=log-injection@v1.0 defects=1} + // ruleid: crlf-injection-logs + String param = request.getParameter("param"); + log.info("foo"+param+"bar"); + response.getWriter().append("Served at: ").append(request.getContextPath()); + } + // {/fact} +} + +class TestLog2 { + private final static Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + // {fact rule=log-injection@v1.0 defects=1} + // ruleid: crlf-injection-logs + String param = request.getParameter("param"); + log.log(log.getLevel(), "foo"+param); + } + // {/fact} +} + +class TestLog3 { + private final static Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // {fact rule=log-injection@v1.0 defects=1} + // ruleid: crlf-injection-logs + log.info("foo"+request.getParameter("param")); + response.getWriter().append("Served at: ").append(request.getContextPath()); + } + // {/fact} +} + +class TestLog4 { + private final static Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + HttpServletRequest httpServletReq = (HttpServletRequest) request; + // {fact rule=log-injection@v1.0 defects=1} + // ruleid: crlf-injection-logs + String param = httpServletReq.getParameter("param"); + log.log(log.getLevel(), param); + } +} + +class TestLog5 { + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + HttpServletRequest httpServletReq = (HttpServletRequest) request; + // {fact rule=log-injection@v1.0 defects=1} + // ruleid: crlf-injection-logs + String param = httpServletReq.getParameter("foo"); + log.log(log.getLevel(), param+"bar"); + } +} + +/*public class OkTestLog1 { + private final static NotLogger log = new NorLogger(); + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + HttpServletRequest httpServletReq = (HttpServletRequest) request; + // ok: crlf-injection-logs + String param = httpServletReq.getParameter("param"); + log.info(param); + } +}*/ + +class OkTestLog2 { + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + HttpServletRequest httpServletReq = (HttpServletRequest) request; + // {fact rule=log-injection@v1.0 defects=0} + // ok: crlf-injection-logs + String param = "foobar"; + log.log(log.getLevel(), param); + } + // {/fact} +} diff --git a/PR_5_java/java/filtered_java/21_overly_permissive_file_permission.java b/PR_5_java/java/filtered_java/21_overly_permissive_file_permission.java new file mode 100644 index 0000000..d3c5122 --- /dev/null +++ b/PR_5_java/java/filtered_java/21_overly_permissive_file_permission.java @@ -0,0 +1,49 @@ +package lang.security.audit; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.HashSet; +import java.util.Set; + + class FileApi { + + public static void notOk() throws IOException { + // {fact rule=insecure-file-permissions@v1.0 defects=1} + // ruleid:overly-permissive-file-permission + Files.setPosixFilePermissions(Paths.get("/var/opt/app/init_script.sh"), PosixFilePermissions.fromString("rw-rw-rw-")); + + // ruleid:overly-permissive-file-permission + Files.setPosixFilePermissions(Paths.get("/var/opt/configuration.xml"), PosixFilePermissions.fromString("rw-rw-r--")); + } + // {/fact} + + public static void notOk2() throws IOException { + Set perms = new HashSet<>(); + perms.add(PosixFilePermission.OWNER_READ); + perms.add(PosixFilePermission.OWNER_WRITE); + perms.add(PosixFilePermission.OWNER_EXECUTE); + + perms.add(PosixFilePermission.GROUP_READ); + perms.add(PosixFilePermission.GROUP_WRITE); + perms.add(PosixFilePermission.GROUP_EXECUTE); + + // {fact rule=insecure-file-permissions@v1.0 defects=1} + // ruleid:overly-permissive-file-permission + perms.add(PosixFilePermission.OTHERS_READ); + // ruleid:overly-permissive-file-permission + perms.add(PosixFilePermission.OTHERS_WRITE); + // ruleid:overly-permissive-file-permission + perms.add(PosixFilePermission.OTHERS_EXECUTE); + + Files.setPosixFilePermissions(Paths.get("/var/opt/app/init_script.sh"),perms); + } + // {/fact} + + public static void ok() throws IOException { + Files.setPosixFilePermissions(Paths.get("/var/opt/configuration.xml"), PosixFilePermissions.fromString("rw-rw----")); + Files.setPosixFilePermissions(Paths.get("/var/opt/configuration.xml"), PosixFilePermissions.fromString("rwxrwx---")); + } +} diff --git a/PR_5_java/java/filtered_java/22_ldap_injection.java b/PR_5_java/java/filtered_java/22_ldap_injection.java new file mode 100644 index 0000000..7503860 --- /dev/null +++ b/PR_5_java/java/filtered_java/22_ldap_injection.java @@ -0,0 +1,149 @@ +package lang.security.audit; /** + * Dependencies not resolved + */ + +/* +package lang.security.audit; + +import com.sun.jndi.ldap.LdapCtx; +import javax.naming.Context; +import javax.naming.InvalidNameException; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import javax.naming.event.EventDirContext; +import javax.naming.ldap.InitialLdapContext; +import javax.naming.ldap.LdapContext; +import javax.naming.ldap.LdapName; +import java.util.Properties; + +class JndiLdapAdditionalSignature { + + // ruleid: ldap-injection + public static void moreLdapInjections(String input) throws NamingException { + Properties props = new Properties(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.put(Context.PROVIDER_URL, "ldap://ldap.example.com"); + props.put(Context.REFERRAL, "ignore"); + + SearchControls ctrls = new SearchControls(); + ctrls.setReturningAttributes(new String[]{"givenName", "sn"}); + ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + DirContext context1 = new InitialDirContext(props); + + NamingEnumeration answers; + answers = context1.search(new LdapName("dc=People,dc=example,dc=com"), "(uid=" + input + ")", ctrls); + } + + // ruleid: ldap-injection + public static void moreLdapInjections1(String input) throws NamingException { + Properties props = new Properties(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.put(Context.PROVIDER_URL, "ldap://ldap.example.com"); + props.put(Context.REFERRAL, "ignore"); + + SearchControls ctrls = new SearchControls(); + ctrls.setReturningAttributes(new String[]{"givenName", "sn"}); + ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + InitialDirContext context2 = new InitialDirContext(props); + + NamingEnumeration answers; + answers = context2.search(new LdapName("dc=People,dc=example,dc=com"), "(uid=" + input + ")", new Object[0], ctrls); + } + + // ruleid: ldap-injection + public static void moreLdapInjections2(String input) throws NamingException { + Properties props = new Properties(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.put(Context.PROVIDER_URL, "ldap://ldap.example.com"); + props.put(Context.REFERRAL, "ignore"); + + SearchControls ctrls = new SearchControls(); + ctrls.setReturningAttributes(new String[]{"givenName", "sn"}); + ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + InitialLdapContext context3 = new InitialLdapContext(); + LdapContext context4 = new InitialLdapContext(); + + NamingEnumeration answers; + answers = context3.search("dc=People,dc=example,dc=com", "(uid=" + input + ")", ctrls); + } + + // ruleid: ldap-injection + public static void moreLdapInjections3(String input) throws NamingException { + Properties props = new Properties(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.put(Context.PROVIDER_URL, "ldap://ldap.example.com"); + props.put(Context.REFERRAL, "ignore"); + + SearchControls ctrls = new SearchControls(); + ctrls.setReturningAttributes(new String[]{"givenName", "sn"}); + ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + LdapContext context4 = new InitialLdapContext(); + + NamingEnumeration answers; + answers = context4.search("dc=People,dc=example,dc=com", "(uid=" + input + ")", new Object[0], ctrls); + } + + // ruleid: ldap-injection + public void ldapInjectionSunApi5(String input) throws NamingException { + Properties props = new Properties(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.put(Context.PROVIDER_URL, "ldap://ldap.example.com"); + props.put(Context.REFERRAL, "ignore"); + + SearchControls ctrls = new SearchControls(); + ctrls.setReturningAttributes(new String[]{"givenName", "sn"}); + ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + //LdapCtx context5 = new InitialDirContext(props); + LdapCtx context5 = new LdapCtx(props.toString(),null,0,null,Boolean.FALSE); + + NamingEnumeration answers; + answers = context5.search("dc=People,dc=example,dc=com", "(uid=" + input + ")", new Object[0], ctrls); + } + + // ruleid: ldap-injection + public void ldapInjectionSunApi6(String input) throws NamingException { + Properties props = new Properties(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.put(Context.PROVIDER_URL, "ldap://ldap.example.com"); + props.put(Context.REFERRAL, "ignore"); + + SearchControls ctrls = new SearchControls(); + ctrls.setReturningAttributes(new String[]{"givenName", "sn"}); + ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + //EventDirContext context6 = new InitialDirContext(props); + + EventDirContext context6 = (EventDirContext) new InitialDirContext(props); + + NamingEnumeration answers; + answers = context6.search("dc=People,dc=example,dc=com", "(uid=" + input + ")", new Object[0], ctrls); + } + + // ok: ldap-injection + public static void moreLdapInjections4(String input) throws NamingException { + Properties props = new Properties(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.put(Context.PROVIDER_URL, "ldap://ldap.example.com"); + props.put(Context.REFERRAL, "ignore"); + + SearchControls ctrls = new SearchControls(); + ctrls.setReturningAttributes(new String[]{"givenName", "sn"}); + ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + DirContext context1 = new InitialDirContext(props); + + NamingEnumeration answers; + //False positive + answers = context1.search(new LdapName("dc=People,dc=example,dc=com"), "(uid=bob)", new Object[0], ctrls); + } +} +*/ diff --git a/PR_5_java/java/filtered_java/23_permissive_cors.java b/PR_5_java/java/filtered_java/23_permissive_cors.java new file mode 100644 index 0000000..128a790 --- /dev/null +++ b/PR_5_java/java/filtered_java/23_permissive_cors.java @@ -0,0 +1,150 @@ +package lang.security.audit; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; + +/** + * Servlet implementation class SuperWebFlet + */ + +/** + * Dependencies not resolved + */ +@WebServlet("/SuperWebFlet") +class SuperWebFlet extends HttpServlet { + +/* + public SuperWebFlet() { + // Auto-generated constructor stub + } + + @ + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + // ruleid: permissive-cors + HttpServletResponse res = (HttpServletResponse) response; + res.addHeader("Access-Control-Allow-Origin", "*"); + chain.doFilter(request, response); + } + + // ruleid: permissive-cors + @GetMapping({"", "/"}) + @PreAuthorize("hasPermission('User', 'read')") + public List index(HttpServletRequest request, HttpServletResponse response) { + response.addHeader("access-control-allow-origin", "*"); + ContentHandler page = null; + return page.getContent().stream().map((item) -> { + Map ret = new HashMap(); + ret.put("createdAt", item.getCreatedAt()); + return ret; + }).collect(Collectors.toList()); + } + + // ruleid: permissive-cors + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + try { + response.setCharacterEncoding("UTF-8"); + response.setContentType("text/html; charset=UTF-8"); + response.setHeader("Access-Control-Allow-Origin", "Null"); + boolean ok = "OK".equals(ibookDbStatus); + if (!ok) { + response.setStatus(500); + } + } + catch (RuntimeException | IOException e) { + logger.log(Level.SEVERE, "RQ[HEALT] -> "+e.toString(), e); + throw e; + } + } + + // ruleid: permissive-cors + public void setErrorsResponse(Errors errors, HttpStatus responseHttpStatus, HttpServletRequest request, HttpServletResponse response) throws IOException { + response.setStatus(responseHttpStatus.value()); + HttpResponseData responseData = getResponseData(errors, request); + if (responseData != null) { + response.addHeader("access-control-allow-origin", "*"); + response.getWriter().write(responseData.getBody()); + } + } + + // ruleid: permissive-cors + public static void write(HttpServletResponse response, Object o) throws Exception { + response.setContentType("text/html;charset=utf-8"); + response.addHeader("Access-Control-Allow-Origin", "*.test.com"); + PrintWriter out = response.getWriter(); + out.println(o.toString()); + out.flush(); + out.close(); + } + + @GetMapping("/response-entity-builder-with-http-headers") + public ResponseEntity usingResponseEntityBuilderAndHttpHeaders() { + // ruleid: permissive-cors + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.set("Access-Control-Allow-Origin", "*"); + + return ResponseEntity.ok() + .headers(responseHeaders) + .body("Response with header using ResponseEntity"); + } + + // ruleid: permissive-cors + @GetMapping("/server-http-response") + public Mono usingServerHttpResponse(ServerHttpResponse response) { + response.getHeaders().add("Access-Control-Allow-Origin", "*"); + return Mono.just("Response with header using ServerHttpResponse"); + } + + @GetMapping("/response-entity") + public Mono> usingResponseEntityBuilder() { + String responseBody = "Response with header using ResponseEntity (builder)"; + // ruleid: permissive-cors + return Mono.just(ResponseEntity.ok() + .header("Access-Control-Allow-Origin", "*") + .body(responseBody)); + } + + public Mono useHandler(final ServerRequest request) { + // ruleid: permissive-cors + return (Mono) ServerResponse.ok() + .header("Access-Control-Allow-Origin", "null") + .body(Mono.just("Response with header using Handler"),String.class); + } + + // ruleid: permissive-cors + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + exchange.getResponse() + .getHeaders() + .add("Access-Control-Allow-Origin", "*.some.domain"); + return chain.filter(exchange); + } + + // ok: permissive-cors + public void setErrorsResponse1(Errors errors, HttpStatus responseHttpStatus, HttpServletRequest request, HttpServletResponse response) throws IOException { + response.addHeader("Foo", "Bar"); + response.getWriter().write(responseData.getBody()); + } + + // ok: permissive-cors + @GetMapping("/ok-ok") + public Mono usingServerHttpResponse1(ServerHttpResponse response) { + response.getHeaders().add("Foo", "Bar"); + return Mono.just("Response with header using ServerHttpResponse"); + } + + @GetMapping("/ok-ok-ok") + public ResponseEntity usingResponseEntityBuilderAndHttpHeaders1() { + // ok: permissive-cors + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.set("Foo", "Bar"); + + return ResponseEntity.ok() + .headers(responseHeaders) + .body("Response with header using ResponseEntity"); + } + +*/ +} diff --git a/PR_5_java/java/filtered_java/24_ognl_injection.java b/PR_5_java/java/filtered_java/24_ognl_injection.java new file mode 100644 index 0000000..d3752a7 --- /dev/null +++ b/PR_5_java/java/filtered_java/24_ognl_injection.java @@ -0,0 +1,56 @@ +package lang.security.audit; + +import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; +import com.opensymphony.xwork2.ognl.OgnlUtil; +import ognl.OgnlException; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.management.ReflectionException; +import java.beans.IntrospectionException; + +class OgnlReflectionProviderSample { + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: ognl-injection + public void unsafeOgnlReflectionProvider(@RequestParam("input") String input, OgnlReflectionProvider reflectionProvider, Class type) throws IntrospectionException, ReflectionException { + reflectionProvider.getGetMethod(type, input); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: ognl-injection + public void unsafeOgnlReflectionProvider1(@RequestParam("input") String input, ReflectionProvider reflectionProvider) throws IntrospectionException, ReflectionException { + reflectionProvider.getValue(input, null, null); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: ognl-injection + public void unsafeOgnlReflectionProvider2(@RequestParam("input") String input, OgnlUtil reflectionProvider) throws IntrospectionException, ReflectionException, OgnlException { + reflectionProvider.setValue(input, null, null,null); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: ognl-injection + public void unsafeOgnlReflectionProvider3(@RequestParam("input") String input, OgnlTextParser reflectionProvider) throws IntrospectionException, ReflectionException { + reflectionProvider.evaluate( input ); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=0} + // ok: ognl-injection + public void safeOgnlReflectionProvider1(OgnlReflectionProvider reflectionProvider, Class type) throws IntrospectionException, ReflectionException { + String input = "thisissafe"; + reflectionProvider.getGetMethod(type, input); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=0} + // ok: ognl-injection + public void safeOgnlReflectionProvider2(OgnlReflectionProvider reflectionProvider, Class type) throws IntrospectionException, ReflectionException { + reflectionProvider.getField(type, "thisissafe"); + } + // {/fact} + +} diff --git a/PR_5_java/java/filtered_java/25_use_of_md5.java b/PR_5_java/java/filtered_java/25_use_of_md5.java new file mode 100644 index 0000000..b62539a --- /dev/null +++ b/PR_5_java/java/filtered_java/25_use_of_md5.java @@ -0,0 +1,52 @@ +package lang.security.audit.crypto; + +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; + +import javax.script.ScriptContext; + +class Bad2{ + public byte[] bad1(String password) throws NoSuchAlgorithmException { + // ruleid: use-of-md5 + MessageDigest md5Digest = MessageDigest.getInstance("MD5"); + md5Digest.update(password.getBytes()); + byte[] hashValue = md5Digest.digest(); + return hashValue; + } + + public byte[] bad2(String password) { + // ruleid: use-of-md5 + byte[] hashValue = DigestUtils.getMd5Digest().digest(password.getBytes()); + return hashValue; + } + + public void bad3() throws NoSuchAlgorithmException, IOException { + // ruleid: use-of-md5 + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] input = {(byte) '?'}; + Object param = null; + Object inputParam = param; + if (inputParam instanceof String) input = ((String) inputParam).getBytes(); + if (inputParam instanceof InputStream) { + byte[] strInput = new byte[1000]; + int i = ((InputStream) inputParam).read(strInput); + if (i == -1) { + ScriptContext response = null; + + response.getWriter() + .write( + "This input source requires a POST, not a GET. Incompatible UI for the InputStream source."); + return; + } + input = Arrays.copyOf(strInput, i); + } + md.update(input); + + byte[] result = md.digest(); + } +} diff --git a/PR_5_java/java/filtered_java/26_LambdaFunctionHandler.java b/PR_5_java/java/filtered_java/26_LambdaFunctionHandler.java new file mode 100644 index 0000000..3041477 --- /dev/null +++ b/PR_5_java/java/filtered_java/26_LambdaFunctionHandler.java @@ -0,0 +1,85 @@ +package aws; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Base64; +import java.util.Calendar; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.json.simple.JSONObject; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.SdkClientException; +import com.amazonaws.lambda.demo.Emp; +import com.amazonaws.lambda.demo.HibernateUtil; +import com.amazonaws.lambda.demo.Request; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.lambda.demo.*; + +public class LambdaFunctionHandler implements RequestHandler < Request, String > { + String dstBucket = System.getenv("bucketname"); + String host_name = System.getenv("host_name"); + String user_name = System.getenv("user_name"); + String password = System.getenv("password"); + String dbname = System.getenv("dbname"); + @Override + + public String handleRequest(Request request, Context context) { + String s = " "; + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + try (Session session = sessionFactory.openSession()) { + int ctr = 0; + Connection connect; + connect = DriverManager.getConnection("jdbc:mysql://" + host_name + ":3306/" + dbname, user_name, password); + int month = request.getMonth(); + int year = request.getYear(); + int overtime = request.getOvertime(); + int empid = request.getEmp_id(); + Calendar Year = Calendar.getInstance(); + int CurrentYear = Year.get(Year.YEAR); + + if ((request.getMonth() <= 12 && request.getMonth() >= 1)) { + Statement statement = connect.createStatement(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: tainted-sql-string + String query = "SELECT emp_name,emp_mail,manager_id FROM employee WHERE emp_id=" + empid; + ResultSet resultSet = statement.executeQuery(query); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=0} + // ok: tainted-sql-string + System.out.println("SELECT emp_name,emp_mail,manager_id FROM employee WHERE emp_id=" + empid); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=0} + String foobar = "'Something'"; + // ok: tainted-sql-string + String query2 = "SELECT emp_name,emp_mail,manager_id FROM employee WHERE emp_id=" + foobar; + ResultSet resultSet2 = statement.executeQuery(query2); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=0} + // ok: tainted-sql-string + ResultSet resultSet3 = statement.executeQuery("SELECT * FROM employee"); + // {/fact} + } + } catch (SQLException e) { + e.printStackTrace(); + context.getLogger().log("error : " + e); + } + if (s == "") { + s = "Sucess " + String.format("Added %s %s %s %s %s.", request.emp_id, request.month, request.year, request.overtime); + } + return s; + } +} \ No newline at end of file diff --git a/PR_5_java/java/filtered_java/27_tainted_file_path.java b/PR_5_java/java/filtered_java/27_tainted_file_path.java new file mode 100644 index 0000000..9160199 --- /dev/null +++ b/PR_5_java/java/filtered_java/27_tainted_file_path.java @@ -0,0 +1,54 @@ +package spring.security.injection; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.sasanlabs.internal.utility.FrameworkConstants; +import org.sasanlabs.service.vulnerability.fileupload.UnrestrictedFileUpload; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Preflight is the request which is executed to download the uploaded file. This controller is made + * specifically for content disposition based response. we could have created the similar endpoint + * in {@code UnrestrictedFileUpload} but as framework appends the "Vulnerability name" hence created + * a new endpoint. + * + * @author KSASAN preetkaran20@gmail.com + */ +@RestController +class PreflightController { + + private UnrestrictedFileUpload unrestrictedFileUpload; + private static final String CONTENT_DISPOSITION_STATIC_FILE_LOCATION = "/test"; + public PreflightController(UnrestrictedFileUpload unrestrictedFileUpload) { + this.unrestrictedFileUpload = unrestrictedFileUpload; + } + + @RequestMapping( + CONTENT_DISPOSITION_STATIC_FILE_LOCATION + FrameworkConstants.SLASH + "{fileName}") + public ResponseEntity fetchFile(@PathVariable("fileName") String fileName) + // {fact rule=path-traversal@v1.0 defects=1} + + throws IOException { + InputStream inputStream = + // ruleid: tainted-file-path + new FileInputStream( + unrestrictedFileUpload.getContentDispositionRoot().toFile() + + FrameworkConstants.SLASH + + fileName); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment"); + return new ResponseEntity( + IOUtils.toByteArray(inputStream), httpHeaders, HttpStatus.OK); + } +// {/fact} + + +} diff --git a/PR_5_java/java/filtered_java/28_Driver.java b/PR_5_java/java/filtered_java/28_Driver.java new file mode 100644 index 0000000..814dd87 --- /dev/null +++ b/PR_5_java/java/filtered_java/28_Driver.java @@ -0,0 +1,39 @@ +package test; + +import lang.security.audit.CommandInjectionFormattedRuntimeCall; +import lang.security.audit.CommandInjectionProcessBuilder; +import org.springframework.security.core.userdetails.User; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.management.ReflectionException; +import javax.persistence.EntityManager; +import java.beans.IntrospectionException; +import java.io.IOException; +import java.io.InputStream; +import java.sql.SQLException; +import org.apache.log4j.Logger; + +public class Driver { + + @GetMapping + public void drive(@RequestParam("input") String userInput, + @RequestParam("user") User user, + @RequestParam("em") EntityManager em, + @RequestParam("stream") InputStream stream) throws IOException, SQLException, ReflectionException, IntrospectionException { + + // Command Injection Format + CommandInjectionFormattedRuntimeCall obj1 = new CommandInjectionFormattedRuntimeCall(userInput); + obj1.test1(userInput); + obj1.test2(userInput); + obj1.okTest(userInput); + + // Command Injection Process Builder + CommandInjectionProcessBuilder obj2 = new CommandInjectionProcessBuilder(); + obj2.test1(userInput, Logger.getLogger("logger")); + obj2.test2(userInput); + obj2.test3(userInput); + obj2.test4(userInput); + obj2.okTest(); + } +} diff --git a/PR_5_java/java/filtered_java/29_Driver.java b/PR_5_java/java/filtered_java/29_Driver.java new file mode 100644 index 0000000..5b2486c --- /dev/null +++ b/PR_5_java/java/filtered_java/29_Driver.java @@ -0,0 +1,19 @@ +package test; + +import lang.security.audit.CommandInjectionFormattedRuntimeCall; +import lang.security.audit.CommandInjectionProcessBuilder; +import org.springframework.security.core.userdetails.User; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.management.ReflectionException; +import javax.persistence.EntityManager; +import java.beans.IntrospectionException; +import java.io.IOException; +import java.io.InputStream; +import java.sql.SQLException; +import org.apache.log4j.Logger; + +public class Driver { + +} diff --git a/PR_5_java/java/filtered_java/30_LDAPServer.java b/PR_5_java/java/filtered_java/30_LDAPServer.java new file mode 100644 index 0000000..64a6609 --- /dev/null +++ b/PR_5_java/java/filtered_java/30_LDAPServer.java @@ -0,0 +1,324 @@ +package org.owasp.benchmark.helpers; + +import org.apache.directory.server.constants.ServerDNConstants; +import org.apache.directory.server.core.DefaultDirectoryService; +import org.apache.directory.server.core.DirectoryService; +import org.apache.directory.server.core.partition.Partition; +import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex; +import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition; +import org.apache.directory.server.core.partition.ldif.LdifPartition; +import org.apache.directory.server.core.schema.SchemaPartition; +import org.apache.directory.server.ldap.LdapServer; +import org.apache.directory.server.protocol.shared.transport.TcpTransport; +import org.apache.directory.server.xdbm.Index; +import org.apache.directory.shared.ldap.entry.Entry; +import org.apache.directory.shared.ldap.entry.ServerEntry; +import org.apache.directory.shared.ldap.name.DN; +import org.apache.directory.shared.ldap.schema.SchemaManager; +import org.apache.directory.shared.ldap.schema.ldif.extractor.SchemaLdifExtractor; +import org.apache.directory.shared.ldap.schema.ldif.extractor.impl.DefaultSchemaLdifExtractor; +import org.apache.directory.shared.ldap.schema.loader.ldif.LdifSchemaLoader; +import org.apache.directory.shared.ldap.schema.manager.impl.DefaultSchemaManager; +import org.apache.directory.shared.ldap.schema.registries.SchemaLoader; + +import java.io.File; +import java.util.HashSet; +import java.util.List; + +public class LDAPServer { + /** The directory service */ + private DirectoryService service; + + /** The LDAP server */ + private LdapServer server; + + public LDAPServer() { + String dir = Utils.getFileFromClasspath("benchmark.properties", LDAPManager.class.getClassLoader()).getParent(); + File workDir = new File(dir + "/../ldap"); + workDir.mkdirs(); + + // Create the server + try { + initDirectoryService(workDir); + } catch (Exception e) { + System.out.println("Error creating LDAP Server: " + e.getMessage()); + } + + // Read an entry + Entry result = null; + try { + result = service.getAdminSession().lookup(new DN("dc=apache,dc=org")); + } catch (Exception e) { + System.out.println("Error creating LDAP Server: " + e.getMessage()); + } + + // And print it if available +// System.out.println("Found entry : " + result); + + // optionally we can start a server too + try { + startServer(); + } catch (Exception e) { + System.out.println("Error creating LDAP Server: " + e.getMessage()); + } + + LDAPManager emd = new LDAPManager(); + LDAPPerson ldapP = new LDAPPerson(); + ldapP.setName("foo"); + ldapP.setPassword("MrFooPa$$word"); + ldapP.setAddress("AddressForFoo #345"); + + emd.insert(ldapP); + + ldapP = new LDAPPerson(); + ldapP.setName("Ms Bar"); + ldapP.setPassword("barM$B4dPass"); + ldapP.setAddress("The streetz 4 Ms bar"); + + emd.insert(ldapP); + + ldapP = new LDAPPerson(); + ldapP.setName("Mr Unknown"); + ldapP.setPassword("YouwontGue$$"); + ldapP.setAddress("Whe home is #678"); + + emd.insert(ldapP); + } + + /** + * Initialize the server. It creates the partition, adds the index, and + * injects the context entries for the created partitions. + * + * @param workDir + * the directory to be used for storing the data + * @throws Exception + * if there were some problems while initializing the system + */ + private void initDirectoryService(File workDir){ + // Initialize the LDAP service + try { + service = new DefaultDirectoryService(); + } catch (Exception e1) { + System.out.println("Error creating DefaultDirectoryService. " + e1.getMessage()); + } + service.setWorkingDirectory(workDir); + + // first load the schema + initSchemaPartition(); + + // then the system partition + // this is a MANDATORY partition + Partition systemPartition = null; + try { + systemPartition = addPartition("system", ServerDNConstants.SYSTEM_DN); + } catch (Exception e1) { + System.out.println("Error addPartition system. " + e1.getMessage()); + } + service.setSystemPartition(systemPartition); + + // Disable the ChangeLog system + service.getChangeLog().setEnabled(false); + service.setDenormalizeOpAttrsEnabled(true); + + // Now we can create as many partitions as we need + // Create some new partitions named 'foo', 'bar' and 'apache'. + Partition fooPartition = null; + try { + fooPartition = addPartition("foo", "dc=foo,dc=com"); + } catch (Exception e1) { + System.out.println("Error addPartition foo. " + e1.getMessage()); + } + Partition barPartition = null; + try { + barPartition = addPartition("bar", "dc=bar,dc=com"); + } catch (Exception e1) { + System.out.println("Error addPartition bar. " + e1.getMessage()); + } + Partition apachePartition = null; + try { + apachePartition = addPartition("apache", "dc=apache,dc=org"); + } catch (Exception e1) { + System.out.println("Error addPartition apache. " + e1.getMessage()); + } + + // Index some attributes on the apache partition + addIndex(apachePartition, "objectClass", "ou", "uid"); + try { + // And start the service + service.startup(); + } catch (Exception e) { + System.out.println("Error at LDAP startup: " + e.getMessage()); + } + // Inject the foo root entry if it does not already exist + try { + service.getAdminSession().lookup(fooPartition.getSuffixDn()); + } catch (Exception lnnfe) { + try { + DN dnFoo = new DN("dc=foo,dc=com"); + ServerEntry entryFoo = service.newEntry(dnFoo); + entryFoo.add("objectClass", "top", "domain", "extensibleObject"); + entryFoo.add("dc", "foo"); + service.getAdminSession().add(entryFoo); + } catch (Exception e) { + System.out.println("Error creating new DN."); + } + } + + // Inject the bar root entry + try { + service.getAdminSession().lookup(barPartition.getSuffixDn()); + } catch (Exception lnnfe) { + try { + DN dnBar = new DN("dc=bar,dc=com"); + ServerEntry entryBar = service.newEntry(dnBar); + entryBar.add("objectClass", "top", "domain", "extensibleObject"); + entryBar.add("dc", "bar"); + service.getAdminSession().add(entryBar); + } catch (Exception e) { + System.out.println("Error creating new DN."); + } + } + + // Inject the apache root entry + try { + if (!service.getAdminSession().exists(apachePartition.getSuffixDn())) { + try{ + DN dnApache = new DN("dc=Apache,dc=Org"); + ServerEntry entryApache = service.newEntry(dnApache); + entryApache.add("objectClass", "top", "domain", "extensibleObject"); + entryApache.add("dc", "Apache"); + service.getAdminSession().add(entryApache); + } catch (Exception e) { + System.out.println("Error creating new DN."); + } + } + } catch (Exception e) { + System.out.println("Error when checking if partition exists."); + } + + } + + /** + * initialize the schema manager and add the schema partition to diectory + * service + * + * @throws Exception + * if the schema LDIF files are not found on the classpath + */ + private void initSchemaPartition() { + SchemaPartition schemaPartition = service.getSchemaService().getSchemaPartition(); + + // Init the LdifPartition + LdifPartition ldifPartition = new LdifPartition(); + String workingDirectory = service.getWorkingDirectory().getPath(); + ldifPartition.setWorkingDirectory(workingDirectory + "/schema"); + + // Extract the schema on disk (a brand new one) and load the registries + File schemaRepository = new File(workingDirectory, "schema"); + File wd = new File(workingDirectory); + SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor(wd); + try { + extractor.extractOrCopy( true ); + //System.out.println("is Extracted: " + extractor.isExtracted()); + } catch (Exception e) { + } + + schemaPartition.setWrappedPartition(ldifPartition); + try { + SchemaLoader loader = new LdifSchemaLoader(schemaRepository); + SchemaManager schemaManager = new DefaultSchemaManager(loader); + service.setSchemaManager(schemaManager); + + // We have to load the schema now, otherwise we won't be able + // to initialize the Partitions, as we won't be able to parse + // and normalize their suffix DN + schemaManager.loadAllEnabled(); + + schemaPartition.setSchemaManager(schemaManager); + + List errors = schemaManager.getErrors(); + + if (errors.size() != 0) { + throw new Exception("Schema load failed : " + errors); + } + } catch (Exception e) { + } + } + + /** + * Add a new partition to the server + * + * @param partitionId + * The partition Id + * @param partitionDn + * The partition DN + * @return The newly added partition + * @throws Exception + * If the partition can't be added + */ + private Partition addPartition(String partitionId, String partitionDn) throws Exception { + // Create a new partition named 'foo'. + JdbmPartition partition = new JdbmPartition(); + partition.setId(partitionId); + partition.setPartitionDir(new File(service.getWorkingDirectory(), partitionId)); + partition.setSuffix(partitionDn); + service.addPartition(partition); + + return partition; + } + + /** + * Add a new set of index on the given attributes + * + * @param partition + * The partition on which we want to add index + * @param attrs + * The list of attributes to index + */ + private void addIndex(Partition partition, String... attrs) { + // Index some attributes on the apache partition + HashSet> indexedAttributes = new HashSet>(); + + for (String attribute : attrs) { + indexedAttributes.add(new JdbmIndex(attribute)); + } + + ((JdbmPartition) partition).setIndexedAttributes(indexedAttributes); + } + + /** + * starts the LdapServer + * + * @throws Exception + */ + public void startServer() throws Exception { + server = new LdapServer(); + int serverPort = 10389; + server.setTransports(new TcpTransport(serverPort)); + server.setDirectoryService(service); + + server.start(); + } + + public void stopServer() throws Exception { + if (server != null) { + server.stop(); + if (server.getDirectoryService() != null) { + server.getDirectoryService().shutdown(); + } + } + } + + /** + * Main class. + * + * @param args + * Not used. + * @throws Exception + */ + public static void main(String[] args) throws Exception { + LDAPServer ldap = new LDAPServer(); + //ldap.stopServer(); + } + +} diff --git a/PR_5_java/java/filtered_java/31_PropertiesManager.java b/PR_5_java/java/filtered_java/31_PropertiesManager.java new file mode 100644 index 0000000..9e7d273 --- /dev/null +++ b/PR_5_java/java/filtered_java/31_PropertiesManager.java @@ -0,0 +1,119 @@ +package org.owasp.benchmark.helpers; + +import java.io.*; +import java.util.Properties; + +public class PropertiesManager { + private String propertiesFileName = null; + private File file = null; + private boolean isExternalFile = false; + + public PropertiesManager() { + propertiesFileName = "benchmark.properties"; + file = Utils.getFileFromClasspath(propertiesFileName, this.getClass().getClassLoader()); + } + + public PropertiesManager(String fileName) { + propertiesFileName = fileName; + file = Utils.getFileFromClasspath(propertiesFileName, this.getClass().getClassLoader()); + } + + public PropertiesManager(String path, String fileName) { + isExternalFile = true; + propertiesFileName = fileName; + file = new File(path + File.separator + fileName); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + System.out.println("Problem creating new properties file."); + } + } + } + + public void displayProperties() { + Properties props = new Properties(); + InputStream is = null; + try { + is = this.getClass().getClassLoader().getResourceAsStream(propertiesFileName); + props.load(is); + } catch (Exception e) { + } + + System.out.println(props.keySet()); + System.out.println(props.values()); + } + + public String getProperty(String key, String defaultValue) { + Properties props = new Properties(); + InputStream is = null; + try { + if (isExternalFile) { + is = new FileInputStream(file); + } else { + is = this.getClass().getClassLoader().getResourceAsStream(propertiesFileName); + } + props.load(is); + } catch (Exception e) { + } + + return props.getProperty(key, defaultValue); + } + + public int getProperty(String key, int defaultValue) { + Properties props = new Properties(); + InputStream is = null; + try { + if (isExternalFile) { + is = new FileInputStream(file); + } else { + is = this.getClass().getClassLoader().getResourceAsStream(propertiesFileName); + } + props.load(is); + } catch (Exception e) { + } + + return Integer.parseInt(props.getProperty(key, Integer.toString(defaultValue))); + } + + public void saveProperty(String key, String value) { + InputStream in = null; + try { + if (isExternalFile) { + in = new FileInputStream(file); + } else { + in = this.getClass().getClassLoader().getResourceAsStream(propertiesFileName); + } + Properties props = new Properties(); + props.load(in); + in.close(); + + FileOutputStream out = new FileOutputStream(file); + props.setProperty(key, value); + props.store(out, null); + out.close(); + } catch (Exception e) { + System.out.println("There was a problem saving a property in the properties file"); + } + } + + public void removeProperty(String key) { + InputStream in = null; + try { + in = this.getClass().getClassLoader().getResourceAsStream(propertiesFileName); + + Properties props = new Properties(); + props.load(in); + in.close(); + + FileOutputStream out = new FileOutputStream(file); + props.remove(key); + props.store(out, null); + out.close(); + } catch (Exception e) { + System.out.println("There was a problem removing a property from the properties file"); + } + + } + +} \ No newline at end of file diff --git a/PR_5_java/java/filtered_java/32_el_injection.java b/PR_5_java/java/filtered_java/32_el_injection.java new file mode 100644 index 0000000..4945d31 --- /dev/null +++ b/PR_5_java/java/filtered_java/32_el_injection.java @@ -0,0 +1,66 @@ +package lang.security.audit; + +import javax.el.ELContext; +import javax.el.ExpressionFactory; +import javax.el.ValueExpression; +import javax.faces.context.FacesContext; +import org.springframework.web.bind.annotation.RequestParam; +class ElExpressionSample { + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: el-injection + public void unsafeEL(@RequestParam("expression") String expression) { + FacesContext context = FacesContext.getCurrentInstance(); + ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory(); + ELContext elContext = context.getELContext(); + ValueExpression vex = expressionFactory.createValueExpression(elContext, expression, String.class); + String result = (String) vex.getValue(elContext); + System.out.println(result); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=0} + // ok: el-injection + public void safeEL() { + FacesContext context = FacesContext.getCurrentInstance(); + ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory(); + ELContext elContext = context.getELContext(); + ValueExpression vex = expressionFactory.createValueExpression(elContext, "1+1", String.class); + String result = (String) vex.getValue(elContext); + System.out.println(result); + } + // {fact} + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: el-injection + public void unsafeELMethod(ELContext elContext,ExpressionFactory expressionFactory,@RequestParam("expression") String expression) { + expressionFactory.createMethodExpression(elContext, expression, String.class, new Class[]{Integer.class}); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=0} + //ok: el-injection + public void safeELMethod(ELContext elContext,ExpressionFactory expressionFactory) { + expressionFactory.createMethodExpression(elContext, "1+1", String.class,new Class[] {Integer.class}); + } + // {/fact} + + // Dependency not resolved + //ruleid: el-injection + /* private void unsafeELTemplate(String message, ConstraintValidatorContext context) { + context.disableDefaultConstraintViolation(); + context + .someMethod() + .buildConstraintViolationWithTemplate(message) + .addConstraintViolation(); + } + + //ok: el-injection + private void safeELTemplate(String message, ConstraintValidatorContext context) { + context.disableDefaultConstraintViolation(); + context + .someMethod() + .buildConstraintViolationWithTemplate("somestring") + .addConstraintViolation(); + }*/ +} diff --git a/PR_5_java/java/filtered_java/33_script_engine_injection.java b/PR_5_java/java/filtered_java/33_script_engine_injection.java new file mode 100644 index 0000000..200eb8f --- /dev/null +++ b/PR_5_java/java/filtered_java/33_script_engine_injection.java @@ -0,0 +1,39 @@ +package lang.security.audit; + +import org.springframework.web.bind.annotation.RequestParam; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; + +class ScriptEngineSample { + + private static ScriptEngineManager sem = new ScriptEngineManager(); + private static ScriptEngine se = sem.getEngineByExtension("js"); + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: script-engine-injection + public static void scripting(@RequestParam("input") String userInput) throws ScriptException { + Object result = se.eval("test=1;" + userInput); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: script-engine-injection + public static void scripting1(@RequestParam("input") String userInput) throws ScriptException { + ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); + ScriptEngine scriptEngine = scriptEngineManager.getEngineByExtension("js"); + Object result = scriptEngine.eval("test=1;" + userInput); + } + // {/fact} + + // {fact rule=code-injection@v1.0 defects=0} + //ok: script-engine-injection + public static void scriptingSafe() throws ScriptException { + ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); + ScriptEngine scriptEngine = scriptEngineManager.getEngineByExtension("js"); + String code = "var test=3;test=test*2;"; + Object result = scriptEngine.eval(code); + } + // {/fact} +} + diff --git a/PR_5_java/java/filtered_java/34_jdbc_sql_formatted_string.java b/PR_5_java/java/filtered_java/34_jdbc_sql_formatted_string.java new file mode 100644 index 0000000..a169571 --- /dev/null +++ b/PR_5_java/java/filtered_java/34_jdbc_sql_formatted_string.java @@ -0,0 +1,85 @@ +package lang.security.audit; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.web.bind.annotation.RequestParam; + + +class TestClass { + + public TestClass() { + System.out.println("Hello"); + } + + public void unsafe_jdbc_queryForObject_1(@RequestParam("paramName") String paramName) { + JdbcTemplate jdbc = new JdbcTemplate(); + System.out.println("Hello"); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jdbc-sql-formatted-string + int count = jdbc.queryForObject("select count(*) from Users where name = '"+paramName+"'", Integer.class); + } + // {/fact} + + public void unsafe_jdbc_queryForObject_2(@RequestParam("input") String paramName) { + JdbcTemplate jdbc = new JdbcTemplate(); + System.out.println("Hello"); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jdbc-sql-formatted-string + String query = "select count(*) from Users where name = '"+paramName+"'"; + int count = jdbc.queryForObject(query, Integer.class); + } + // {/fact} + + public void unsafe_jdbc_queryForObject_3(@RequestParam("input") String paramName) { + JdbcTemplate jdbc = new JdbcTemplate(); + System.out.println("Hello"); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jdbc-sql-formatted-string + StringBuilder query = new StringBuilder("select count(*) from Users"); + query.append( "where name = '"+paramName+"'"); + int count = jdbc.queryForObject(query.toString(), Integer.class); + } + // {/fact} + + public void unsafe_jdbc_queryForList_1(@RequestParam("input") String paramName) { + JdbcTemplate jdbc = new JdbcTemplate(); + System.out.println("Hello"); + List users = new ArrayList<>(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jdbc-sql-formatted-string + String query = "select count(*) from Users where name = '"+paramName+"'"; + List> rows = jdbc.queryForList(query); + } + // {/fact} + + public void unsafe_jdbc_queryForList_2(@RequestParam("input") String paramName) { + JdbcTemplate jdbc = new JdbcTemplate(); + System.out.println("Hello"); + List users = new ArrayList<>(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jdbc-sql-formatted-string + List> rows = jdbc.queryForList("select count(*) from Users where name = '"+paramName+"'"); + } + // {/fact} + + public void unsafe_jdbc_update(@RequestParam("input") String paramName, @RequestParam("salary") String paramSalary) { + JdbcTemplate jdbc = new JdbcTemplate(); + System.out.println("Hello"); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jdbc-sql-formatted-string + String updateQuery = "update Users set salary = '"+paramSalary+"' where name = '"+paramName+"'"; + jdbc.update(updateQuery); + } + // {/fact} + public void safe(@RequestParam("input") String paramName) { + JdbcTemplate jdbc = new JdbcTemplate(); + // {fact rule=sql-injection@v1.0 defects=0} + // ok:jdbc-sql-formatted-string + int count = jdbc.queryForObject("select count(*) from Users where name = ?", Integer.class, paramName); + } + // {/fact} +} + diff --git a/PR_5_java/java/filtered_java/35_CommandInjectionFormattedRuntimeCall.java b/PR_5_java/java/filtered_java/35_CommandInjectionFormattedRuntimeCall.java new file mode 100644 index 0000000..e079e1f --- /dev/null +++ b/PR_5_java/java/filtered_java/35_CommandInjectionFormattedRuntimeCall.java @@ -0,0 +1,51 @@ +package lang.security.audit; + +import org.springframework.web.bind.annotation.RequestParam; + +import java.io.File; +import java.io.IOException; +import java.lang.Runtime; + +public class CommandInjectionFormattedRuntimeCall { + + public CommandInjectionFormattedRuntimeCall(String input) throws IOException { + Runtime r = Runtime.getRuntime(); + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: command-injection-formatted-runtime-call + r.exec("/bin/sh -c some_tool" + input); + } + // {/fact} + + public void test1(String input) { + Runtime r = Runtime.getRuntime(); + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: command-injection-formatted-runtime-call + r.loadLibrary(String.format("%s.dll", input)); + } + // {/fact} + + public void test2(String input) throws IOException { + Runtime r = Runtime.getRuntime(); + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: command-injection-formatted-runtime-call + r.exec("bash", new String[]{"-c"}, new File(input)); + } + // {/fact} + + public void okTest(String input) throws IOException { + Runtime r = Runtime.getRuntime(); + // {fact rule=os-command-injection@v1.0 defects=0} + // ok: command-injection-formatted-runtime-call + r.exec("echo 'blah'"); + } + // {/fact} +} + +class CommandInjectionRuntimeDriver { + public void drive(@RequestParam("input") String input) throws IOException { + CommandInjectionFormattedRuntimeCall obj = new CommandInjectionFormattedRuntimeCall(input); + obj.test1(input); + obj.test2(input); + obj.okTest(input); + } +} diff --git a/PR_5_java/java/filtered_java/36_bad_hexa_conversion.java b/PR_5_java/java/filtered_java/36_bad_hexa_conversion.java new file mode 100644 index 0000000..d615000 --- /dev/null +++ b/PR_5_java/java/filtered_java/36_bad_hexa_conversion.java @@ -0,0 +1,43 @@ +package lang.security.audit; + +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +class BadHexa { + public static void main(String[] args) throws Exception { + String good = goodHash("12345"); + String bad = badHash("12345"); + System.out.println(String.format("%s (len=%d) != %s (len=%d)", good, good.length(), bad, bad.length())); + } + + // {fact rule=nan-injection@v1.0 defects=0} + // ok: bad-hexa-conversion + public static String goodHash(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + byte[] resultBytes = md.digest(password.getBytes("UTF-8")); + + StringBuilder stringBuilder = new StringBuilder(); + for (byte b : resultBytes) { + stringBuilder.append(String.format("%02X", b)); + } + + return stringBuilder.toString(); + } + // {/fact} + + // {fact rule=nan-injection@v1.0 defects=1} + // ruleid: bad-hexa-conversion + public static String badHash(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + byte[] resultBytes = md.digest(password.getBytes("UTF-8")); + + StringBuilder stringBuilder = new StringBuilder(); + for (byte b : resultBytes) { + stringBuilder.append(Integer.toHexString(b & 0xFF)); + } + + return stringBuilder.toString(); + } + // {/fact} +} diff --git a/PR_5_java/java/filtered_java/37_use_of_sha1.java b/PR_5_java/java/filtered_java/37_use_of_sha1.java new file mode 100644 index 0000000..9608064 --- /dev/null +++ b/PR_5_java/java/filtered_java/37_use_of_sha1.java @@ -0,0 +1,56 @@ +package lang.security.audit.crypto; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.apache.commons.codec.digest.DigestUtils; +class Bad { + public byte[] bad1(String password) throws NoSuchAlgorithmException { + // ruleid: use-of-sha1 + MessageDigest sha1Digest = MessageDigest.getInstance("SHA1"); + sha1Digest.update(password.getBytes()); + byte[] hashValue = sha1Digest.digest(); + return hashValue; + } + public byte[] bad2(String password) { + // ruleid: use-of-sha1 + byte[] hashValue = DigestUtils.getSha1Digest().digest(password.getBytes()); + return hashValue; + } + + //Dependency not resolved + /* + public void bad3() throws IOException, NoSuchAlgorithmException, NoSuchProviderException { + // ruleid: use-of-sha1 + MessageDigest md = MessageDigest.getInstance("SHA1", "SUN"); + byte[] input = {(byte) '?'}; + Object inputParam = bar; + if (inputParam instanceof String) input = ((String) inputParam).getBytes(); + if (inputParam instanceof java.io.InputStream) { + byte[] strInput = new byte[1000]; + int i = ((java.io.InputStream) inputParam).read(strInput); + if (i == -1) { + response.getWriter() + .println( + "This input source requires a POST, not a GET. Incompatible UI for the InputStream source."); + return; + } + input = java.util.Arrays.copyOf(strInput, i); + } + md.update(input); + byte[] result = md.digest(); + java.io.File fileTarget = + new java.io.File( + new java.io.File(org.owasp.benchmark.helpers.Utils.TESTFILES_DIR), + "passwordFile.txt"); + java.io.FileWriter fw = + new java.io.FileWriter(fileTarget, true); // the true will append the new data + fw.write( + "hash_value=" + + org.owasp.esapi.ESAPI.encoder().encodeForBase64(result, true) + + "\n"); + fw.close(); + } + + */ +} diff --git a/PR_5_java/java/filtered_java/38_insecure_hostname_verifier.java b/PR_5_java/java/filtered_java/38_insecure_hostname_verifier.java new file mode 100644 index 0000000..ade0066 --- /dev/null +++ b/PR_5_java/java/filtered_java/38_insecure_hostname_verifier.java @@ -0,0 +1,37 @@ +package lang.security.audit.crypto.ssl; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; + +// {fact rule=improper-certificate-validation@v1.0 defects=1} +// ruleid:insecure-hostname-verifier +class AllHosts implements HostnameVerifier { + public boolean verify(final String hostname, final SSLSession session) { + return true; + } +} +// {/fact} + +// {fact rule=improper-certificate-validation@v1.0 defects=0} +// ok:insecure-hostname-verifier +class LocalHost implements HostnameVerifier { + public boolean verify(final String hostname, final SSLSession session) { + return hostname.equals("localhost"); + } +} +// {/fact} + +// {fact rule=improper-certificate-validation@v1.0 defects=1} +// cf. https://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https +class InlineVerifier { + public InlineVerifier() { + // ruleid:insecure-hostname-verifier + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + } + // {/fact} +} diff --git a/PR_5_java/java/filtered_java/39_jpa_sqli.java b/PR_5_java/java/filtered_java/39_jpa_sqli.java new file mode 100644 index 0000000..f4c67a7 --- /dev/null +++ b/PR_5_java/java/filtered_java/39_jpa_sqli.java @@ -0,0 +1,103 @@ +package lang.security.audit.sqli; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; + +class JpaSql { + + public void getUserByUsername(EntityManager em,@RequestParam String username) { + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jpa-sqli + TypedQuery q = em.createQuery( + String.format("select * from Users where name = %s", username), + UserEntity.class); + + UserEntity res = q.getSingleResult(); + } + // {/fact} + + public void getUserByUsernameAlt2(EntityManager em,@RequestParam String username) { + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jpa-sqli + TypedQuery q = em.createQuery( + "select * from Users where name = '" + username + "'", + UserEntity.class); + + UserEntity res = q.getSingleResult(); + } + // {/fact} + + public UserEntity getFirst(EntityManager em) { + // {fact rule=sql-injection@v1.0 defects=0} + // ok:jpa-sqli + TypedQuery q = em.createQuery( + "select * from Users", + UserEntity.class); + return q.getSingleResult(); + } + // {/fact} + + public UserEntity getFirstAlt2(EntityManager em) { + final String sql = "select * from Users"; + // {fact rule=sql-injection@v1.0 defects=0} + // ok:jpa-sqli + TypedQuery q = (TypedQuery) em.createQuery(sql); + return q.getSingleResult(); + } + // {/fact} + + public void getUserWithNativeQueryUnsafe(EntityManager em,@RequestParam String password) { + String sql = "select * from Users where user = 'admin' and password='"+password+"'"; + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jpa-sqli + em.createNativeQuery(sql); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jpa-sqli + em.createNativeQuery(sql,"testcode.sqli.UserEntity"); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:jpa-sqli + em.createNativeQuery(sql, UserEntity.class); + // {/fact} + } + + public void getUserWithNativeQuerySafe(EntityManager em) { + String sql = "select * from Users where user = 'admin'"; + // {fact rule=sql-injection@v1.0 defects=0} + // ok:jpa-sqli + em.createNativeQuery(sql); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=0} + // ok:jpa-sqli + em.createNativeQuery(sql,"testcode.sqli.UserEntity"); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=0} + // ok:jpa-sqli + em.createNativeQuery(sql, UserEntity.class); + // {/fact} + } +} + +class TestJpa { + + @GetMapping + public void drive(@RequestParam("input") String userInput, + @RequestParam("em") EntityManager em){ + + // JPA SQL Injection + new JpaSql().getUserByUsername(em, userInput); + new JpaSql().getUserByUsernameAlt2(em, userInput); + new JpaSql().getFirst(em); + new JpaSql().getUserWithNativeQueryUnsafe(em, userInput); + new JpaSql().getUserWithNativeQuerySafe(em); + + } +} diff --git a/PR_5_java/java/filtered_java/40_jdo_sqli.java b/PR_5_java/java/filtered_java/40_jdo_sqli.java new file mode 100644 index 0000000..4ef7162 --- /dev/null +++ b/PR_5_java/java/filtered_java/40_jdo_sqli.java @@ -0,0 +1,153 @@ +package lang.security.audit.sqli; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.jdo.Extent; +import javax.jdo.JDOHelper; +import javax.jdo.PersistenceManager; +import javax.jdo.PersistenceManagerFactory; +import javax.jdo.Query; +import java.util.ArrayList; + +class JdoSqlFilter { + + private static final PersistenceManagerFactory pmfInstance = + JDOHelper.getPersistenceManagerFactory("transactions-optional"); + + public static PersistenceManager getPM() { + return pmfInstance.getPersistenceManager(); + } + + public void testJdoUnsafeFilter(String filterValue) { + PersistenceManager pm = getPM(); + Query q = pm.newQuery(UserEntity.class); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: jdo-sqli + q.setFilter("id == "+filterValue); + } + // {/fact} + + public void testJdoSafeFilter(String filterValue) { + PersistenceManager pm = getPM(); + Query q = pm.newQuery(UserEntity.class); + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + q.setFilter("id == 1"); + } + // {/fact} + + public void testJdoSafeFilter2(String filterValue) { + PersistenceManager pm = getPM(); + Query q = pm.newQuery(UserEntity.class); + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + q.setFilter("id == userId"); + q.declareParameters("int userId"); + + } + // {/fact} + + private static final String FIELD_TEST = "test"; + + public void testJdoUnsafeGrouping(String groupByField) { + PersistenceManager pm = getPM(); + Query q = pm.newQuery(UserEntity.class); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: jdo-sqli + q.setGrouping(groupByField); + } + // {/fact} + + public void testJdoSafeGrouping() { + PersistenceManager pm = getPM(); + Query q = pm.newQuery(UserEntity.class); + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + q.setGrouping(FIELD_TEST); + } + // {/fact} +} + +class JdoSql { + + private static final PersistenceManagerFactory pmfInstance = + JDOHelper.getPersistenceManagerFactory("transactions-optional"); + + + public static PersistenceManager getPM() { + return pmfInstance.getPersistenceManager(); + } + + public void testJdoQueries(String input) { + PersistenceManager pm = getPM(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: jdo-sqli + pm.newQuery("select * from Users where name = " + input); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: jdo-sqli + pm.newQuery("sql", "select * from Products where name = " + input); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + pm.newQuery("select * from Config"); + // {/fact} + + final String query = "select * from Config"; + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + pm.newQuery(query); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + pm.newQuery("sql", query); + // {/fact} + } + + public void testJdoQueriesAdditionalMethodSig(String input) { + PersistenceManager pm = getPM(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: jdo-sqli + pm.newQuery(UserEntity.class,new ArrayList(),"id == "+ input); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + pm.newQuery(UserEntity.class,new ArrayList(),"id == 1"); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: jdo-sqli + pm.newQuery(UserEntity.class,"id == "+ input); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + pm.newQuery(UserEntity.class,"id == 1"); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: jdo-sqli + pm.newQuery((Extent) null,"id == "+input); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=0} + // ok: jdo-sqli + pm.newQuery((Extent) null,"id == 1"); + // {/fact} + } + +} + +class TestJdo { + + @GetMapping + public void drive(@RequestParam("input") String userInput){ + // JDO SQL Injection + new JdoSqlFilter().testJdoUnsafeFilter(userInput); + new JdoSqlFilter().testJdoSafeFilter(userInput); + new JdoSqlFilter().testJdoSafeFilter2(userInput); + new JdoSqlFilter().testJdoUnsafeGrouping(userInput); + new JdoSqlFilter().testJdoSafeGrouping(); + new JdoSql().testJdoQueries(userInput); + new JdoSql().testJdoQueriesAdditionalMethodSig(userInput); + } +} diff --git a/PR_5_java/java/filtered_java/41_LambdaFunctionHandlerEx.java b/PR_5_java/java/filtered_java/41_LambdaFunctionHandlerEx.java new file mode 100644 index 0000000..1ada0d0 --- /dev/null +++ b/PR_5_java/java/filtered_java/41_LambdaFunctionHandlerEx.java @@ -0,0 +1,59 @@ +package aws; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Calendar; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import com.amazonaws.lambda.demo.HibernateUtil; +import com.amazonaws.lambda.demo.Request; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +public class LambdaFunctionHandlerEx implements RequestHandler < Request, String > { + String dstBucket = System.getenv("bucketname"); + String host_name = System.getenv("host_name"); + String user_name = System.getenv("user_name"); + String password = System.getenv("password"); + String dbname = System.getenv("dbname"); + @Override + + public String handleRequest(Request request, Context context) { + String s = " "; + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + try (Session session = sessionFactory.openSession()) { + int ctr = 0; + Connection connect; + connect = DriverManager.getConnection("jdbc:mysql://" + host_name + ":3306/" + dbname, user_name, password); + int month = request.getMonth(); + int year = request.getYear(); + int overtime = request.getOvertime(); + int empid = request.getEmp_id(); + Calendar Year = Calendar.getInstance(); + int CurrentYear = Year.get(Year.YEAR); + + if ((request.getMonth() <= 12 && request.getMonth() >= 1)) { + Statement statement = connect.createStatement(); + String query = "SELECT emp_name,emp_mail,manager_id FROM employee WHERE emp_id=" + empid; + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: tainted-sqli + ResultSet resultSet = statement.executeQuery(query); + // {/fact} + // {fact rule=sql-injection@v1.0 defects=0} + // ok: tainted-sqli + ResultSet resultSet2 = statement.executeQuery("SELECT * FROM employee"); + // {/fact} + } + } catch (SQLException e) { + e.printStackTrace(); + context.getLogger().log("error : " + e); + } + if (s == "") { + s = "Sucess " + String.format("Added %s %s %s %s %s.", request.emp_id, request.month, request.year, request.overtime); + } + return s; + } +} \ No newline at end of file diff --git a/PR_5_java/java/filtered_java/42_unrestricted_request_mapping.java b/PR_5_java/java/filtered_java/42_unrestricted_request_mapping.java new file mode 100644 index 0000000..a034cf4 --- /dev/null +++ b/PR_5_java/java/filtered_java/42_unrestricted_request_mapping.java @@ -0,0 +1,53 @@ +package spring.security;// cf. https://find-sec-bugs.github.io/bugs.htm#SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +class ControllerEx { +// {fact rule=coral-csrf-rule@v1.0 defects=1} + + // ruleid: unrestricted-request-mapping + @RequestMapping("/path") + public void writeData() { + // State-changing operations performed within this method. + } + // {/fact} + +// {fact rule=coral-csrf-rule@v1.0 defects=1} + + // ruleid: unrestricted-request-mapping + @RequestMapping(value = "/path") + public void writeData2() { + // State-changing operations performed within this method. + } + // {/fact} + + /** + * For methods without side-effects use either + * RequestMethod.GET, RequestMethod.HEAD, RequestMethod.TRACE, or RequestMethod.OPTIONS. + */ + // {fact rule=coral-csrf-rule@v1.0 defects=0} + + // ok: unrestricted-request-mapping + @RequestMapping(value = "/path", method = RequestMethod.GET) + public String readData() { + // No state-changing operations performed within this method. + return ""; + } + // {/fact} + + /** + * For state-changing methods use either + * RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, or RequestMethod.PATCH. + */ + // {fact rule=coral-csrf-rule@v1.0 defects=0} + + // ok: unrestricted-request-mapping + @RequestMapping(value = "/path", method = RequestMethod.POST) + public void writeData3() { + // State-changing operations performed within this method. + } + // {/fact} +} diff --git a/PR_5_java/java/filtered_java/43_HttpRequestDebugFilter.java b/PR_5_java/java/filtered_java/43_HttpRequestDebugFilter.java new file mode 100644 index 0000000..c483196 --- /dev/null +++ b/PR_5_java/java/filtered_java/43_HttpRequestDebugFilter.java @@ -0,0 +1,72 @@ +package jboss.security; + +import java.io.IOException; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + +import javax.crypto.spec.IvParameterSpec; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.jboss.seam.log.Logging; +import org.jboss.seam.log.Log; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.security.core.userdetails.User; + +//seam-log-injection +public class HttpRequestDebugFilter implements Filter { + Log log = Logging.getLog(HttpRequestDebugFilter.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, + ServletException { + + if (request instanceof HttpServletRequest) { + HttpServletRequest httpRequest = (HttpServletRequest)request; + if (httpRequest.getRequestURI().endsWith(".seam")) { + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: seam-log-injection + log.info("request: method="+httpRequest.getMethod()+", URL="+httpRequest.getRequestURI()); + } + // {/fact} + } + + chain.doFilter(request, response); + } + + @Override + public void destroy() { + + } + + public void logUser(@RequestParam("input") User user) { + // {fact rule=code-injection@v1.0 defects=1} + // ruleid: seam-log-injection + log.info("Current logged in user : " + user.getUsername()); + } + // {/fact} + + public void logUserEx(@RequestParam("input") User user) { + // {fact rule=code-injection@v1.0 defects=0} + // ok: seam-log-injection + log.info("Current logged in user : #0", user.getUsername()); + } + + public void init(int encryptMode, Object skeySpec, IvParameterSpec staticIvSpec, SecureRandom secureRandom) { + } + // {/fact} + +} diff --git a/PR_5_java/java/filtered_java/44_Constants.java b/PR_5_java/java/filtered_java/44_Constants.java new file mode 100644 index 0000000..e7fd241 --- /dev/null +++ b/PR_5_java/java/filtered_java/44_Constants.java @@ -0,0 +1,16 @@ +package org.sasanlabs.vulnerability.utils; + +/** @author KSASAN preetkaran20@gmail.com */ +public interface Constants { + + String NULL_BYTE_CHARACTER = String.valueOf((char) 0); + String EYE_CATCHER = "0W45pz4p"; + + // Constant used by SQLInjection Vulnerability + String ID = "id"; + String LOCALHOST = "localhost"; + + static String getEyeCatcher() { + return EYE_CATCHER; + } +} \ No newline at end of file diff --git a/PR_5_java/java/filtered_java/45_SourceUtils.java b/PR_5_java/java/filtered_java/45_SourceUtils.java new file mode 100644 index 0000000..b085b02 --- /dev/null +++ b/PR_5_java/java/filtered_java/45_SourceUtils.java @@ -0,0 +1,90 @@ +/** +* OWASP Benchmark Project +* +* This file is part of the Open Web Application Security Project (OWASP) +* Benchmark Project For details, please see +* https://www.owasp.org/index.php/Benchmark. +* +* The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms +* of the GNU General Public License as published by the Free Software Foundation, version 2. +* +* The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without +* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details +* +* @author Dave Wichers Aspect Security +* @created 2015 +*/ + +package org.owasp.benchmark.helpers; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.List; + +public class SourceUtils { + + public static final String USERDIR = System.getProperty("user.dir"); + + public static String getCookie( HttpServletRequest request, String paramName ) { + Cookie[] values = request.getCookies(); + String param = "none"; + if (paramName != null) { + int i = 0; + while (i < values.length) + { + if (values[i].getName().equals(paramName)) { + param = values[i].getValue(); + break; + } + i++; + } + } + return param; + } + + public static String getParam( HttpServletRequest request, String paramName ) { + String param = request.getParameter(paramName); + return param; + } + + public static List getLinesFromFile(String f) { + + File file = new File(f); + + if (!file.exists()) { + System.out.println("Can't find file to get lines from: " + f); + return null; + } + + FileReader fr = null; + BufferedReader br = null; + + List sourceLines = new ArrayList(); + + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while ((line = br.readLine()) != null) { + sourceLines.add(line); + } + } catch (Exception e) { + // + } finally { + try { + if (br != null) + br.close(); + if (fr != null) + fr.close(); + } catch (Exception ex) { + } + } + + return sourceLines; + } +} diff --git a/PR_5_java/java/filtered_java/46_do_privileged_use.java b/PR_5_java/java/filtered_java/46_do_privileged_use.java new file mode 100644 index 0000000..5457c85 --- /dev/null +++ b/PR_5_java/java/filtered_java/46_do_privileged_use.java @@ -0,0 +1,57 @@ +package lang.security; + +import java.security.*; + +class NoReturnNoException { + + // {fact rule=improper-privilege-management@v1.0 defects=1} + // ruleid: do-privileged-use + class MyAction implements PrivilegedAction { + public Void run() { + // Privileged code goes here, for example: + System.loadLibrary("awt"); + return null; // nothing to return + } + } + // {/fact} + + public void somemethod() { + + MyAction mya = new MyAction(); + + // {fact rule=improper-privilege-management@v1.0 defects=1} + // Become privileged: + // ruleid: do-privileged-use + AccessController.doPrivileged(mya); + // {/fact} + + // Anonymous class + // {fact rule=improper-privilege-management@v1.0 defects=1} + // ruleid: do-privileged-use + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + // Privileged code goes here, for example: + System.loadLibrary("awt"); + return null; // nothing to return + } + }); + // {/fact} + + // Lambda expression + // {fact rule=improper-privilege-management@v1.0 defects=1} + // ruleid: do-privileged-use + AccessController.doPrivileged((PrivilegedAction) + () -> { + // Privileged code goes here, for example: + System.loadLibrary("awt"); + return null; // nothing to return + } + ); + // {/fact} + } + + public static void main(String... args) { + NoReturnNoException myApplication = new NoReturnNoException(); + myApplication.somemethod(); + } +} diff --git a/PR_5_java/java/filtered_java/47_ldap_entry_poisoning.java b/PR_5_java/java/filtered_java/47_ldap_entry_poisoning.java new file mode 100644 index 0000000..bafa9d4 --- /dev/null +++ b/PR_5_java/java/filtered_java/47_ldap_entry_poisoning.java @@ -0,0 +1,52 @@ +package lang.security.audit;/* +package lang.security.audit; + +import com.amazonaws.services.lambda.model.Environment; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; + +import static com.sun.java.util.jar.pack.Attribute.attributes; +import static java.security.IdentityScope.scope; + + +class Cls { + + long countLimit = 0; + int timeLimit = 0; + String[] attributes = new String[0]; + DirContext ctx = new InitialDirContext(); + String query = null; + String filter = null; + boolean deref = false; + + Cls() throws NamingException { + } + + public void ldapSearchEntryPoison(Environment env) throws NamingException { + + + // ruleid:ldap-entry-poisoning + ctx.search(query, filter, new SearchControls(scope, countLimit, timeLimit, attributes, + true, //Enable object deserialization if bound in directory + deref)); + } + + public void ldapSearchEntryPoisonViaSetter(Environment env) throws NamingException { + DirContext ctx = new InitialDirContext(); + // ruleid:ldap-entry-poisoning + SearchControls ctrls = new SearchControls(); + ctrls.setReturningObjFlag(true); + } + + public void ldapSearchSafe(Environment env) throws NamingException { + DirContext ctx = new InitialDirContext(); + ctx.search(query, filter, + new SearchControls(scope, countLimit, timeLimit, attributes, + false, //Disable + deref)); + } +} +*/ diff --git a/PR_5_java/java/filtered_java/48_CommandInjectionProcessBuilder.java b/PR_5_java/java/filtered_java/48_CommandInjectionProcessBuilder.java new file mode 100644 index 0000000..4b554ab --- /dev/null +++ b/PR_5_java/java/filtered_java/48_CommandInjectionProcessBuilder.java @@ -0,0 +1,81 @@ +package lang.security.audit; + +import jaxrs.security.Pair; +import org.apache.log4j.Logger; +import org.springframework.web.bind.annotation.RequestParam; + +import java.io.IOException; + +public class CommandInjectionProcessBuilder { + + public Process test1(String command, Logger logAppender) throws IOException { + String[] cmd = new String[3]; + String osName = System.getProperty("os.name"); + if (osName.startsWith("Windows")) { + cmd[0] = "cmd.exe"; + cmd[1] = "/C"; + } else { + cmd[0] = "/bin/bash"; + cmd[1] = "-c"; + } + cmd[2] = command; + + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: command-injection-process-builder + ProcessBuilder builder = new ProcessBuilder(cmd); + builder.redirectErrorStream(true); + Process proc = builder.start(); + return proc; + } + // {/fact} + + public String test2(String userInput) { + ProcessBuilder builder = new ProcessBuilder(); + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: command-injection-process-builder + builder.command(userInput); + return "foo"; + } + // {/fact} + + public String test3(String userInput) { + ProcessBuilder builder = new ProcessBuilder(); + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: command-injection-process-builder + builder.command("bash", "-c", userInput); + return "foo"; + } + // {/fact} + + public String test4(String userInput) { + ProcessBuilder builder = new ProcessBuilder(); + // {fact rule=os-command-injection@v1.0 defects=1} + // ruleid: command-injection-process-builder + builder.command("cmd", "/c", userInput); + return "foo"; + } + // {/fact} + + public String okTest() { + ProcessBuilder builder = new ProcessBuilder(); + // {fact rule=os-command-injection@v1.0 defects=0} + // ok: command-injection-process-builder + builder.command("bash", "-c", "ls"); + return "foo"; + } + // {/fact} + + +} + +class CommandInjectionProcessBuilderDriver { + public void drive(@RequestParam("input") String input) throws IOException { + CommandInjectionProcessBuilder obj = new CommandInjectionProcessBuilder(); + obj.test1(input, Logger.getLogger("logger")); + obj.test2(input); + obj.test3(input); + obj.test4(input); + obj.okTest(); + } +} + diff --git a/PR_5_java/java/filtered_java/49_tainted_session_from_http_request.java b/PR_5_java/java/filtered_java/49_tainted_session_from_http_request.java new file mode 100644 index 0000000..6ed367c --- /dev/null +++ b/PR_5_java/java/filtered_java/49_tainted_session_from_http_request.java @@ -0,0 +1,173 @@ +/** + * OWASP Benchmark v1.2 + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Dave Wichers + * @created 2015 + */ +package lang.security.audit; + +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 = "/trustbound-00/BenchmarkTest00004") +class BenchmarkTest00004Ex extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + javax.servlet.http.Cookie userCookie = + new javax.servlet.http.Cookie("BenchmarkTest00004", "color"); + userCookie.setMaxAge(60 * 3); // Store cookie for 3 minutes + userCookie.setSecure(true); + userCookie.setPath(request.getRequestURI()); + userCookie.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost()); + response.addCookie(userCookie); + javax.servlet.RequestDispatcher rd = + request.getRequestDispatcher("/trustbound-00/BenchmarkTest00004.html"); + rd.include(request, response); + } + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // some code + response.setContentType("text/html;charset=UTF-8"); + + javax.servlet.http.Cookie[] theCookies = request.getCookies(); + + String param = "noCookieValueSupplied"; + if (theCookies != null) { + for (javax.servlet.http.Cookie theCookie : theCookies) { + if (theCookie.getName().equals("BenchmarkTest00004")) { + param = java.net.URLDecoder.decode(theCookie.getValue(), "UTF-8"); + break; + } + } + } + + // javax.servlet.http.HttpSession.setAttribute(java.lang.String^,java.lang.Object) + // {fact rule=resource-leak@v1.0 defects=1} + // ruleid: tainted-session-from-http-request + request.getSession().setAttribute(param, "10340"); + + response.getWriter() + .println( + "Item: '" + + org.owasp.benchmark.helpers.Utils.encodeForHTML(param) + + "' with value: '10340' saved in session."); + } + // {/fact} +} + +@WebServlet(value = "/trustbound-00/BenchmarkTest00321") + class BenchmarkTest00321 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 { + response.setContentType("text/html;charset=UTF-8"); + + String param = ""; + java.util.Enumeration headers = request.getHeaders("BenchmarkTest00321"); + + if (headers != null && headers.hasMoreElements()) { + param = headers.nextElement(); // just grab first element + } + + // URL Decode the header value since req.getHeaders() doesn't. Unlike req.getParameters(). + param = java.net.URLDecoder.decode(param, "UTF-8"); + + String bar = org.owasp.esapi.ESAPI.encoder().encodeForHTML(param); + + // javax.servlet.http.HttpSession.putValue(java.lang.String^,java.lang.Object) + // {fact rule=resource-leak@v1.0 defects=1} + // ruleid: tainted-session-from-http-request + request.getSession().putValue(bar, "10340"); + + response.getWriter() + .println( + "Item: '" + + org.owasp.benchmark.helpers.Utils.encodeForHTML(bar) + + "' with value: 10340 saved in session."); + } + // {/fact} +} + +@WebServlet(value = "/trustbound-00/BenchmarkTest00004") + class BenchmarkTest00004 extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + javax.servlet.http.Cookie userCookie = + new javax.servlet.http.Cookie("BenchmarkTest00004", "color"); + userCookie.setMaxAge(60 * 3); // Store cookie for 3 minutes + userCookie.setSecure(true); + userCookie.setPath(request.getRequestURI()); + userCookie.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost()); + response.addCookie(userCookie); + javax.servlet.RequestDispatcher rd = + request.getRequestDispatcher("/trustbound-00/BenchmarkTest00004.html"); + rd.include(request, response); + } + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // some code + response.setContentType("text/html;charset=UTF-8"); + + javax.servlet.http.Cookie[] theCookies = request.getCookies(); + + String param = "noCookieValueSupplied"; + if (theCookies != null) { + for (javax.servlet.http.Cookie theCookie : theCookies) { + if (theCookie.getName().equals("BenchmarkTest00004")) { + param = java.net.URLDecoder.decode("hello", "UTF-8"); + break; + } + } + } + + // javax.servlet.http.HttpSession.setAttribute(java.lang.String^,java.lang.Object) + // {fact rule=resource-leak@v1.0 defects=0} + // ok: tainted-session-from-http-request + request.getSession().setAttribute(param, "10340"); + + response.getWriter() + .println( + "Item: '" + + org.owasp.benchmark.helpers.Utils.encodeForHTML(param) + + "' with value: '10340' saved in session."); + } + // {/fact} +} diff --git a/PR_5_java/java/filtered_java/50_formatted_sql_string.java b/PR_5_java/java/filtered_java/50_formatted_sql_string.java new file mode 100644 index 0000000..c730e4f --- /dev/null +++ b/PR_5_java/java/filtered_java/50_formatted_sql_string.java @@ -0,0 +1,187 @@ +// cf. https://www.baeldung.com/sql-injection + +package lang.security.audit; +import com.squareup.okhttp.Call; +import lang.security.audit.xxe.Account; +import lang.security.audit.xxe.ApiClient; +import lang.security.audit.xxe.ApiException; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.stream.Collectors; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.TypedQuery; + +import org.springframework.web.bind.annotation.RequestParam; + +class SqlExample { + EntityManagerFactory emfactory; + public void staticQuery() throws SQLException { + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=0} + // ok:formatted-sql-string + ResultSet rs = c.createStatement().executeQuery("SELECT * FROM happy_messages"); + } + // {/fact} + + public void getAllFields(@RequestParam("tableName") String tableName) throws SQLException { + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:formatted-sql-string + ResultSet rs = c.createStatement().executeQuery("SELECT * FROM " + tableName); + } + // {/fact} + + public void findAccountsById(@RequestParam("id") String id) throws SQLException { + String sql = "SELECT * " + + "FROM accounts WHERE id = '" + + id + + "'"; + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:formatted-sql-string + ResultSet rs = c.createStatement().executeQuery(sql); + } + // {/fact} + + public void findAccountsById(@RequestParam("id") String id, @RequestParam("field") String field) throws SQLException { + String sql = "SELECT "; + sql += field; + sql += " FROM accounts WHERE id = '"; + sql += id; + sql += "'"; + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:formatted-sql-string + ResultSet rs = c.createStatement().executeQuery(sql); + } + // {/fact} +} + +class SqlExample2 { + EntityManagerFactory emfactory; + public void getAllFields(@RequestParam("tableName") String tableName) throws SQLException { + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:formatted-sql-string + Boolean rs = c.createStatement().execute("SELECT * FROM " + tableName); + } + // {/fact} + + public void findAccountsById2(@RequestParam("id") String id) throws SQLException { + String sql = "SELECT * " + + "FROM accounts WHERE id = '" + + id + + "'"; + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:formatted-sql-string + Boolean rs = c.createStatement().execute(sql); + } + // {/fact} + + public List findAccountsById(@RequestParam("id") String id) { + String jql = "from Account where id = '" + id + "'"; + EntityManager em = emfactory.createEntityManager(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:formatted-sql-string + TypedQuery q = em.createQuery(jql, Account.class); + return q.getResultList() + .stream() + .map(this::toAccountDTO) + .collect(Collectors.toList()); + } + // {/fact} + + private AccountDTO toAccountDTO(Account account) { + return new AccountDTO(); + } +} + +class SQLExample3 { + EntityManagerFactory emfactory; + public void getAllFields(@RequestParam("tableName") String tableName) throws SQLException { + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:formatted-sql-string + Boolean rs = c.createStatement().execute(String.format("SELECT * FROM %s", tableName)); + } + // {/fact} + + public void findAccountsById2(@RequestParam("id") String id) throws SQLException { + String sql = String.format("SELECT * FROM accounts WHERE id = '%s'", id); + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid:formatted-sql-string + boolean rs = c.createStatement().execute(sql); + } + // {/fact} + + public List findAccountsById(@RequestParam("id") String id) { + String jql = String.format("from Account where id = '%s'", id); + EntityManager em = emfactory.createEntityManager(); + // {fact rule=sql-injection@v1.0 defects=1} + // ruleid: formatted-sql-string + TypedQuery q = em.createQuery(jql, Account.class); + return q.getResultList() + .stream() + .map(this::toAccountDTO) + .collect(Collectors.toList()); + } + // {/fact} + + private AccountDTO toAccountDTO(Account account) { + return new AccountDTO(); + } + + public void findAccountsByIdOk() throws SQLException { + String id = "const"; + String sql = String.format("SELECT * FROM accounts WHERE id = '%s'", id); + Connection c = DB.getConnection(); + // {fact rule=sql-injection@v1.0 defects=0} + // ok:formatted-sql-string + Boolean rs = c.createStatement().execute(sql); + } + // {/fact} + +} + +class tableConcatStatements { + private ApiClient stmt; + + public void tableConcat() { + Call tableName = null; + // {fact rule=sql-injection@v1.0 defects=0} + // ok:formatted-sql-string + stmt.execute("DROP TABLE " + tableName); + stmt.execute(String.format("CREATE TABLE %s", tableName)); + } + // {/fact} +} + +// This whole operation has nothing to do with SQL +class FalsePositiveCase { + private ApiClient apiClient; // imagine an ApiClient class that contains a method named execute + + public void test(String parameter) throws ApiException { + Call call = constructHttpCall(parameter); // Create OKHttp call using parameter from outside + // {fact rule=sql-injection@v1.0 defects=0} + // ok: formatted-sql-string + apiClient.execute(call); + // {/fact} + + // {fact rule=sql-injection@v1.0 defects=0} + // ok: formatted-sql-string + apiClient.execute(call); + apiClient.run(call); // proof that 'execute' name is causing the false-positive + // {/fact} + } + + private Call constructHttpCall(String parameter) { + return null; + } +} + diff --git a/PR_5_java/java/filtered_java/VULNERABILITY_SUMMARY.md b/PR_5_java/java/filtered_java/VULNERABILITY_SUMMARY.md new file mode 100644 index 0000000..6452d76 --- /dev/null +++ b/PR_5_java/java/filtered_java/VULNERABILITY_SUMMARY.md @@ -0,0 +1,56 @@ +# Filtered Java Files - Vulnerability Summary + +This folder contains 50 Java files filtered from the AWS Guru Java Security Benchmarks dataset based on the **Top 25 Most Dangerous Software Weaknesses (2023 CWE Top 25)**. + +## CWE Coverage + +The filtered files cover the following CWE vulnerabilities: + +### Input Validation Issues +- **CWE-79**: Cross-site Scripting (XSS) +- **CWE-89**: SQL Injection +- **CWE-78**: OS Command Injection +- **CWE-20**: Improper Input Validation +- **CWE-22**: Path Traversal +- **CWE-502**: Deserialization of Untrusted Data +- **CWE-77**: Command Injection +- **CWE-94**: Code Injection +- **CWE-918**: Server-Side Request Forgery (SSRF) + +### Buffer and Memory Issues +- **CWE-787**: Out-of-bounds Write +- **CWE-125**: Out-of-bounds Read +- **CWE-119**: Buffer Overflow +- **CWE-476**: NULL Pointer Dereference + +### Access Control Issues +- **CWE-352**: Cross-Site Request Forgery (CSRF) +- **CWE-434**: Unrestricted Upload of File +- **CWE-862**: Missing Authorization +- **CWE-287**: Improper Authentication +- **CWE-306**: Missing Authentication +- **CWE-269**: Improper Privilege Management +- **CWE-863**: Incorrect Authorization +- **CWE-276**: Incorrect Default Permissions + +### Other Security Issues +- **CWE-190**: Integer Overflow +- **CWE-798**: Use of Hard-coded Credentials +- **CWE-362**: Race Condition + +## File Selection Criteria + +Files were selected based on: +1. Presence of vulnerability patterns matching the Top 25 CWE list +2. Ranked by number of different CWE patterns found +3. Top 50 files with the most comprehensive vulnerability coverage + +## Usage + +These files can be used for: +- Security testing and validation +- Static analysis tool benchmarking +- Security training and education +- Vulnerability research + +Each file is prefixed with a number (01-50) to maintain order and avoid naming conflicts. \ No newline at end of file