コンテンツにスキップ

入口メソッド

メタデータとオプションが終わったら、フレームワークが呼び出す 入口メソッド を実装します。type によって名前が違います。

type入口いつ呼ばれるか
exploitexploitrun / exploit コマンド
exploit / 一部 auxiliarycheckcheck コマンド、または AutoCheck
auxiliary(通常)runrun
auxiliary + Scannerrun_host(ip)各 host ごと(run は mixin が持つ)
auxiliary + Scanner の checkcheck_host(ip)各 host の check
postrunrun(要 SESSION)

脆弱かどうかの判定だけを行い、ペイロードは流さない(または最小の証明に留める)メソッドです。戻り値は CheckCode::* です。fail_with は使わず、CheckCode を返します。

CheckCode意味
Unknown情報不足(タイムアウトなど)
Safe脆弱でない / 対象外
Detectedサービスは見つかったが可否不明
Appearsバージョンなど受動的根拠で怪しそう
Vulnerable実際に挙動で確認できた
Unsupportedcheck 非対応
def check
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'index.php')
)
return CheckCode::Unknown('no response') if res.nil?
return CheckCode::Safe('not ExampleApp') unless res.body.include?('ExampleApp')
if res.body =~ /Version: 1\.[0-2]/
return CheckCode::Appears('ExampleApp 1.0-1.2 detected')
end
CheckCode::Detected('ExampleApp found, version unknown')
end

Scanner では次です。

def check_host(ip)
# ip ごとに判定
CheckCode::Safe
end

メッセージは vprint_* を優先し、「Vulnerable です」と自分で断言しすぎない方がよいです。フレームワークが CheckCode を表示します。

exploit の本体です。接続 → 脆弱性利用 → ペイロード配送 →(必要なら)handler の流れが多いです。

def exploit
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'ping'),
'vars_post' => { 'ip' => "127.0.0.1;#{payload.encoded}" }
)
fail_with(Failure::Unreachable, 'no response') if res.nil?
end

CmdStager 利用時です。

def execute_command(cmd, _opts = {})
send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'ping'),
'vars_get' => { 'ip' => "127.0.0.1;#{cmd}" }
)
end
def exploit
if target['Arch'] == ARCH_CMD
execute_command(payload.encoded)
else
execute_cmdstager(linemax: 1500)
end
end

TCP 雛形(example.rb)では connect → sock.put → handler です。

失敗時は fail_with(Failure::..., message) を使います。定数は 応答処理と fail_with を参照してください。

def run
print_status("Running against #{peer}")
# 処理
print_good('Done')
end

post では session が使えます。

def run
print_status(cmd_exec('id'))
end
def run_host(ip)
res = send_request_cgi('method' => 'GET', 'uri' => '/')
return if res.nil?
print_good("#{ip}:#{rport} #{res.code}")
report_service(host: ip, port: rport, name: 'http', info: res.headers['Server'])
end

run を自分で定義して Scanner の仕組みを潰さないこと。host 単位の状態はローカル変数に閉じます。

prepend Msf::Exploit::Remote::AutoCheck すると、exploit / run の前に check が自動実行されます。詳細は AutoCheck です。

メソッド用途
print_status通常の進捗 [*]
print_good成功 [+]
print_error失敗 [-]
print_warning警告
vprint_*VERBOSE true のときだけ

次は 成果の保存 です。