Автоматическое заполнение учетных данных веб-клиента ESXi

Я пытаюсь написать скрипт Greasemonkey, который автоматически заполняет веб-страницу входа ESXi учетными данными. Следующий код заполняет поля ввода и включает кнопку отправки:

// ==UserScript==
// @name         ESXi autofill credentials
// @namespace    https://esx_address/ui/*
// @version      0.1
// @description  Autofills user and password inputs
// @author       Mirek
// @require      http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require      https://gist.github.com/raw/2625891/waitForKeyElements.js
// @match        https://esx_address/ui/*
// @grant        none
// ==/UserScript==

try {
    waitForKeyElements ("#password", function(jNode) {jNode.val("password");});
    waitForKeyElements ("#username", function(jNode) {jNode.val("user");});
    waitForKeyElements ("#submit", function(jNode) {jNode.prop("disabled", false);});
} catch(err) {
    console.log("Something went wrong: " + err.message);
}

К сожалению, после нажатия кнопки отправки я вижу Cannot complete login due to an incorrect user name or password., хотя учетные данные верны.

Проблема, вероятно, связана с включенной кнопкой отправки. Страница входа включает его, когда пользователь вводит что-то в поле имени пользователя. К сожалению, скрипт не запускает такое поведение. Я обнаружил, что при включенном скрипте, когда я перехожу на страницу входа и повторно набираю последние буквы полей имени пользователя и пароля, вход проходит успешно.

Как я могу заполнить поля ввода таким образом, чтобы кнопка отправки активировалась?


person Mirek    schedule 08.11.2017    source источник


Ответы (2)


Это досадная наихудшая практика1, которая обычно требует подделки пользовательских событий.

  1. Детали того, что требуется, зависят от сайта/приложения (и я не собираюсь в ближайшее время экспериментировать с esxi).
    Иногда вам просто нужно отправить событие change. Иногда вам нужно сымитировать всю машину состояний mousein, key dow/press/up, mouseout, blur — часто с временными задержками и/или проверками состояния между ключевыми шагами.
    См. ниже пример кода промежуточного уровня.
  2. Некоторые сайты, такие как Patreon, особенно запутаны.
  3. Теоретически сайт может полностью заблокировать это, поскольку пользовательские скрипты не могут создавать trusted события, особенно события клавиатуры.
  4. Тем не менее, НЕ ВКЛЮЧАЙТЕ РЕКОМЕНДАЦИИ АККАУНТА В ПОЛЬЗОВАТЕЛЬСКИЙ СЦЕНАРИЙ!
    Не верьте мне на слово, поищите...
    Как минимум используйте зашифрованная структура.

Разумнее всего будет использовать менеджер паролей. Например, KeePass "Двухканальная обфускация автоматического ввода" побеждает большинство этих паршивых входов в систему. KeePass имеет открытый исходный код.


Пример вида кода, необходимого, если вы не используете хороший менеджер паролей.
Это работает для моего местного супермаркета. Этого будет недостаточно для более сложных сайтов, таких как многие банки. Это может НЕ работать, как есть, для любого другого сайта. См. № 1 выше.

function loginSite () {
    //--- Set username and password, from decrypted values. ---
    $("div.input_box_div #userId").attr ('value', usr);
    $("div.input_box_div #password").attr ('value', pword);

    //--- New style login page, approx 10/28/16...
    $('#keepMeSignedIn').prop ('checked', true);
    $("#input-email").attr ('value', usr);
    $("#password-password").attr ('value', pword);
    $("#show-password-checkbox")[0].click (); //-- This is needed for blur hack!!!?!?!

    setTimeout (function () {
        changeAndBlur ("#input-email");
        changeAndBlur ("#input-password");
    }, 400);

    waitForKeyElements ("#create-account-btn", clickWhenPrimed, true);
}

function changeAndBlur (jSelector) {
    let node    = $(jSelector);
    if (node.length) {
        var evChng  = new Event("change");
        node[0].dispatchEvent (evChng);
        var evBlur  = new Event("blur");
        node[0].dispatchEvent (evBlur);
    }
}

function clickWhenPrimed (jNode) {
    if (jNode.css("background-color") == "rgb(228, 23, 32)") {
      click_jNode (jNode);
    }
    else
        return true;
}

Обратите внимание, что для всех других сайтов я лично использую менеджер паролей, который может автоматически заполнять каждую учетную запись веб-страницы, которую я использую (до сих пор и с некоторыми настройками).


1 Подобные сайты/приложения раздражают и опасны, поскольку ограничивают функциональность менеджеров паролей. NIST недавно не одобрял блокировку менеджера паролей. Поэтому энергично жалуйтесь виновной организации и поддерживайте любые ожидающие рассмотрения законы / правила, которые ваша юрисдикция может разрешить использовать как длинные фразы-пароли, так и менеджеры паролей.

person Brock Adams    schedule 10.11.2017
comment
Спасибо друг! ChangeAndBlur сделал свое дело. Мне интересно - почему разработчики придерживаются такой практики? Это для повышения безопасности? Злоумышленник все равно всегда найдет способ обойти такие фичи... - person Mirek; 14.11.2017
comment
Иногда это ошибочная попытка остановить ботов (это не так). Иногда это просто плохой механизм проверки. Иногда он просто делает неверные предположения о том, как работают пользователи (предполагая, что они наводят мышь, вручную вводят учетные данные, убирают мышь и т. д.), когда на самом деле лучшие пользователи используют одноразовые пароли (или фразы-пароли) в сочетании с менеджером паролей. - person Brock Adams; 14.11.2017

Благодаря вкладу Брока мне удалось добиться успеха. Спасибо! Работает с версией ESXi: 6.5.0, версией клиента: 1.18.0.

События изменения и размытия успешно включают кнопку отправки.

function loginSite() {
    waitForKeyElements("#username", function(jNode) {jNode.val(username);}, true);
    waitForKeyElements ("#password", function(jNode) {jNode.val(password);}, true);
    setTimeout(function() {
        changeAndBlur("#username");
        changeAndBlur("#password");
    }, 400);
}

function changeAndBlur(jSelector) {
    let node = $(jSelector);
    if (node.length) {
        var evChng = new Event("change");
        node[0].dispatchEvent(evChng);
        var evBlur = new Event("blur");
        node[0].dispatchEvent(evBlur);
    }
}

waitForKeyElements("#submit", loginSite, true);
person Mirek    schedule 14.11.2017