0

Do you have an idea how my AWS credentials could be stolen in the following setup:

  • A 4 weeks old GitHub organization with 5 repositories & AWS Account
  • AWS CI User Credentials with Administration Privileges were saved as Github secrets
  • AWS keys were also stored in my Apple Notes
  • 4 repositories are using GitHub actions to deploy backend functions via the serverless framework
  • 1 repository uses GitHub actions to deploy a vue 3 / vite frontend
  • There was no other user who had access to the repository

The attack went in such a way:

  • 2 new admin users were created with the CI user.
  • One of these 2 new admin users has opened an AWS ticket to increase the SES and EC2 Spot Instance Limit

Yes, I know that the CI user had too many rights, and “Create env file” is stupid and isn't needed ;) But I still wonder how the AWS Keys could be stolen.

Has anyone come across similar attacks from GitHub Actions?

These are my GH Ations templates:


on:
  push:
    branches:
      - main
      
jobs:
  deploy-stage:
    timeout-minutes: 15 
    runs-on: ubuntu-latest

    if: "!contains(github.event.head_commit.message, 'ci skip')"
    steps:
      - uses: actions/checkout@v2
        with:
          persist-credentials: false
          fetch-depth: 0
      - uses: actions/setup-node@v1
        with:
          node-version: '20.x'
          registry-url: 'https://npm.pkg.github.com'
          scope: '@YOUR_ORGANISATION'
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_ID__STAGE }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY__STAGE }}
          aws-region: eu-central-1
      - name: Install AWS cli
        uses: chrislennon/[email protected]
        env:
          ACTIONS_ALLOW_UNSECURE_COMMANDS: true
      - name: Create env file
        run: |
          cat > env.yml << EOF
          ${{ secrets.ENV }}
          EOF
      - name: Install NPM dependencies
        run: |
          echo "//npm.pkg.github.com/:_authToken=${{ secrets.GH_PAT }}" > .npmrc
          echo "@YOUR_ORGANISATION:registry=https://npm.pkg.github.com/" >> .npmrc
          npm install

      # Run build
      - name: Run build
        run: npm run build:stage
      
      # Run cloudformation
      - name: Run cfn
        run: |
          npm install -g cfn-create-or-update
          cfn-create-or-update --stack-name MY_APP-v2-webapp-stage --wait \
            --template-body file://cloudformation.yml \
            --parameters ParameterKey=BucketName,ParameterValue=MY_APP-v2-webapp-stage \
            --parameters ParameterKey=DomainName,ParameterValue=beta.MY_APP.space \
            --parameters ParameterKey=RootDomainName,ParameterValue=beta.MY_APP.com \
            --parameters ParameterKey=ACMCertificateArn,ParameterValue=arn:aws:acm:us-east-1:XXXXYYYZYZYYZYZ:certificate/uuid-uuid-uuid-uuid

      # Deploy
      - name: Deploy to S3
        run: aws s3 cp --recursive ./dist/ s3://MY_APP-v2-webapp-stage/ 
on:
  push:
    branches:
      - main
jobs:
  deploy-stage:
    runs-on: ubuntu-latest
    if: "!contains(github.event.head_commit.message, 'ci skip')"
    steps:
      - uses: actions/checkout@v2
        with:
          persist-credentials: false
          fetch-depth: 0
      - name: Setup git user
        run: |
          git config --global user.name "$(git --no-pager log --format=format:'%an' -n 1)"
          git config --global user.email "$(git --no-pager log --format=format:'%ae' -n 1)"
          
      - uses: actions/setup-node@v1
        with:
          node-version: '20.x'
          registry-url: 'https://npm.pkg.github.com'
          scope: '@YOUR_ORGANISATION'
      
      - name: Install Serverless Framework
        run: npm install -g serverless
      
      - name: Create env file
        run: |
          cat > env.yml << EOF
          ${{ secrets.ENV }}
          EOF
      
      - name: Install NPM dependencies
        run: |
          echo "//npm.pkg.github.com/:_authToken=${{ secrets.GH_PAT }}" > .npmrc
          echo "@YOUR_ORGANISATION:registry=https://npm.pkg.github.com/" >> .npmrc
          npm install

       Run tests
      - name: Build assets
        run: npm run tests

      # SLS Deployment
      - name: Serverless AWS authentication
        run: sls config credentials --provider aws --key ${{ secrets.AWS_ACCESS_ID__STAGE }} --secret ${{ secrets.AWS_SECRET_KEY__STAGE }}
      
      - name: Serverless Deployment
        run: | 
          sls deploy -s stage
          cat .serverless/stack-output/outputs.json

      # Prepare SDK Package
      - name: Set Env File
        run: echo "export const env = " | cat - .serverless/stack-output/outputs.json > sdk/src/env-stage.ts
      - name: Generate typedoc
        run: |
          cd sdk  
          echo "//npm.pkg.github.com/:_authToken=${{ secrets.GH_PAT }}" > .npmrc
          echo "@YOUR_ORGANISATION:registry=https://npm.pkg.github.com/" >> .npmrc
          npm i
          npm run typedoc

      - name: Commit SDK updates
        run: |
          git add sdk
          git commit -m "SDK Build from CI/CD [ci skip]" sdk || true

      # Push git changes
      - uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: ${{ github.ref }}

      - name: Build NPM Package
        run: |
          cd sdk
          npm run build

      # Publish SDK Package
      - name: NPM Publish
        run: |
          cd sdk
          npm version prerelease
          cp package.json  dist/package.json
          cp README.md  dist/README.md
          cd dist
          npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
      
      - name: Commit package
        run: |
          git add sdk
          git commit -m "NPM Publish from CI/CD [ci skip]" sdk || true

      # Push git changes
      - uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: ${{ github.ref }}

      # Run  SDK Smoke tests
      - name: SDK Smoke tests
        run: |
          cd sdk  
          echo "//npm.pkg.github.com/:_authToken=${{ secrets.GH_PAT }}" > .npmrc
          echo "@YOUR_ORGANISATION:registry=https://npm.pkg.github.com/" >> .npmrc
          npm i
          VUE_APP_SDK_ENVIRONMENT=stage npm run tests:stage
2
  • Welcome to the community. The secrets are always decrypted in the pipeline in order to do something, so that might be your weak spot :/ Commented Apr 29 at 17:16
  • ... the other thing you have to worry about is how the attacker got sufficient permissions to modify the GitHub action to do things (after that, stealing the credentials is trivial). If this is a public repo, you need to change the required permissions for a few things. Commented Apr 30 at 15:56

0

You must log in to answer this question.

Browse other questions tagged .