Modify S5147: Add context specific code examples for Spring Data MongoDB (#3912)
Co-authored-by: Thomas Serre <118730793+thomas-serre-sonarsource@users.noreply.github.com>
This commit is contained in:
parent
4a50193c56
commit
d8c45777df
@ -47,6 +47,7 @@
|
|||||||
* Realm
|
* Realm
|
||||||
* Servlet
|
* Servlet
|
||||||
* Spring
|
* Spring
|
||||||
|
* Spring Data MongoDB
|
||||||
* Spring Data Cassandra
|
* Spring Data Cassandra
|
||||||
* Spring Data Redis
|
* Spring Data Redis
|
||||||
* Spring Data Neo4j
|
* Spring Data Neo4j
|
||||||
|
53
rules/S5147/java/how-to-fix-it/spring-data-mongodb.adoc
Normal file
53
rules/S5147/java/how-to-fix-it/spring-data-mongodb.adoc
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
== How to fix it in Spring Data MongoDB
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
The following code is an example of a simple API endpoint designed to read public messages. It is vulnerable to NoSQL injection because user-controlled data is inserted directly into a query string. The application assumes that incoming data always has a specific range of characters and ignores that some characters may change the query logic to a malicious one.
|
||||||
|
|
||||||
|
In this particular case, the query can be exploited with the following values:
|
||||||
|
|
||||||
|
* ``++username=user1', private:true}},{a:'++``
|
||||||
|
|
||||||
|
By adapting and inserting these values, an attacker can bypass the `private = false` condition and get access to private messages.
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,java,diff-id=3,diff-type=noncompliant]
|
||||||
|
----
|
||||||
|
@RestController
|
||||||
|
public class ApiController {
|
||||||
|
@Autowired
|
||||||
|
MongoClient mongoClient;
|
||||||
|
|
||||||
|
@GetMapping(value = "/read")
|
||||||
|
@ResponseBody
|
||||||
|
List<String> readPublicOnly(@RequestParam(value = "username") String username) {
|
||||||
|
MongoOperations template = new MongoTemplate(mongoClient, "demo");
|
||||||
|
BasicQuery query = new BasicQuery("{ username:'"+username+"', private: false }"); // Noncompliant
|
||||||
|
return template.find(query, String.class, "messages");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
==== Compliant solution
|
||||||
|
|
||||||
|
[source,java,diff-id=3,diff-type=compliant]
|
||||||
|
----
|
||||||
|
@RestController
|
||||||
|
public class ApiController {
|
||||||
|
@Autowired
|
||||||
|
MongoClient mongoClient;
|
||||||
|
|
||||||
|
@GetMapping(value = "/read")
|
||||||
|
@ResponseBody
|
||||||
|
List<String> readPublicOnly(@RequestParam(value = "username") String username) {
|
||||||
|
MongoOperations template = new MongoTemplate(mongoClient, "demo");
|
||||||
|
Query query = Query.query(Criteria.where("username").is(username).and("private").is(false));
|
||||||
|
return template.find(query, String.class, "messages");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
=== How does this work?
|
||||||
|
|
||||||
|
The compliant solution uses the `Query` and `Critera` objects to build the query syntax safely.
|
@ -8,6 +8,8 @@ include::how-to-fix-it/mongo-java-driver.adoc[]
|
|||||||
|
|
||||||
include::how-to-fix-it/spring-data-redis.adoc[]
|
include::how-to-fix-it/spring-data-redis.adoc[]
|
||||||
|
|
||||||
|
include::how-to-fix-it/spring-data-mongodb.adoc[]
|
||||||
|
|
||||||
== Resources
|
== Resources
|
||||||
|
|
||||||
include::../common/resources/articles.adoc[]
|
include::../common/resources/articles.adoc[]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user