diff --git a/docs/header_names/allowed_framework_names.adoc b/docs/header_names/allowed_framework_names.adoc index e530f53263..3c2fa3403d 100644 --- a/docs/header_names/allowed_framework_names.adoc +++ b/docs/header_names/allowed_framework_names.adoc @@ -28,6 +28,7 @@ * JSP * Servlet * Spring +* Spring Data Redis * Thymeleaf * Java SE * Java EE diff --git a/rules/S5147/java/how-to-fix-it/spring-data-redis.adoc b/rules/S5147/java/how-to-fix-it/spring-data-redis.adoc new file mode 100644 index 0000000000..d20c22217b --- /dev/null +++ b/rules/S5147/java/how-to-fix-it/spring-data-redis.adoc @@ -0,0 +1,59 @@ +== How to fix it in Spring Data Redis + +=== Code examples + +The following code is vulnerable to NoSQL injections because untrusted data is +concatenated to a Redis script. Such a script is used to perform advanced +queries on a Redis instance so that an injection in it might result in the +compromise of the Redis instance. + +==== Noncompliant code example + +[source,java,diff-id=2,diff-type=noncompliant] +---- +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.RedisScript; + +@RestController +@RequestMapping(path = "/redis") +public class RedisController { + + @Autowired RedisTemplate redisTemplate; + + @GetMapping("/template/redisscript/echo/{echo}") + public String templateRedisScriptCompliant(@PathVariable String echo) { + String script = "return " + echo + ";"; + Object result = redisTemplate.execute(RedisScript.of(script, Object.class), new ArrayList()); // Noncompliant + return result.toString(); + } +} +---- + +==== Compliant solution + +[source,java,diff-id=2,diff-type=compliant] +---- +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.RedisScript; + +@RestController +@RequestMapping(path = "/redis") +public class RedisController { + + @Autowired RedisTemplate redisTemplate; + + @GetMapping("/template/redisscript/echo/{echo}") + public String templateRedisScriptCompliant(@PathVariable String echo) { + String script = "return ARGV[1];"; + Object result = redisTemplate.execute(RedisScript.of(script, Object.class), new ArrayList(), echo); + return result.toString(); + } +} +---- + +=== How does this work? + +Here, the compliant solution passes the untrusted data as a parameter to the +Redis script. This ensures the data will be treated as a single value and will +not tamper with the script semantics. + diff --git a/rules/S5147/java/rule.adoc b/rules/S5147/java/rule.adoc index b7093ee0b0..7983bb5235 100644 --- a/rules/S5147/java/rule.adoc +++ b/rules/S5147/java/rule.adoc @@ -6,6 +6,8 @@ include::../impact.adoc[] include::how-to-fix-it/mongo-java-driver.adoc[] +include::how-to-fix-it/spring-data-redis.adoc[] + == Resources include::../common/resources/articles.adoc[]