-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20 from carlspring/missing-input-validation
Add example for blocking the event loop
- Loading branch information
Showing
2 changed files
with
111 additions
and
0 deletions.
There are no files selected for viewing
57 changes: 57 additions & 0 deletions
57
src/main/java/org/carlspring/security/vertx/http/InsecureEventLoopWorkloads.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package org.carlspring.security.vertx.http; | ||
|
||
import io.vertx.core.AbstractVerticle; | ||
import io.vertx.core.json.JsonArray; | ||
import io.vertx.core.json.JsonObject; | ||
|
||
/** | ||
* In this example, the Vert.x HTTP server expects a user-supplied input parameter called "data" via a query parameter | ||
* or request body. The input is then converted into a {@link JsonArray} and each element of the {@link JsonArray} is | ||
* iterated and processed sequentially. The processing involves some complex computations, which might work well with | ||
* small data, but not for large {@link JsonArray}s. | ||
* | ||
* An attacker can exploit this vulnerability by injecting a large {@link JsonArray} as the input parameter, | ||
* overwhelming the server's processing capabilities. For example, if the attacker sends a request with a large | ||
* {@link JsonArray} containing thousands or millions of elements, the server will iterate through each element, | ||
* causing a significant delay. As the workload is executed directly on the eventloop, such an attack would violate the | ||
* <a href="https://vertx.io/docs/vertx-core/java/#golden_rule">Golden Rule of Vert.x<a/>, and block other tasks. | ||
* | ||
* To mitigate this vulnerability, you should consider implementing appropriate input validation and limiting the | ||
* amount of data processed in a single request. You can also offload the processing of the {@link JsonArray} to a worker | ||
* thread or divide the processing into smaller batches to avoid blocking the event loop and handle large inputs more | ||
* efficiently. | ||
*/ | ||
public class InsecureEventLoopWorkloads extends AbstractVerticle { | ||
|
||
@Override | ||
public void start() { | ||
|
||
vertx.createHttpServer().requestHandler(req -> { | ||
String input = req.getParam("data"); // User-supplied input | ||
|
||
// Transform the input without validation | ||
JsonArray jsonArray = new JsonArray(input); | ||
|
||
// Process the input | ||
JsonObject transformedObject = new JsonObject(); | ||
for (Object jsonObject : jsonArray) { | ||
transformedObject = performExpensiveProcessing((JsonObject) jsonObject); | ||
} | ||
|
||
// Return the transform input | ||
req.response().end(transformedObject.toBuffer()); | ||
}).listen(8080); | ||
} | ||
|
||
private JsonObject performExpensiveProcessing(JsonObject jsonObject) { | ||
// Expensive transformation logic here; simulated with a sleep. | ||
// This can include complex computations, database queries, network calls, etc. | ||
try { | ||
Thread.sleep(100); // Simulating processing time | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
return jsonObject; | ||
} | ||
} | ||
|
54 changes: 54 additions & 0 deletions
54
src/main/java/org/carlspring/security/vertx/http/SecureEventLoopWorkloads.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package org.carlspring.security.vertx.http; | ||
|
||
import io.vertx.core.AbstractVerticle; | ||
import io.vertx.core.json.JsonArray; | ||
import io.vertx.core.json.JsonObject; | ||
|
||
/** | ||
* In this updated code, the executeBlocking method is used to offload the processing of each JsonObject to a worker | ||
* thread, ensuring that it doesn't block the event loop. The expensive transformation logic is still performed, but | ||
* now it's executed on a worker. | ||
*/ | ||
public class SecureEventLoopWorkloads extends AbstractVerticle { | ||
|
||
private static final int MAX_INPUT_SIZE = 1_000; // Maximum allowed input size | ||
|
||
@Override | ||
public void start() { | ||
|
||
vertx.createHttpServer().requestHandler(req -> { | ||
String input = req.getParam("data"); // User-supplied input | ||
|
||
// Execute processing on a worker | ||
vertx.executeBlocking(promise -> { | ||
// Transform the input without validation | ||
JsonArray jsonArray = new JsonArray(input); | ||
|
||
// Process the input | ||
JsonObject transformedObject = new JsonObject(); | ||
for (Object jsonObject : jsonArray) { | ||
transformedObject = performExpensiveProcessing((JsonObject) jsonObject); | ||
} | ||
|
||
promise.complete(transformedObject); | ||
}, result -> { | ||
if (result.succeeded()) { | ||
req.response().end(result.result().toString()); | ||
} else { | ||
req.response().setStatusCode(500).end("Internal Server Error"); | ||
} | ||
}); | ||
}).listen(8080); | ||
} | ||
|
||
private JsonObject performExpensiveProcessing(JsonObject jsonObject) { | ||
// Expensive transformation logic here; simulated with a sleep. | ||
// This can include complex computations, database queries, network calls, etc. | ||
try { | ||
Thread.sleep(100); // Simulating processing time | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
return jsonObject; | ||
} | ||
} |