+ "details": "In `JsonBeanPropertyBinder::expandArrayToThreshold` in `io.micronaut:micronaut-json-core` before Micronaut 4 4.10.16 and in Micronaut 3 before 3.10.5 does not correctly handle descending array index order during form-urlencoded body binding, which allows remote attackers to cause a denial of service (non-terminating loop, CPU exhaustion, and OutOfMemoryError) via crafted indexed form parameters (e.g., `authors[1].name` followed by `authors[0].name`).\n\n### Example\n\nWith such an application\n\n```java\npackage dosform;\n\nimport io.micronaut.http.HttpResponse;\nimport io.micronaut.http.MediaType;\nimport io.micronaut.http.annotation.Body;\nimport io.micronaut.http.annotation.Consumes;\nimport io.micronaut.http.annotation.Controller;\nimport io.micronaut.http.annotation.Get;\nimport io.micronaut.http.annotation.Post;\nimport io.micronaut.http.annotation.Produces;\n\nimport java.net.URI;\n\n@Controller\nclass HomeController {\n\n @Produces(MediaType.TEXT_HTML)\n @Get\n String index() {\n return \"\"\"\n <!DOCTYPE html>\n <html>\n <head>\n <title></title>\n </head>\n <body>\n <form action=\"/submit\" method=\"post\">\n <label for=\"firstAuthor\">Fist Author</label>\n <input id=\"firstAuthor\" name=\"authors[0].name\" type=\"text\"/>\n\n <label for=\"secondAuthor\">Second Author</label>\n <input id=\"secondAuthor\" name=\"authors[1].name\" type=\"text\"/>\n \n <label for=\"thirdAuthor\">Third Author</label>\n <input id=\"thirdAuthor\" name=\"authors[2].name\" type=\"text\"/>\n\n <button type=\"submit\">Submit</button>\n </form>\n \n </body>\n </html>\n \"\"\";\n }\n\n @Consumes(MediaType.APPLICATION_FORM_URLENCODED)\n @Post(\"/submit\")\n HttpResponse<?> submit(@Body Book book) {\n return HttpResponse.seeOther(URI.create(\"/\"));\n }\n}\npackage dosform;\n\nimport io.micronaut.core.annotation.Introspected;\n\nimport java.util.Objects;\n\n@Introspected\npublic class Author {\n private String name;\n public String getName() { return name; }\n public void setName(String name) { this.name = name; }\n\n @Override\n public final boolean equals(Object o) {\n if (!(o instanceof Author)) return false;\n\n Author author = (Author) o;\n return Objects.equals(name, author.name);\n }\n\n @Override\n public int hashCode() {\n return Objects.hashCode(name);\n }\n\n @Override\n public String toString() {\n return \"Author{\" +\n \"name='\" + name + '\\'' +\n '}';\n }\n}\npackage dosform;\n\nimport io.micronaut.core.annotation.Introspected;\n\nimport java.util.List;\nimport java.util.Objects;\n\n@Introspected\npublic class Book {\n private List<Author> authors;\n public List<Author> getAuthors() { return authors; }\n public void setAuthors(List<Author> authors) { this.authors = authors; }\n\n @Override\n public final boolean equals(Object o) {\n if (!(o instanceof Book)) return false;\n\n Book book = (Book) o;\n return Objects.equals(authors, book.authors);\n }\n\n @Override\n public int hashCode() {\n return Objects.hashCode(authors);\n }\n\n @Override\n public String toString() {\n return \"Book{\" +\n \"authors=\" + authors +\n '}';\n }\n}\n```\n\nSending `curl -v -X POST 'http://127.0.0.1:8080/submit' -H 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'authors[1].name=RobertGalbraith' --data-urlencode 'authors[0].name=JKRowling'` causes sustained CPU usage and unbounded memory growth (eventually `OutOfMemoryError`). \n\n### Patches\nFor Micronaut 4, the problem has been patched in `micronaut-core`, dependencies with group id `io.micronaut`, since [4.10.16](https://github.com/micronaut-projects/micronaut-core/releases/tag/v4.10.16).\n\nFor Micronaut 3, the problem has been patched since [3.10.5](https://github.com/micronaut-projects/micronaut-core/releases/tag/v3.10.5)\n\nUsers upgrade to the latest version of the framework. \n\n### Workarounds\nThere is no way for users to fix or remediate the vulnerability without upgrading.\n\n### References\nPR Fix: https://github.com/micronaut-projects/micronaut-core/pull/12410",
0 commit comments