Sploitus

Exploit for Code Injection in Gitea

githubexploit Β· 2026-09-14

Exploit Code

README179 lines
## https://sploitus.com/exploit?id=8F6A462F-FE9E-5CC7-9551-8CAFC43FD570
# CVE-2026-60004: Gitea Diffpatch API Remote Code Execution

> [!WARNING]
> This repository is intended exclusively for authorized security research and
> controlled laboratory testing. Do not run the proof of concept against
> systems you do not own or have explicit permission to assess.

## Overview

CVE-2026-60004 is a critical remote code execution vulnerability in Gitea's
diffpatch API. An authenticated user with permission to create or write to a
repository can submit a crafted patch that causes an executable Git hook to be
materialized inside a temporary bare repository. When the hook is triggered,
attacker-controlled commands execute with the privileges of the Gitea service
account.

If public registration is enabled, an unauthenticated attacker may be able to
create an account and reach the vulnerable authenticated endpoint.

| Attribute | Details |
|---|---|
| Identifier | CVE-2026-60004 |
| Advisory | GHSA-rcr6-4jqh-j84m |
| Severity | Critical β€” CVSS 3.1: 9.8 |
| Weakness | CWE-94: Improper Control of Generation of Code |
| Affected versions | Gitea 1.17.0 through 1.27.0 |
| Fixed version | Gitea 1.27.1 |
| Required access | Repository write access |
| Execution context | Gitea operating-system account |
| CISA KEV date | 2026-08-25 |

## Repository Contents

| File | Description |
|---|---|
| [`gitea_diffpatch_rce.py`](gitea_diffpatch_rce.py) | Standard-library-only proof of concept that authenticates, creates a private repository, submits the crafted patch, and retrieves command output. |
| [`payload.patch`](payload.patch) | Example patch that creates an executable `hooks/post-index-change` hook. |
| [`poc.png`](poc.png) | Screenshot captured during laboratory validation. |
| [`README.md`](README.md) | Original research notes. |

## Tested Environment

The proof of concept was validated in the following isolated environment:

| Component | Configuration |
|---|---|
| Gitea | 1.27.0 |
| Git | 2.47.2 |
| Deployment | Docker container named `gitea-lab` |
| Service address | `192.168.184.128:3000` |
| Observed identity | `uid=1000(git) gid=1000(git)` |

Successful exploitation produced command output similar to:

```text
uid=1000(git) gid=1000(git) groups=1000(git)
Linux 6.12.20-amd64 x86_64
/data/gitea/tmp/local-repo/upload.git630501597
[exit-status=0]
```

![Proof-of-concept output](poc.png)

## Prerequisites

- Python 3.8 or later
- Network access to the target Gitea instance
- A valid Gitea account with repository creation and write permissions, or a
  target laboratory instance with public registration enabled
- An explicitly authorized test environment

The script uses only Python's standard library and does not require additional
packages.

## Usage

```bash
python3 gitea_diffpatch_rce.py    ""
```

Example for a local laboratory instance:

```bash
python3 gitea_diffpatch_rce.py \
  http://127.0.0.1:3000 \
  pocuser \
  'P@ssw0rd!' \
  'id; uname -a'
```

The script first attempts web registration, then authenticates with the supplied
credentials. This allows the same command to work with either a new account on
an instance with open registration or an existing account.

## Technical Analysis

The exploitation chain consists of four stages:

1. **Attacker-controlled patch submission**  
   `POST /api/v1/repos/{owner}/{repo}/diffpatch` applies supplied patch content
   using `git apply --index --recount --cached --binary --ignore-whitespace
   --whitespace=fix -3` within a temporary clone.

2. **Hook path placement**  
   The temporary repository is created as a bare, shared clone. In a bare
   repository, the repository root is also `$GIT_DIR`; consequently, the patch
   path `hooks/post-index-change` resolves inside Git's active hooks directory.

3. **Executable hook materialization**  
   The same patch is submitted twice. The second application produces an
   add/add conflict, causing the three-way fallback to materialize the path on
   disk with mode `100755`, despite the use of `--cached`. A subsequent index
   update invokes `post-index-change`, executing the injected shell code as the
   Gitea service account.

4. **Git-native output retrieval**  
   The hook identifies the origin repository through
   `objects/info/alternates`, stores command output as a Git blob, creates a
   tree and commit, and updates `refs/heads/output-leak`. The proof of concept
   then retrieves the result through Gitea's raw-file API. This technique does
   not require a direct outbound connection from the target.

## Impact

Successful exploitation grants command execution with the privileges of the
Gitea service account. Depending on deployment configuration, an attacker may
be able to access:

- `app.ini` and database credentials
- `SECRET_KEY`, `INTERNAL_TOKEN`, and LFS-related secrets
- Repositories mounted or readable by the Gitea process
- Process environment variables
- Internal services reachable from the Gitea host or container

The laboratory account was confirmed to have read access to `app.ini`.

## Indicators of Compromise

Defenders should investigate the following artifacts and request patterns:

- Two identical or near-identical requests to
  `/api/v1/repos/*/*/diffpatch` in quick succession
- A branch named `output-leak`
- Commits authored by `poc `
- Unexpected executable files named `hooks/post-index-change` in bare
  repositories or temporary clone directories
- Suspicious activity below paths such as
  `/data/gitea/tmp/local-repo/upload.git*`

These indicators describe the included proof of concept and are not exhaustive;
a modified exploit may use different paths, refs, identities, or output channels.

## Remediation and Mitigation

1. **Upgrade to Gitea 1.27.1 or later.** This is the recommended remediation.
   The fix changes the affected workflow to use a non-bare temporary clone.
2. **Restrict the diffpatch API at the reverse proxy** until the upgrade is
   complete, for example by denying access to matching `/api/v1/.../diffpatch`
   routes. Validate the rule against legitimate integrations before deployment.
3. **Disable public registration** by setting `DISABLE_REGISTRATION=true` if it
   is not operationally required. This reduces unauthenticated reachability but
   does not protect against existing users with repository write access.
4. **Review logs and repository refs** for the indicators above, and rotate
   credentials or secrets accessible to the Gitea account if compromise is
   suspected.

For the laboratory container used in this research, teardown can be performed
with:

```bash
docker rm -f gitea-lab
```

## Responsible Use

This material is provided to help defenders reproduce, understand, detect, and
remediate the vulnerability. Operators should test only in isolated environments
and follow their organization's authorization and disclosure requirements.