CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/lib/metasploit/framework/login_scanner/softing_sis.rb
Views: 1904
require 'metasploit/framework/login_scanner/http'12module Metasploit3module Framework4module LoginScanner5class SoftingSIS < HTTP67DEFAULT_PORT = 80998DEFAULT_SSL_PORT = 4439PRIVATE_TYPES = [ :password ]10LOGIN_STATUS = Metasploit::Model::Login::Status1112# Check if the target is Softing Secure Integration Server13#14# @return [Boolean] TrueClass if target is SIS, otherwise FalseClass15def check_setup16# we can interact with this endpoint as an unauthenticated user17uri = normalize_uri("#{uri}/runtime/core/product-version")18res = send_request({ 'uri' => uri })19# make sure we get a response, and that the check was successful20unless res && res.code == 20021return { status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: res.to_s }22end2324# convert the response to JSON25# we expect to see a response like {"version" : "1.22.0.8686"}26res_json = res.get_json_document27# if we successfully get the version28if res_json['version']29# return true30return res_json['version']31end3233false34end3536# get the authentication token37#38# @param user [String] The username39# @return [Hash]40# * status [Metasploit::Model::Login::Status]41# * proof [String] the authentication token42def get_auth_token(user)43auth_token_uri = normalize_uri("#{uri}/runtime/core/user/#{user}/authentication-token")4445# send the request to get an authentication token46auth_res = send_request({47'method' => 'GET',48'uri' => auth_token_uri,49'cookie' => 'lang=en; user=guest'50})5152# check if we get a response53unless auth_res54return { status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: auth_res.to_s }55end5657# convert the response to JSON58auth_json = auth_res.get_json_document59# if the response code is 404, the user does not exist60if auth_res.code == 404 && auth_json && auth_json['Message']61return { status: LOGIN_STATUS::INCORRECT, proof: auth_json['Message'] }62end6364# if the response code is 403, the user exists but access is denied65if auth_res.code == 403 && auth_json && auth_json['Message']66return { status: LOGIN_STATUS::DENIED_ACCESS, proof: auth_json['Message'] }67end6869# get authentication token70auth_token = auth_json['authentication-token']71# check that the token is not blank72if auth_token.blank?73framework_module.vprint_error('Received empty authentication token!')74return { status: LOGIN_STATUS::INCORRECT, proof: auth_res.body.to_s }75end7677{ status: LOGIN_STATUS::SUCCESSFUL, proof: auth_token }78end7980# generate a signature from the authentication token, username, and password81#82# @param auth_token [String] The authentication token retrieved by calling get_auth_token83# @param user [String] The username84# @param pass [String] The password85# @return [String] A hexadecimal string representation of the signature86def generate_signature(auth_token, user, pass)87Digest::MD5.hexdigest(auth_token + pass + auth_token + user + auth_token)88end8990# the actual login method, called by #attempt_login91#92# @param user [String] The username to try93# @param pass [String] The password to try94# @return [Hash]95# * status [Metasploit::Model::Login::Status]96# * proof [String] the HTTP response body97def do_login(user, pass)98# prep the data needed for login99protocol = ssl ? 'https' : 'http'100# attempt to get an authentication token101auth_token_res = get_auth_token(user)102# get_auth_token always returns a hash - check that status is SUCCESSFUL103# if not, just return as it is104unless auth_token_res[:status] == LOGIN_STATUS::SUCCESSFUL105return auth_token_res106end107108# extract the authentication token from the hash109auth_token = auth_token_res[:proof]110111login_uri = normalize_uri("#{uri}/runtime/core/user/#{user}/authentication")112# calculate signature to use when logging in113signature = generate_signature(auth_token, user, pass)114# GET parameters for login115vars_get = {116'Signature' => signature,117'User' => user118}119120# do the login121res = send_request({122'method' => 'GET',123'uri' => login_uri,124'cookie' => 'lang=en; user=guest',125'headers' => { 'Referer' => "#{protocol}://#{host}:#{port}" },126'vars_get' => vars_get127})128129unless res130return { status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: res.to_s }131end132133# the response is in JSON format134res_json = res.get_json_document135# a successful response will contain {"Message": "Success"}136if res.code == 200 && res_json && res_json['Message'] == 'Success'137return { status: LOGIN_STATUS::SUCCESSFUL, proof: res.body }138end139140{ status: LOGIN_STATUS::INCORRECT, proof: res.body }141end142143# Attempts to login to Softing Secure Integration Server144#145# @param credential [Metasploit::Framework::Credential] The credential object146# @return [Result] A Result object indicating success or failure147def attempt_login(credential)148result_opts = {149credential: credential,150status: Metasploit::Model::Login::Status::INCORRECT,151proof: nil,152host: host,153port: port,154protocol: 'tcp'155}156157begin158result_opts.merge!(do_login(credential.public, credential.private))159rescue ::Rex::ConnectionError => e160# something went wrong during login161result_opts.merge!(status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: e.message)162end163164Result.new(result_opts)165end166167end168end169end170end171172173