first commit for typo3
parent
bdba80c05c
commit
aab4d4ae76
|
@ -59,6 +59,7 @@ require 'msf/core/post'
|
|||
|
||||
# Custom HTTP Modules
|
||||
require 'msf/http/wordpress'
|
||||
require 'msf/http/typo3'
|
||||
|
||||
# Drivers
|
||||
require 'msf/core/exploit_driver'
|
||||
|
|
|
@ -312,6 +312,14 @@ module Exploit::Remote::HttpClient
|
|||
end
|
||||
end
|
||||
|
||||
# Returns the complete URI including the scheme and host
|
||||
def full_uri
|
||||
uri_scheme = ssl ? 'https' : 'http'
|
||||
# check if target_uri starts with a /
|
||||
uri = target_uri.to_s =~ /^\// ? target_uri : "/#{target_uri}"
|
||||
"#{uri_scheme}://#{rhost}#{uri}"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns a modified version of the URI that:
|
||||
# 1. Always has a starting slash
|
||||
|
@ -343,6 +351,13 @@ module Exploit::Remote::HttpClient
|
|||
end
|
||||
end
|
||||
|
||||
# removes HTML tags from a provided string.
|
||||
# The string is html-unescaped before the tags are removed
|
||||
# Leading whitespaces and double linebreaks are removed too
|
||||
def strip_tags(html)
|
||||
Rex::Text.html_decode(html).gsub(/<\/?[^>]*>/, '').gsub(/^\s+/, '').strip
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the target host
|
||||
#
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
# This module provides a way of interacting with typo3 installations
|
||||
module Msf
|
||||
module HTTP
|
||||
module Typo3
|
||||
require 'msf/http/typo3/login'
|
||||
require 'msf/http/typo3/uris'
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::HTTP::Typo3::Login
|
||||
include Msf::HTTP::Typo3::URIs
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
register_options(
|
||||
[
|
||||
Msf::OptString.new('TARGETURI', [true, 'The base path to the typo3 application', '/']),
|
||||
], HTTP::Typo3
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,97 @@
|
|||
# -*- coding: binary -*-
|
||||
module Msf::HTTP::Typo3::Login
|
||||
|
||||
# performs a typo3 backend login
|
||||
#
|
||||
# @param user [String] Username
|
||||
# @param pass [String] Password
|
||||
# @return [String,nil] the session cookies as a single string on successful login, nil otherwise
|
||||
def typo3_backend_login(user, pass)
|
||||
# get login page for RSA modulus and exponent
|
||||
res_main = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => typo3_url_login
|
||||
})
|
||||
if res_main and res_main.code == 200
|
||||
e = res_main.body.match(/<input type="hidden" id="rsa_e" name="e" value="(\d+)" \/>/)[1]
|
||||
n = res_main.body.match(/<input type="hidden" id="rsa_n" name="n" value="(\w+)" \/>/)[1]
|
||||
vprint_status("e: #{e}")
|
||||
vprint_status("n: #{n}")
|
||||
rsa_enc = typo3_helper_login_rsa(e, n, pass)
|
||||
vprint_status("RSA Hash: #{rsa_enc}")
|
||||
# make login request
|
||||
vars_post = {
|
||||
'n' => '',
|
||||
'e' => '',
|
||||
'login_status' => 'login',
|
||||
'userident' => rsa_enc,
|
||||
'redirect_url' => 'backend.php',
|
||||
'loginRefresh' => '',
|
||||
'interface' => 'backend',
|
||||
'username' => user,
|
||||
'p_field' => '',
|
||||
'commandLI' => 'Login'
|
||||
}
|
||||
res_login = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => typo3_url_login,
|
||||
'cookie' => res_main.get_cookies,
|
||||
'vars_post' => vars_post,
|
||||
'headers' => {'Referer' => full_uri}
|
||||
})
|
||||
if res_login
|
||||
if res_login.body =~ /<!-- ###LOGIN_ERROR### begin -->(.*)<!-- ###LOGIN_ERROR### end -->/im
|
||||
print_error(strip_tags($1))
|
||||
return nil
|
||||
elsif res_login.body =~ /<p class="t3-error-text">(.*?)<\/p>/im
|
||||
print_error(strip_tags($1))
|
||||
return nil
|
||||
else
|
||||
cookies = res_login.get_cookies
|
||||
return cookies if typo3_admin_cookie_valid?(cookies)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
else
|
||||
print_error('Can not reach login page')
|
||||
return nil
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
# verifies cookies by calling the backend and checking the response
|
||||
#
|
||||
# @param cookiestring [String] The http cookies as a concatenated string
|
||||
# @return [Boolean] true if the cookie is valid, false otherwise
|
||||
def typo3_admin_cookie_valid?(cookiestring)
|
||||
res_check = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => typo3_url_backend,
|
||||
'cookie' => cookiestring,
|
||||
'headers' => {'Referer' => full_uri}
|
||||
})
|
||||
return true if res_check and res_check.code == 200 and res_check.body and res_check.body =~ /<body [^>]+ id="typo3-backend-php">/
|
||||
return false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# encrypts the password with the public key for login
|
||||
#
|
||||
# @param e [String] The exponent extracted from the login page
|
||||
# @param n [String] The modulus extracted from the login page
|
||||
# @param password [String] The clear text password to encrypt
|
||||
# @return [String] the base64 encoded password with prefixed 'rsa:'
|
||||
def typo3_helper_login_rsa(e, n, password)
|
||||
key = OpenSSL::PKey::RSA.new
|
||||
exponent = OpenSSL::BN.new e.hex.to_s
|
||||
modulus = OpenSSL::BN.new n.hex.to_s
|
||||
key.e = exponent
|
||||
key.n = modulus
|
||||
enc = key.public_encrypt(password)
|
||||
enc_b64 = Rex::Text.encode_base64(enc)
|
||||
"rsa:#{enc_b64}"
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: binary -*-
|
||||
module Msf::HTTP::Typo3::URIs
|
||||
|
||||
# Returns the Typo3 Login URL
|
||||
#
|
||||
# @return [String] Typo3 Login URL
|
||||
def typo3_url_login
|
||||
normalize_uri(target_uri.path, '/typo3/', 'index.php')
|
||||
end
|
||||
|
||||
# Returns the Typo3 backend URL
|
||||
#
|
||||
# @return [String] Typo3 Backend URL
|
||||
def typo3_url_backend
|
||||
normalize_uri(target_uri.path, '/typo3/', 'backend.php')
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue