├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src ├── main └── java │ └── com │ └── github │ └── rkpunjal │ └── sqlsafe │ ├── SQLInjectionSafe.java │ ├── SQLInjectionSafeValidator.java │ └── SqlSafeUtil.java └── test └── java └── com └── github └── rkpunjal └── sqlsafe └── SqlSafeUtilTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Intellij 2 | .idea 3 | *.iws 4 | *.class 5 | *.ids 6 | *.iml 7 | *.ipr 8 | *.iws 9 | .classpath 10 | 11 | target/ 12 | **/src/generated/ 13 | .idea/ 14 | .project 15 | .settings/ 16 | bin/ 17 | build/ 18 | classes/ 19 | work/ 20 | 21 | # Eclipse 22 | .classpath 23 | .project 24 | .settings/ 25 | 26 | 27 | # Maven 28 | log/ 29 | target/ 30 | 31 | # Package Files # 32 | *.jar 33 | *.war 34 | *.ear 35 | 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Annotation for SQL Injection Safe Parameters and fields, and Util for Sql-Injection-Safe check 2 | 3 | Through this library you get an annotation SQLInjectionSafe for validating if field-values or parameter-values are SQL-Injection safe. 4 | 5 | The library is **extremely light-weight** and has been thoroughly tested with various sql-injection-embedded data samples. 6 | 7 | To use this, include this dependency in your pom.xml 8 | 9 | 10 | com.github.rkpunjal.sqlsafe 11 | sql-injection-safe 12 | 1.0.2 13 | 14 | 15 | A usage could look something like this 16 | `private @SQLInjectionSafe String id;` 17 | 18 | or you can also use the utility method 19 | `SqlSafeUtil.isSqlInjectionSafe("my-string-value")` 20 | 21 | 22 | **For a Detailed Explanation on how this library works, refer to my article here:** 23 | [https://dzone.com/articles/custom-annotation-in-java-for-sql-injection-safe-p](https://dzone.com/articles/custom-annotation-in-java-for-sql-injection-safe-p) 24 | 25 | It's the same code that has been slightly enhanced and modified so that now you have the annotation directly for your own use. 26 | 27 | --- 28 | 29 | # Detail Explanation for usage in a Spring mvc controller 30 | 31 | You can also this used it in a spring mvc controller to validate the incoming request parameter. 32 | 33 | Spring MVC has it’s own way of running validators on RequestParameters. 34 | Hence you have to first create a wrapper class annotate your parameter. 35 | 36 | eg: 37 | 38 | public static class IdWrapper{ 39 | private @SQLInjectionSafe String id; 40 | public String getId() { 41 | return id; 42 | } 43 | public void setId(String id) { 44 | this.id = id; 45 | } 46 | } 47 | 48 | 49 | Then you can use the wrapper in your controller like this: 50 | 51 | 52 | @RequestMapping(value = "/getById) 53 | public MyResponseObject getById( 54 | @Valid @ModelAttribute() IdWrapper idWrapper){ 55 | // do your stuff 56 | } 57 | 58 | 59 | 60 | Now when you have a validation Failure on the incoming parameter, Spring throws a **BindException**. 61 | If not handeled, the BindException is sent across as response directly. 62 | 63 | To send a cleaner response, you can create an ExceptionHandler method in the controller. 64 | 65 | This could be something like this : 66 | 67 | @ExceptionHandler(BindException.class) 68 | public @ResponseBody WebResponse handleBindException(BindException be ){ 69 | return new MyResponseObject(false, 70 | getBindExceptionMessage(be) // custom method to find and send an appropriate response 71 | ); 72 | } 73 | 74 | 75 | the **getBindExceptionMessage** could look something like this 76 | 77 | public static final String INVALID_DATA_PROVIDED = "Invalid data provided"; 78 | public static final String ID_WRAPPER = "idWrapper"; 79 | 80 | protected String getBindExceptionMessage(BindException be){ 81 | 82 | if(be==null && be.getBindingResult()==null){ 83 | return INVALID_DATA_PROVIDED; 84 | } 85 | 86 | List errors = be.getBindingResult().getAllErrors(); 87 | 88 | if(errors==null || errors.isEmpty()){ 89 | return INVALID_DATA_PROVIDED; 90 | } 91 | 92 | for(ObjectError objectError : errors){ 93 | if(objectError instanceof FieldError){ 94 | if(ID_WRAPPER.equalsIgnoreCase(objectError.getObjectName())){ 95 | return "Invalid 'id' specified"; 96 | } 97 | } 98 | } 99 | 100 | return INVALID_DATA_PROVIDED; 101 | 102 | } 103 | 104 | Refer to these links to understand in detail why you need to create a wrapper class for the parametes. 105 | - [http://copyrightdev.tumblr.com/post/92560458673/tips-tricks-having-fun-with-spring-validators](http://copyrightdev.tumblr.com/post/92560458673/tips-tricks-having-fun-with-spring-validators) 106 | - [http://stackoverflow.com/questions/6203740/spring-web-mvc-validate-individual-request-params](http://stackoverflow.com/questions/6203740/spring-web-mvc-validate-individual-request-params) 107 | 108 | 109 | In case you have questions you can write to me. 110 | 111 | 112 | **For a Detailed Explanation on how this library works, refer to my article here: ** 113 | [https://dzone.com/articles/custom-annotation-in-java-for-sql-injection-safe-p](https://dzone.com/articles/custom-annotation-in-java-for-sql-injection-safe-p) -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.github.rkpunjal.sqlsafe 7 | sql-injection-safe 8 | 1.0.2 9 | jar 10 | 11 | SQL-Injection-Safe Annotation 12 | 13 | This is an extremely lightweight library that provides 14 | an Annotation and a Utility class to verify if the provided string value is Sql-Injection-safe. 15 | This is backed by thorough and intelligent unit-tests. 16 | 17 | https://github.com/rkpunjal/sql-injection-safe 18 | 19 | 20 | 21 | MIT License 22 | http://www.opensource.org/licenses/mit-license.php 23 | repo 24 | 25 | 26 | 27 | 28 | 29 | Ramakrishna Punjal 30 | rkpunjal@gmail.com 31 | 32 | 33 | 34 | 35 | 1.8 36 | UTF-8 37 | 1.1.0.Final 38 | 4.12 39 | 40 | 41 | 42 | scm:git:git@github.com:rkpunjal/sql-injection-safe.git 43 | scm:git:git@github.com:rkpunjal/sql-injection-safe.git 44 | git@github.com:rkpunjal/sql-injection-safe.git 45 | 46 | 47 | 48 | 49 | 50 | javax.validation 51 | validation-api 52 | ${javax.validation.version} 53 | 54 | 55 | 56 | junit 57 | junit 58 | ${junit.version} 59 | test 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | ossrh 68 | https://oss.sonatype.org/content/repositories/snapshots 69 | 70 | 71 | ossrh 72 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | org.sonatype.plugins 81 | nexus-staging-maven-plugin 82 | 1.6.7 83 | true 84 | 85 | ossrh 86 | https://oss.sonatype.org/ 87 | false 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-source-plugin 94 | 2.2.1 95 | 96 | 97 | attach-sources 98 | 99 | jar-no-fork 100 | 101 | 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-javadoc-plugin 107 | 2.9.1 108 | 109 | 110 | attach-javadocs 111 | 112 | jar 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | org.apache.maven.plugins 121 | maven-release-plugin 122 | 2.5 123 | 124 | false 125 | release 126 | deploy 127 | 128 | 129 | 130 | 131 | org.apache.maven.plugins 132 | maven-gpg-plugin 133 | 1.6 134 | 135 | 136 | sign-artifacts 137 | verify 138 | 139 | sign 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /src/main/java/com/github/rkpunjal/sqlsafe/SQLInjectionSafe.java: -------------------------------------------------------------------------------- 1 | package com.github.rkpunjal.sqlsafe; 2 | 3 | import javax.validation.Constraint; 4 | import javax.validation.Payload; 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | *

SQLInjectionSafe

9 | * Annotation to help verify if the annotated string field or parameter is sql injection safe 10 | * 11 | * @author Ramakrishna Punjal 12 | * @version 1.0.0 13 | * @since 2016-08-26 14 | * 15 | */ 16 | @Documented 17 | @Constraint(validatedBy = SQLInjectionSafeValidator.class) 18 | @Target( { ElementType.FIELD, ElementType.PARAMETER}) 19 | @Retention(RetentionPolicy.RUNTIME) 20 | public @interface SQLInjectionSafe { 21 | 22 | String message() default "{SQLInjectionSafe}"; 23 | 24 | Class[] groups() default {}; 25 | 26 | Class[] payload() default {}; 27 | 28 | } -------------------------------------------------------------------------------- /src/main/java/com/github/rkpunjal/sqlsafe/SQLInjectionSafeValidator.java: -------------------------------------------------------------------------------- 1 | package com.github.rkpunjal.sqlsafe; 2 | 3 | import javax.validation.ConstraintValidator; 4 | import javax.validation.ConstraintValidatorContext; 5 | 6 | /** 7 | *

SQLInjectionSafeValidator

8 | * The Constraint validator for for the annotation SQLInjectionSafe 9 | * 10 | * @author Ramakrishna Punjal 11 | * @version 1.0.0 12 | * @since 2016-08-26 13 | * @see SQLInjectionSafe 14 | * 15 | */ 16 | public class SQLInjectionSafeValidator implements ConstraintValidator { 17 | 18 | public void initialize(SQLInjectionSafe sqlInjectionSafe) { } 19 | 20 | public boolean isValid(String dataString, ConstraintValidatorContext cxt) { 21 | return SqlSafeUtil.isSqlInjectionSafe(dataString); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/com/github/rkpunjal/sqlsafe/SqlSafeUtil.java: -------------------------------------------------------------------------------- 1 | package com.github.rkpunjal.sqlsafe; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | *

SqlSafeUtil

10 | * Util Class to help verify if provided string value is sql injection safe 11 | * 12 | * @author Ramakrishna Punjal 13 | * @version 1.0.0 14 | * @since 2016-08-26 15 | * 16 | */ 17 | public class SqlSafeUtil { 18 | 19 | private static final String SQL_TYPES = 20 | "TABLE, TABLESPACE, PROCEDURE, FUNCTION, TRIGGER, KEY, VIEW, MATERIALIZED VIEW, LIBRARY" + 21 | "DATABASE LINK, DBLINK, INDEX, CONSTRAINT, TRIGGER, USER, SCHEMA, DATABASE, PLUGGABLE DATABASE, BUCKET, " + 22 | "CLUSTER, COMMENT, SYNONYM, TYPE, JAVA, SESSION, ROLE, PACKAGE, PACKAGE BODY, OPERATOR" + 23 | "SEQUENCE, RESTORE POINT, PFILE, CLASS, CURSOR, OBJECT, RULE, USER, DATASET, DATASTORE, " + 24 | "COLUMN, FIELD, OPERATOR"; 25 | 26 | private static final String[] SQL_REGEXPS = { 27 | "(?i)(.*)(\\b)+(OR|AND)(\\s)+(true|false)(\\s)*(.*)", 28 | "(?i)(.*)(\\b)+(OR|AND)(\\s)+(\\w)(\\s)*(\\=)(\\s)*(\\w)(\\s)*(.*)", 29 | "(?i)(.*)(\\b)+(OR|AND)(\\s)+(equals|not equals)(\\s)+(true|false)(\\s)*(.*)", 30 | "(?i)(.*)(\\b)+(OR|AND)(\\s)+([0-9A-Za-z_'][0-9A-Za-z\\d_']*)(\\s)*(\\=)(\\s)*([0-9A-Za-z_'][0-9A-Za-z\\d_']*)(\\s)*(.*)", 31 | "(?i)(.*)(\\b)+(OR|AND)(\\s)+([0-9A-Za-z_'][0-9A-Za-z\\d_']*)(\\s)*(\\!\\=)(\\s)*([0-9A-Za-z_'][0-9A-Za-z\\d_']*)(\\s)*(.*)", 32 | "(?i)(.*)(\\b)+(OR|AND)(\\s)+([0-9A-Za-z_'][0-9A-Za-z\\d_']*)(\\s)*(\\<\\>)(\\s)*([0-9A-Za-z_'][0-9A-Za-z\\d_']*)(\\s)*(.*)", 33 | "(?i)(.*)(\\b)+SELECT(\\b)+\\s.*(\\b)(.*)", 34 | // "(?i)(.*)(\\b)+SELECT(\\b)+\\s.*(\\b)+FROM(\\b)+\\s.*(.*)", 35 | "(?i)(.*)(\\b)+INSERT(\\b)+\\s.*(\\b)+INTO(\\b)+\\s.*(.*)", 36 | "(?i)(.*)(\\b)+UPDATE(\\b)+\\s.*(.*)", 37 | "(?i)(.*)(\\b)+DELETE(\\b)+\\s.*(\\b)+FROM(\\b)+\\s.*(.*)", 38 | "(?i)(.*)(\\b)+UPSERT(\\b)+\\s.*(.*)", 39 | "(?i)(.*)(\\b)+SAVEPOINT(\\b)+\\s.*(.*)", 40 | "(?i)(.*)(\\b)+CALL(\\b)+\\s.*(.*)", 41 | "(?i)(.*)(\\b)+ROLLBACK(\\b)+\\s.*(.*)", 42 | "(?i)(.*)(\\b)+KILL(\\b)+\\s.*(.*)", 43 | "(?i)(.*)(\\b)+DROP(\\b)+\\s.*(.*)", 44 | "(?i)(.*)(\\b)+CREATE(\\b)+(\\s)*(" + SQL_TYPES.replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", 45 | "(?i)(.*)(\\b)+ALTER(\\b)+(\\s)*(" + SQL_TYPES.replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", 46 | "(?i)(.*)(\\b)+TRUNCATE(\\b)+(\\s)*(" + SQL_TYPES.replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", 47 | "(?i)(.*)(\\b)+LOCK(\\b)+(\\s)*(" + SQL_TYPES.replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", 48 | "(?i)(.*)(\\b)+UNLOCK(\\b)+(\\s)*(" + SQL_TYPES.replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", 49 | "(?i)(.*)(\\b)+RELEASE(\\b)+(\\s)*(" + SQL_TYPES.replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", 50 | "(?i)(.*)(\\b)+DESC(\\b)+(\\w)*\\s.*(.*)", 51 | "(?i)(.*)(\\b)+DESCRIBE(\\b)+(\\w)*\\s.*(.*)", 52 | "(.*)(/\\*|\\*/|;){1,}(.*)", 53 | "(.*)(-){2,}(.*)", 54 | 55 | }; 56 | 57 | 58 | // pre-build the Pattern objects for faster validation 59 | // private static final List validationPatterns = buildValidationPatterns(); 60 | private static final List validationPatterns = buildPatterns(SQL_REGEXPS); 61 | 62 | /** 63 | * Determines if the provided string value is SQL-Injection-safe. 64 | *

65 | * Empty value is considered safe. 66 | * This is used in by the SqlInjectionSafe annotation. 67 | * 68 | * @param dataString string value that is to verified 69 | * @return 'true' for safe and 'false' for unsafe 70 | */ 71 | public static boolean isSqlInjectionSafe(String dataString){ 72 | if(isEmpty(dataString)){ 73 | return true; 74 | } 75 | 76 | for(Pattern pattern : validationPatterns){ 77 | if(matches(pattern, dataString)){ 78 | return false; 79 | } 80 | } 81 | return true; 82 | } 83 | 84 | private static boolean matches(Pattern pattern, String dataString){ 85 | Matcher matcher = pattern.matcher(dataString); 86 | return matcher.matches(); 87 | } 88 | 89 | private static List buildPatterns(String[] expressionStrings){ 90 | List patterns = new ArrayList(); 91 | for(String expression : expressionStrings){ 92 | patterns.add(getPattern(expression)); 93 | } 94 | return patterns; 95 | } 96 | 97 | 98 | private static Pattern getPattern(String regEx){ 99 | return Pattern.compile(regEx, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); 100 | } 101 | 102 | private static boolean isEmpty(CharSequence cs) { 103 | return cs == null || cs.length() == 0; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/test/java/com/github/rkpunjal/sqlsafe/SqlSafeUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.github.rkpunjal.sqlsafe; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | import static org.junit.Assert.assertFalse; 9 | import static org.junit.Assert.assertTrue; 10 | 11 | public class SqlSafeUtilTest { 12 | 13 | private static final String SPACES_REGEX = "[\\s|\\r|\\n|\\t]"; 14 | private static final String EMPTY = ""; 15 | 16 | @Test 17 | public void testWithBadData(){ 18 | String[] maliciousDataSamples = { 19 | "select adf from abc", 20 | "insert into abcd", 21 | "update abcd", 22 | "delete from abcd", 23 | "upsert abcd", 24 | "call abcd", 25 | "rollback ", 26 | "create table abc", 27 | "drop table", 28 | "drop view", 29 | "alter table abc", 30 | "truncate table abc", 31 | "desc abc", 32 | "select id", 33 | "select 'abc'", 34 | }; 35 | 36 | for(String maliciousPart : maliciousDataSamples){ 37 | testUnSafeWithAllVariations(maliciousPart); 38 | } 39 | 40 | 41 | String[] sqlDisruptiveDataSamples = { 42 | "--", 43 | "/*", 44 | "*/", 45 | ";", 46 | "someone -- abcd", 47 | "abcd /* adf */ adf", 48 | }; 49 | 50 | 51 | for(String desruptivePart : sqlDisruptiveDataSamples){ 52 | testForPurelyUnSafeDataWithAllVariations(desruptivePart); 53 | } 54 | 55 | 56 | 57 | } 58 | 59 | @Test 60 | public void testWithGoodData(){ 61 | String[] safeDataSamples = { 62 | "12", 63 | "abcd123", 64 | "123abcd", 65 | "abcd", 66 | " OR adfadfa adf column1 = COLUMN1", 67 | " and adfadfa adf column1 = COLUMN1", 68 | }; 69 | 70 | for(String safeData : safeDataSamples){ 71 | assertTrue("Failed to qualify this as SQL-injection safe data : " + safeData, 72 | SqlSafeUtil.isSqlInjectionSafe(safeData) 73 | ); 74 | } 75 | 76 | } 77 | 78 | @Test 79 | public void testForEqualsInjection(){ 80 | 81 | String[] maliciousSamples = { 82 | " OR false ", 83 | " OR true ", 84 | " and true ", 85 | " OR equals true ", 86 | " OR not equals true ", 87 | " OR equals false ", 88 | " and equals false ", 89 | " OR 1=1", 90 | " and 1=1", 91 | " OR column1=COLUMN1", 92 | " OR column1 = COLUMN1", 93 | " OR column1!=COLUMN1", 94 | " OR column1<>COLUMN1", 95 | " OR colu_mn1=COL_UMN1", 96 | " OR 'A'='A'", 97 | " OR '1afA'='2fadfA'", 98 | " OR 1=1 OR 2=2", 99 | " OR 1=1 and 2=2", 100 | " and 1=1 and 2=2", 101 | " and 1=1 or 2=2", 102 | }; 103 | 104 | for(String maliciousData : maliciousSamples){ 105 | testForPurelyUnSafeDataWithAllVariationsExcludeEmptySpacesCheck(maliciousData); 106 | } 107 | 108 | } 109 | 110 | 111 | private void testUnSafeWithAllVariations(String maliciousPart) { 112 | String prefix = "some-Data-prefix"; 113 | String suffix = "some-Data-suffix"; 114 | String space = " "; 115 | 116 | String maliciousData = ""; 117 | String safeData = ""; 118 | 119 | maliciousData = prefix + space + maliciousPart + space + suffix; 120 | 121 | assertFalse("Failed to detect SQL-unsafe data : " + maliciousData, 122 | SqlSafeUtil.isSqlInjectionSafe(maliciousData) 123 | ); 124 | 125 | assertFalse("Failed to detect SQL-unsafe data : " + maliciousData.toUpperCase(), 126 | SqlSafeUtil.isSqlInjectionSafe(maliciousData.toUpperCase()) 127 | ); 128 | 129 | safeData = prefix + maliciousPart + suffix; 130 | 131 | assertTrue("Failed to qualify this as SQL-injection safe data : " + safeData, 132 | SqlSafeUtil.isSqlInjectionSafe(safeData) 133 | ); 134 | 135 | safeData = removeAllSpaces(maliciousData); 136 | assertTrue("Failed to qualify this as SQL-injection safe data : " + safeData, 137 | SqlSafeUtil.isSqlInjectionSafe(safeData) 138 | ); 139 | 140 | prefix = ""; 141 | suffix = ""; 142 | maliciousData = prefix + maliciousPart + suffix; 143 | 144 | assertFalse("Failed to detect SQL-unsafe data : " + maliciousData, 145 | SqlSafeUtil.isSqlInjectionSafe(maliciousData) 146 | ); 147 | 148 | 149 | safeData = removeAllSpaces(maliciousData); 150 | assertTrue("Failed to qualify this as SQL-injection safe data : " + safeData, 151 | SqlSafeUtil.isSqlInjectionSafe(safeData) 152 | ); 153 | 154 | } 155 | 156 | private void testForPurelyUnSafeDataWithAllVariations(String maliciousPart, boolean emptySpaceCheckRequired) { 157 | String prefix = "some-Data-prefix"; 158 | String suffix = "some-Data-suffix"; 159 | String space = " "; 160 | 161 | String maliciousData = ""; 162 | String safeData = ""; 163 | 164 | maliciousData = prefix + space + maliciousPart + space + suffix; 165 | 166 | assertFalse("Failed to detect SQL-unsafe data : " + maliciousData, 167 | SqlSafeUtil.isSqlInjectionSafe(maliciousData) 168 | ); 169 | 170 | assertFalse("Failed to detect SQL-unsafe data : " + maliciousData.toUpperCase(), 171 | SqlSafeUtil.isSqlInjectionSafe(maliciousData.toUpperCase()) 172 | ); 173 | 174 | if(emptySpaceCheckRequired) { 175 | assertFalse("Failed to detect SQL-unsafe data : " + removeAllSpaces(maliciousData), 176 | SqlSafeUtil.isSqlInjectionSafe(removeAllSpaces(maliciousData)) 177 | ); 178 | } 179 | 180 | prefix = ""; 181 | suffix = ""; 182 | maliciousData = prefix + maliciousPart + suffix; 183 | 184 | assertFalse("Failed to detect SQL-unsafe data : " + maliciousData, 185 | SqlSafeUtil.isSqlInjectionSafe(maliciousData) 186 | ); 187 | 188 | if(emptySpaceCheckRequired){ 189 | assertFalse("Failed to detect SQL-unsafe data : " + removeAllSpaces(maliciousData), 190 | SqlSafeUtil.isSqlInjectionSafe(removeAllSpaces(maliciousData)) 191 | ); 192 | } 193 | 194 | } 195 | 196 | private void testForPurelyUnSafeDataWithAllVariations(String maliciousPart) { 197 | testForPurelyUnSafeDataWithAllVariations(maliciousPart, true); 198 | } 199 | 200 | 201 | private void testForPurelyUnSafeDataWithAllVariationsExcludeEmptySpacesCheck(String maliciousPart) { 202 | testForPurelyUnSafeDataWithAllVariations(maliciousPart, false); 203 | 204 | } 205 | 206 | private String removeAllSpaces(String str){ 207 | Pattern pattern = Pattern.compile(SPACES_REGEX); 208 | Matcher matcher = pattern.matcher(str); 209 | return matcher.replaceAll(EMPTY); 210 | } 211 | 212 | } 213 | 214 | 215 | --------------------------------------------------------------------------------