認証と Cookie
ログインが必要なケースのパターンです。
Basic 認証
Section titled “Basic 認証”res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'admin'), 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']))HttpUsername / HttpPassword を set しておくと、401 時の再送で Basic / Digest / NTLM などが選ばれる経路もあります。明示したいときは authorization か preferred_auth を使います。
res = send_request_cgi( 'method' => 'GET', 'uri' => '/', 'username' => datastore['HttpUsername'], 'password' => datastore['HttpPassword'], 'preferred_auth' => 'Digest')preferred_auth の例: Basic、Digest、NTLM、Kerberos、Negotiate、None。
フォームログイン + keep_cookies
Section titled “フォームログイン + keep_cookies”res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'login.php'), 'keep_cookies' => true, 'vars_post' => { 'username' => datastore['USERNAME'], 'password' => datastore['PASSWORD'] })fail_with(Failure::Unreachable, "#{peer} - no response") if res.nil?fail_with(Failure::NoAccess, "login failed: #{res.code}") unless res.code == 302
# 以降は cookie_jar が自動添付されるres = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'dashboard'))example_webapp.rb も同じ流れです。Basic とフォームを同時に載せる例もあります。
'authorization' => basic_auth(user, pass),'keep_cookies' => true,'vars_post' => { 'username' => user, 'password' => pass }自己登録 → ログイン
Section titled “自己登録 → ログイン”公開登録があるアプリでは、新しいアカウントを作成してからログインします。登録応答にセッション Cookie が含まれない場合、keep_cookies はログイン時だけで足ります。保存された Cookie は後続のリクエストに自動で添付されます。
def authenticate return true if @authenticated
user = datastore['USERNAME'] pass = datastore['PASSWORD']
send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'register'), 'vars_post' => { 'username' => user, 'password' => pass } )
res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'login'), 'keep_cookies' => true, 'vars_post' => { 'username' => user, 'password' => pass } ) fail_with(Failure::NoAccess, 'login failed') if res.nil? fail_with(Failure::NoAccess, "login failed: HTTP #{res.code}") unless res.code == 200 || res.redirect?
@authenticated = true trueend- 登録応答に
Set-Cookieが含まれるアプリでは、登録 POST にもkeep_cookiesを付けます。 - 登録・ログインの成否は応答コードや遷移先で確認します。
- CSRF が要る場合は次節と同じく、先に GET してトークンを取ります。
- AutoCheck を使う場合は
checkとexploitの入口でこの関数を呼びます。@authenticatedによって、同じ実行中の登録とログインは繰り返しません。実装例は Exploit の「自己登録 → ログイン → JSON API RCE」を参照してください。
参考モジュール: modules/exploits/unix/webapp/byob_unauth_rce.rb(register_user と login_user を分離)、modules/exploits/linux/http/xplico_exec.rb。
CSRF トークン付きログイン
Section titled “CSRF トークン付きログイン”res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'users', 'sign_in'))fail_with(Failure::Unreachable, 'no response') if res.nil?
token = res.body[%r{name="authenticity_token" value="([^"]+)"}, 1]fail_with(Failure::UnexpectedReply, 'CSRF token missing') if token.blank?
res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'users', 'sign_in'), 'keep_cookies' => true, 'vars_post' => { 'authenticity_token' => token, 'user[login]' => datastore['USERNAME'], 'user[password]' => datastore['PASSWORD'], 'user[remember_me]' => '0' })Cookie 文字列を直接指定
Section titled “Cookie 文字列を直接指定”jar を使わず、そのリクエストだけ Cookie を固定します。
res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'admin'), 'cookie' => "PHPSESSID=#{@phpsessid}; role=admin")cookie を渡したリクエストでは、その回に限って jar の自動添付より指定が使われます。
HttpCookieJar で組み立て
Section titled “HttpCookieJar で組み立て”cj = Msf::Exploit::Remote::HTTP::HttpCookieJar.newhost = datastore['RHOST']cj.add(Msf::Exploit::Remote::HTTP::HttpCookie.new('PHPSESSID', @phpsessid, domain: host, path: '/'))cj.add(Msf::Exploit::Remote::HTTP::HttpCookie.new('role', 'admin', domain: host, path: '/'))
send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'admin'), 'cookie' => cj)domain と path は必須です。値は String です。
Cookie jar の消去と期限切れ
Section titled “Cookie jar の消去と期限切れ”cookie_jar.clear
send_request_cgi( 'method' => 'GET', 'uri' => '/', 'expire_cookies' => false)別アカウントで再ログインする前に cookie_jar.clear します。
手動で Set-Cookie を拾う古典パターン
Section titled “手動で Set-Cookie を拾う古典パターン”res = send_request_cgi(...)cookie = res.get_cookiessend_request_cgi( 'method' => 'GET', 'uri' => '/next', 'cookie' => cookie)新規モジュールでは keep_cookies の方が短くて済みます。

