1.1.1 [Обязательно] Операции с HTML-тегами: ограничение или фильтрация значений переменных
innerHTML=
, outerHTML=
, document.write()
, document.writeln()
необходимо выполнять кодирование специальных символов (&, <, >, ", '
) или использовать безопасные альтернативы DOM API, такие как innerText=
.Пример:
// Предположим, что params содержит пользовательский ввод, а text — узел DOM
// Плохо: использование небезопасного содержимого в HTML-тегах
const { user } = params;
// ...
text.innerHTML = `Follow @${user}`;
// Хорошо: кодирование специальных символов перед операцией innerHTML
function htmlEncode(iStr) {
let sStr = iStr;
sStr = sStr.replace(/&/g, "&");
sStr = sStr.replace(/>/g, ">");
sStr = sStr.replace(/</g, "<");
sStr = sStr.replace(/"/g, """);
sStr = sStr.replace(/'/g, "'");
return sStr;
}
let { user } = params;
user = htmlEncode(user);
// ...
text.innerHTML = `Follow @${user}`;
// Хорошо: использование безопасного DOM API вместо innerHTML
const { user } = params;
// ...
text.innerText = `Follow @${user}`;
1.1.2 [Обязательно] Безопасные операции с HTML-атрибутами: ограничение или фильтрация значений переменных
При использовании element.setAttribute(name, value)
и если значение первого параметра name
может контролироваться извне, следует применять белый список для ограничения допустимых операций с атрибутами.
При выполнении операций с a.href
, ifame.src
, form.action
, embed.src
, object.data
, link.href
, area.href
, input.formaction
и button.formaction
, если значение второго параметра value
может контролироваться извне, необходимо следовать рекомендациям из раздела JavaScript-страницы, пункт 1.3.1, ограничивая цели перенаправления страниц или ресурсы, которые будут импортированы.
Пример:
// Хорошо: проверка URL перед добавлением внешнего CSS
function addExternalCss(e) {
const t = document.createElement('link');
t.setAttribute('href', e),
t.setAttribute('rel', 'stylesheet'),
t.setAttribute('type', 'text/css'),
document.head.appendChild(t)
}
function validURL(sUrl) {
return !!((/^(https?:\/\/)?[\w\-.]+\.(qq|tencent)\.com($|\/|\\)/i).test(sUrl) || (/^[\w][\w/.\-_%]+$/i).test(sUrl) || (/^[/\\][^/\\]/i).test(sUrl));
}
let sUrl = "https://evil.com/1.css"
if (validURL(sUrl)) {
addExternalCss(sUrl);
}
1.2.1 [Обязательно] Ограничение или фильтрация переменных значений при использовании небезопасных функций jQuery
При использовании .html()
, .append()
, .prepend()
, .wrap()
, .replaceWith()
, .wrapAll()
, .wrapInner()
, .after()
, .before()
, если значения переменных могут контролироваться извне, рекомендуется выполнять кодирование специальных символов (&, <, >, ", '
).
Для версий jQuery 1.x (равных или ниже 1.12) и jQuery2.x (равных или ниже 2.2), если необходимо их использовать, рекомендуется рассмотреть возможность замены на более новые версии. В случае обязательного использования этих версий, рекомендуется кодировать специальные символы (&, <, >, ", '
), содержащиеся в значениях параметров.
Пример:
// Плохо: добавление небезопасного контента с помощью after()
const { user } = params;
// ...
$("p").after(user);
// Хорошо: выполнение html() после кодирования специальных символов
function htmlEncode(iStr) {
let sStr = iStr;
sStr = sStr.replace(/&/g, "&");
sStr = sStr.replace(/>/g, ">");
sStr = sStr.replace(/</g, "<");
sStr = sStr.replace(/"/g, """);
sStr = sStr.replace(/'/g, "'");
return sStr;
}
// const user = params.user;
user = htmlEncode(user);
// ...
$("p").html(user);
Использование .attr()
для операций с a.href
, ifame.src
, form.action
, embed.src
, object.data
, link.href
, area.href
, input.formaction
и button.formaction
должно соответствовать рекомендациям из пункта JavaScript-страницы 1.3.1 для ограничения целей перенаправления ресурсов.
При использовании .attr(attributeName, value)
, если значение первого параметра attributeName
может контролироваться извне, применяется белый список для ограничения разрешённых операций с атрибутами. 1.2.2 Обязательное ограничение/фильтрация переменных небезопасных функций Vue.js
v-html
, не следует использовать HTML-разметку, предоставленную пользователем. Если это необходимо для бизнеса, то следует предварительно обработать ненадёжный контент с помощью фильтрации форматированного текста.// Плохо: прямое рендеринг ненадёжного контента, полученного извне
<div v-html="userProvidedHtml"></div>
// Хорошо: использование фильтрации форматированного текста для обработки ненадёжного содержимого перед рендерингом
<!-- Использование -->
<div v-xss-html="{'mode': 'whitelist', dirty: html, options: options}" ></div>
<!-- Настройка -->
<script>
new Vue({
el: "#app",
data: {
options: {
a: ["href", "title", "target", "class", "id"],
div: ["class", "id"],
span: ["class", "id"],
img: ["src", "alt"],
},
},
});
</script>
При использовании v-bind
для операций с a.href
, ifame.src
, form.action
, embed.src
, object.data
, link.href
, area.href
, input.formaction
и button.formaction
, необходимо убедиться, что серверная часть уже ссылается на JavaScript страницу класса спецификации 1.3.1 и ограничивает перенаправление на целевые адреса.
При использовании v-bind
для управления стилем, следует разрешать только внешние значения для определённых контролируемых свойств CSS.
// Плохо: v-bind разрешает внешние значения, настраиваемые свойства CSS и числовые значения
<a v-bind:href="sanitizedUrl" v-bind:style="userProvidedStyles">
click me
</a>
// Хорошо: v-bind позволяет внешним значениям контролировать только определённые свойства CSS
<a v-bind:href="sanitizedUrl" v-bind:style="{
color: userProvidedColor,
background: userProvidedBackground
}">
click me
</a>
1.3 Перенаправление страницы
1.3.1 Обязательное ограничение цели перенаправления
Использовать белый список для ограничения протокола префикса (по умолчанию разрешены только HTTP и HTTPS), домена (по умолчанию разрешено только корневое доменное имя компании) или указывать фиксированное значение;
Это применимо к использованию функций методов, таких как location.href
, window.open()
, location.assign()
и location.replace()
, а также к присвоению или обновлению атрибутов HTML, таких как a.href
, iframe.src
, form.action
, embed.src
, object.data
, link.href
, area.href
, input.formaction
и button.formaction
.
// Плохо: перенаправление на внешний ненадёжный адрес
const sTargetUrl = getURLParam("target");
location.replace(sTargetUrl);
// Хорошо: ограничение белого списка для целей перенаправления
function validURL(sUrl) {
return !!((/^(https?:\/\/)?[\w\-.]+\.(qq|tencent)\.com($|\/|\\)/i).test(sUrl) || (/^[\w][\w/.\-_%]+$/i).test(sUrl) || (/^[/\\][^/\\]/i).test(sUrl));
}
const sTargetUrl = getURLParam("target");
if (validURL(sTargetUrl)) {
location.replace(sTargetUrl);
}
// Хорошо: определение фиксированной цели перенаправления
const sTargetUrl = "http://www.qq.com";
location.replace(sTargetUrl);
1.4 Анализ JSON и динамическое выполнение
1.4.1 Обязательный безопасный анализ JSON
JSON.parse()
для анализа строк JSON. В старых браузерах можно использовать безопасные полифиллы (например, Polyfill обёртывание).// Плохо: прямой вызов eval для анализа json
const sUserInput = getURLParam("json_val");
const jsonstr1 = `{"name":"a","company":"b","value":"${sUserInput}"}`;
const json1 = eval(`(${jsonstr1})`);
// Хорошо: использовать JSON.parse для анализа
const sUserInput = getURLPass("json_val");
JSON.parse(sUserInput, (k, v) => {
if (k === "") return v;
return v * 2;
});
// Хорошо: в старых браузерах используйте безопасное Polyfill обёртывание (на основе eval)
<script src="https://github.com/douglascrockford/JSON-js/blob/master/json2.js"></script>;
const sUserInput = getURLParam("json_val");
JSON.parse(sUserInput);
1.5 Междоменное взаимодействие
1.5.1 Обязательное использование безопасного способа междоменного взаимодействия
document.domain
для понижения домена. Вместо этого следует использовать postMessage.1.5.2 Обязательное использование postMessage для ограничения Origin
В прослушивателе событий message следует сначала использовать event.origin
для проверки источника, а затем выполнять конкретные операции.
Во время проверки источника следует использовать оператор ===
вместо indexOf()
.
// Плохо: использование indexOf для проверки Origin
window.addEventListener("message", (e) => {
if (~e.origin.indexOf("https://a.qq.com")) {
// ...
} else {
// ...
}
});
// Хорошо: при использовании postMessage ограничьте Origin и используйте === для сравнения
window.addEventListener("message", (e) => {
if (e.origin === "https://a.qq.com") {
// ...
}
});
``` **res.send({
data: txt,
});
});**
// Хорошо: проверка данных по типу, для ввода
const Router = require("express").Router();
const validator = require("validator");
Router.get("/email_with_validator", (req, res) => {
const txt = req.query.txt || "";
if (validator.isEmail(txt)) {
res.send({
data: txt
});
} else {
res.send({ err: 1 });
}
});
*Связанные уязвимости: защита от проникновения на глубину — функции повышения безопасности*
#### 1.2 Выполнение команды
**1.2.1 [Обязательно] использовать child_process для выполнения системных команд, необходимо ограничить или проверить содержимое команд и параметров**
- Применимые сценарии включают: `child_process.exec`, `child_process.execSync`, `child_process.spawn`, `child_process.spawnSync`, `child_process.execFile`, `child_process.execFileSync`
- Вызывая вышеуказанные функции, следует сначала рассмотреть ограничение диапазона, чтобы пользователь мог выбрать.
- Используя `child_process.exec` или `child_process.execSync`, если можно перечислить входные параметры или формат, следует ограничить белый список. Если невозможно перечислить команду или параметр, необходимо фильтровать или экранировать определённые символы, включая: ```|;&$()><`!```
- Использование `child_process.spawn` или `child_process.execFile` требует проверки переданных команд и параметров в контролируемом списке.
```js
const Router = require('express').Router;
const validator = require('validator');
const { exec } = require('child_process');
// Плохо: не ограничено или не отфильтровано, команда выполняется напрямую
Router.get('/vul_cmd_inject', (req, res) => {
const txt = req.query.txt || 'echo 1';
exec(txt, (err, stdout, stderr) => {
if (err) { res.send({ err: 1 }) }
res.send({ stdout, stderr });
});
});
// Хорошо: использование белого списка для ограничения диапазона внешних исполняемых команд
Router.get('/not_vul_cmd_inject', (req, res) => {
const txt = req.query.txt || 'echo 1';
const phone = req.query.phone || '';
const cmdList = {
sendmsg: './sendmsg '
};
if (txt in cmdList && validator.isMobilePhone(phone)) {
exec(cmdList[txt] + phone, (err, stdout, stderr) => {
if (err) { res.send({ err: 1 }) };
res.send({stdout, stderr});
});
} else {
res.send({
err: 1,
tips: `you can use '${Object.keys(cmdList)}'`,
});
}
});
// Хорошо: фильтрация/экранирование определённых символов перед выполнением команды
Router.get('/not_vul_cmd_inject', (req, res) => {
const txt = req.query.txt || 'echo 1';
let phone = req.query.phone || '';
const cmdList = {
sendmsg: './sendmsg '
};
phone = phone.replace(/(\||;|&|\$\(|\(|\)|>|<|\`|!)/gi, '');
if (txt in cmdList) {
exec(cmdList[txt] + phone, (err, stdout, stderr) => {
if (err) { res.send({ err: 1 }) };
res.send({stdout, stderr});
});
} else {
res.send({
err: 1,
tips: `you can use '${Object.keys(cmdList)}'`,
});
}
});
Связанная уязвимость: высокий риск — выполнение произвольной команды
1.3.1 [Обязательно] ограничить диапазон операций с файлами по расширению
1.3.2 [Обязательно] проверять и ограничивать диапазон путей к файлам
Следует установить фиксированный путь для загрузки и доступа к файлам. Если необходимо объединить внешние переменные значения, проверьте, содержат ли они ..
или .
, что может привести к переходу по пути. Если это так, следует отказаться.
Когда используются методы функций модуля fs
, такие как fs.truncate
, fs.truncateSync
, fs.chown
, fs.chownSync
, fs.lchown
, fs.lchownSync
, fs.stat
, fs.lchmodSync
, fs.lstat
, fs.statSync
, fs.lstatSync
, fs.readlink
, fs.unlink
, fs.unlinkSync
, fs.rmdir
, fs.rmdirSync
, fs.mkdir
, fs.mkdirSync
, fs.readdir
, fs.readdirSync
, fs.openSync
, fs.open
, fs.createReadStream
, fs.createWriteStream
, следует проверить первый параметр, который является путём, и убедиться, что он не содержит символов перехода по пути .
или ..
.
Если используется метод sendFile
фреймворка express, следует также проверить первый параметр, являющийся путём, и убедиться, что он не содержит символы перехода по пути .
или ..
.
Во время проверки следует использовать значение параметра пути до обработки модулем path
, или определить, выходит ли обработанный путь за пределы текущего рабочего каталога. Методы, которые могут быть использованы, включают, но не ограничиваются: path.resolve
, path.join
, path.normalize
и т. д.
const fs = require('fs');
const path = require('path');
let filename = req.query.ufile;
let root = '/data/ufile';
// Плохо: путь к файлу не проверен
fs.readFile(root + filename, (err, data) => {
if (err) {
return console.error(err);
}
console.log(`异步读取: ${data.toString()}`);
});
// Плохо: после обработки пути с помощью модуля path всё ещё существует риск перехода по пути
filename = path.join(root, filename);
if (filename.indexOf('..') < 0) {
fs.readFile(filename, (err, data) => {
if (err) {
return console.error(err);
}
console.log(data.toString());
});
};
// Хорошо: путь к файлу проверен, содержит ли он символы перехода по пути . или ..
if (filename.indexOf('..') < 0) {
filename = path.join(root, filename);
fs.readFile(filename, (err, data) => {
if (err) {
return console.error(err);
}
console.log(data.toString());
});
};
1.3.3 [Обязательно] безопасно обрабатывать имена загружаемых файлов
С обязательным применением мер по укреплению безопасности:
— чувствительные ресурсы, такие как удостоверения личности, банковские карты и т. п., должны быть защищены с помощью шифрования, аутентификации и водяных знаков;
— URL-адреса, указывающие на подобные файлы, должны обеспечивать непредсказуемость; при этом необходимо гарантировать отсутствие интерфейсов, которые могли бы массово отображать URL-адреса таких ресурсов;
— при доступе к чувствительным ресурсам должен осуществляться контроль разрешений; по умолчанию только пользователь может просматривать и работать со своими собственными чувствительными ресурсами.
Файлы типа изображений должны содержать бизнес-водяные знаки, чтобы указать, что эти изображения могут использоваться только в рамках текущего бизнеса.
1.4.1
Необходимо ограничить доступ к сетевым ресурсам по адресам:
— следует зафиксировать протоколы, доменные имена и пути доступа к сетевым ресурсам;
— если это требуется для бизнеса, внешние стороны могут указывать адреса сетевых ресурсов, но доступ к частным внутренним IP-адресам и доменам должен быть запрещён. Например, можно использовать RFC-определённые частные сети в качестве примера, а также добавлять собственные частные сетевые сегменты в список запрещённых.
10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 127.0.0.0/8
1.4.2
Рекомендуется шифровать передачу запросов к сетевым ресурсам:
— предпочтительно использовать протокол HTTPS для запросов к сетевым ресурсам.
Связанные уязвимости: высокий риск — SSRF, высокий риск — HTTP-перехват.
1.5.1
Обязательно не хранить и не показывать высокочувствительную информацию:
— пароли, ответы на вопросы безопасности, биометрические данные и другие формы аутентификационной информации не должны отображаться;
— в нефинансовых бизнесах номера кредитных карт CVV и журналы не должны храниться.
1.5.2
Обязательно маскировать общие чувствительные данные:
— показывать только первую и последнюю цифры номера удостоверения личности (например, 3**********1);
— скрывать шесть средних цифр номера мобильного телефона (например, 134************48);
— отображать только район для адресов работы или проживания;
— показывать только последние четыре цифры номера банковской карты (например, ********8639).
1.5.3
Рекомендовано выводить поля в соответствии с потребностями бизнеса:
— выводить только необходимые поля, избегая ненужного раскрытия личной информации пользователей;
— обрабатывать чувствительные пользовательские данные на сервере и затем выводить их, не допуская первоначального вывода на клиентскую сторону и последующей обработки через клиентский код.
Связанная уязвимость: высокий риск — раскрытие чувствительной информации пользователя.
1.6.1
Обязательно устанавливать правильный тип пакета ответа HTTP:
— тип содержимого в заголовке ответа Content-Type должен соответствовать фактическому типу данных ответа. Например, если ответ API является JSON, то заголовок ответа должен использовать application/json; если это XML, то следует установить text/xml.
1.6.2
Обязательно добавлять безопасные заголовки ответов:
— все интерфейсы и страницы должны включать заголовок X-Content-Type-Options: nosniff;
— все интерфейсы и страницы должны иметь заголовок X-Frame-Options, который может быть установлен в соответствии с требованиями безопасности, включая DENY, SAMEORIGIN или ALLOW-FROM origin. Для получения дополнительной информации рекомендуется обратиться к документации MDN (https://developer.mozilla.org/zh-CN/docs/Web/HTTP/X-Frame-Options);
— рекомендуется использовать компонент Helmet.
1.6.3
Перед внешним вводом данных в ответный HTML-код необходимо выполнить кодирование:
Сценарии | Правила кодирования |
---|---|
Ввод между HTML-тегами | Требуется кодировать следующие специальные символы: &, <, >, ", ', /. Пример: & → &, < → <, > → >, " → ", ' → ', / → / |
Входные данные в обычных атрибутах HTML (таких как href, src, style и т. д.), кроме событий on | Необходимо кодировать данные. Кодируются все символы, кроме арабских цифр и букв. После кодирования ASCII-коды символов должны быть меньше 256. Формат после кодирования: &#xHH (начинается с &#x, HH обозначает шестнадцатеричное число символа) |
Данные в коде JavaScript | Требует кодирования JavaScript. Кодируются все символы, кроме арабских цифр и букв. После кодирования ASCII-коды символов должны быть меньше 256. Результат кодирования: \xHH (\x обозначает начало, HH — шестнадцатеричный код символа) |
Данные в CSS | Требуют кодирования CSS. Кодируются все символы, кроме арабских цифр и букв. После кодирования ASCII-коды символов должны быть меньше 256. Результат кодирования: \HH (\ обозначает начало, HH — шестнадцатеричный код символа) |
Вводные данные в URL-атрибутах | Требует URL-кодирования данных. |
1.6.4
Запрещено показывать физические ресурсы, программную логику и другую чувствительную информацию в ответах:
— в производственной среде (официальной) при возникновении ошибок приложения ответы не должны раскрывать чувствительную информацию, такую как физические пути, внутренний исходный код программы, журналы отладки, внутренние учётные записи, внутренние IP-адреса и т. д.
Пример неправильного кода:
Access denied for user 'xxx'@'xx.xxx.xxx.162' (using password: NO)
1.6.5
Рекомендуется применять дополнительные меры безопасности:
— внедрить политику CSP, включая использование новейших строгих режимов с nonce-.
Правильный код:
// Хороший пример: использование компонента Helmet для безопасного конфигурирования заголовков ответов
const express = require("express");
const helmet = require("helmet");
const app = express();
app.use(helmet());
// Хороший пример: правильное конфигурирование Content-Type, добавление безопасных заголовков ответов и внедрение CSP
Router.get("/", (req, res) => {
res.header("Content-Type", "application/json");
res.header("X-Content-Type-Options", "nosniff");
res.header("X-Frame-Options", "SAMEORIGIN");
res.header("Content-Security-Policy", "script-src 'self'");
});
Связанное уязвимое место: средний риск — XSS, средний риск — перехват перехода.
1.7.1
Обязательное использование безопасных методов выполнения кода:
— запрещено использовать функцию eval;
— запрещено создавать функции с использованием new Function("input")();
— при использовании setInteval и setTimeout необходимо проверять передаваемые параметры.
Связанное уязвимое место: высокий риск — выполнение кода.
1.8.1
Обязательные ограничения для имён функций обратного вызова в JSONP:
— имена функций обратного вызова для интерфейсов JSONP должны быть ограничены фиксированным белым списком. Например, имена функций могут состоять только из букв, цифр и подчёркивания. Пример: [a-zA-Z0-9_-]+
1.8.2
Обязательная безопасная конфигурация CORS:
— используя CORS, необходимо строго фильтровать и проверять значение заголовка Origin. Можно использовать сравнение «точно равно» или строгие регулярные выражения для проверки. Пример: ^https://domain\.qq\.com$
// хороший пример: используется сравнение «точно равно», проверяется значение Origin
if (req.headers.origin === 'https://domain.qq.com') {
res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
res.setHeader('Access-control-allow-credentials', true);
}
Связанное уязвимое место: средний риск — XSS, средний риск — CSRF, средний риск — подделка межсайтовых запросов. Вот перевод текста на русский язык:
Проверка подлинности и авторизация
1.10.2 Обязательно: перед выполнением операций NoSQL необходимо проверять разрешения и роли.
— Перед выполнением логики вставки, обновления, удаления и запроса NoSQL необходимо проверить разрешения.
// Пример использования express и MongoDB (mongoose) для удаления статьи
// Плохо: перед удалением статьи не была проведена проверка разрешений
app.post("/deleteArticle", (req, res) => {
db.articles.deleteOne({ article_id: req.body.article_id }, (err, users) => {
// TODO: обработать остальное
});
});
// Хорошо: перед выполнением операции NoSQL сначала выполняется проверка разрешений
app.post("/deleteArticle", (req, res) => {
checkPriviledge(ctx.uin, req.body.article_id);
db.articles.deleteOne({ article_id: req.body.article_id }, (err, users) => {
// TODO: обработать остальное
});
});
1.11.1 Обязательно: безопасная серверная отрисовка Vue (Vue SSR)
— Запрещается напрямую передавать ненадёжный внешний контент в выражение {{{ data }}}
.
— Содержимое шаблона должно быть защищено от загрязнения.
// Плохо: пользовательский ввод заменяется в шаблоне
const app = new Vue({
template: appTemplate.replace("word", __USER_INPUT__),
});
renderer.renderToString(app);
— Для уже отрисованного HTML-текста (после renderToString). Если требуется снова вставить ненадёжный внешний ввод, необходимо сначала выполнить безопасную фильтрацию, см. 1.6.3.
// Плохо: после рендеринга html снова объединяется с ненадёжным внешним вводом
return new Promise(((resolve) => {
renderer.renderToString(component, (err, html) => {
let htmlOutput = html;
htmlOutput += `${__USER_INPUT__}`;
resolve(htmlOutput);
});
}));
1.11.2 Обязательно: безопасное использование EJS, LoDash, UnderScore для серверной отрисовки
— При использовании функции рендера содержимое шаблона не должно быть загрязнено.
lodash.Template:
// Плохо: пользовательский ввод отправляется в шаблон
const compiled = _.template(`<b>${__USER_INPUT__}<%- value %></b>`);
compiled({ value: "hello" });
ejs:
// Плохо: пользовательский ввод отправляется в шаблон
const ejs = require("ejs");
const people = ["geddy", "neil", "alex"];
const html = ejs.render(`<%= people.join(", "); %>${__USER_INPUT__}`, { people });
Ejs, LoDash и UnderScore предоставляют HTML-шаблоны по умолчанию, подобные <%= data %>
. Хотя по умолчанию существует фильтрация <%= data %>
, при написании HTML-шаблонов следует учитывать следующее:
<base data-id = "<%= __USER_INPUT__ %>">
, необходимо использовать двойные кавычки.<script></script>
или on*, например <script>var id = <%= __USER_INPUT__ %></script>
, необходимо выполнить фильтрацию методом белого списка или методом чёрного списка, фреймворк/компонент здесь не действует.1.11.3 Обязательно: при самостоятельной реализации хранилища состояний и его сериализации JSON.Stringify перед внедрением в HTML необходимо выполнить безопасную фильтрацию
1.12.1 Обязательно: ограничение перенаправления целевых адресов
Применяется к следующим сценариям:
<script>location.href=__Redirection_URL__</script>
на странице ответа.Используйте белый список для ограничения переадресации URL-адресов по протоколу (по умолчанию разрешены только HTTP и HTTPS), домену (по умолчанию разрешено только корневое доменное имя компании) или укажите фиксированное значение.
// Реализация успешного входа в систему с использованием express
// Плохо: не проверяется адрес перенаправления страницы
app.get("/login", (req, res) => {
// Если неавторизованный пользователь пытается получить доступ к другой странице, он будет направлен на эту функцию обработки для входа в систему
// Используйте параметр loginCallbackUrl для записи ранее посещённого URL, после успешного входа перенаправьте на loginCallbackUrl:
const { loginCallbackUrl } = req.query;
if (loginCallbackUrl) {
res.redirect(loginCallbackUrl);
}
});
// Хорошо: белый список ограничивает адрес переадресации
function isValidURL(sUrl) {
return !!((/^(https?:\/\/)?[\w\-.]+\.(qq|tencent)\.com($|\/|\\)/i).test(sUrl) || (/^[\w][\w/.\-_%]+$/i).test(sUrl) || (/^[/\\][^/\\]/i).test(sUrl));
}
app.get("/login", (req, res) => {
// Если неавторизованный пользователь пытается получить доступ к другой странице, он будет направлен на эту функцию обработки для входа в систему
// Используйте параметр loginCallbackUrl для записи ранее посещённого URL, после успешного входа перенаправьте на loginCallbackUrl:
const { loginCallbackUrl } = req.query;
if (loginCallbackUrl && isValidUrl(loginCallbackUrl)) {
res.redirect(loginCallbackUrl);
}
});
// Хорошо: белый список ограничивает адрес переадресации, реализуется через возврат html
function isValidURL(sUrl) {
return !!((/^(https?:\/\/)?[\w\-.]+\.(qq|tencent)\.com($|\/|\\)/i).test(sUrl) || (/^[\w][\w/.\-_%]+$/i).test(sUrl) || (/^[/\\][^/\\]/i).test(sUrl));
}
app.get("/login", (req, res) => {
// Если неавторизованный пользователь пытается получить доступ к другой странице, он будет направлен на эту функцию обработки для входа в систему
// Используйте параметр loginCallbackUrl для записи ранее посещённого URL, после успешного входа перенаправьте на loginCallbackUrl:
const { loginCallbackUrl } = req.query;
if (loginCallbackUrl && isValidUrl(loginCallbackUrl)) {
// Использование encodeURI, экранирование угловых скобок и двойных кавычек, предотвращение побега двойных кавычек из упаковки
const redirectHtml = `<script>location.href = "${encodeURI(loginCallbackUrl)}";</script>`;
res.end(redirectHtml);
}
});
Связанные уязвимости: средний риск — уязвимость произвольного перенаправления URL.
1.13.1 Рекомендуется: добавить защиту http-only для хранения важных данных состояния входа в файлах cookie
Связанная уязвимость: защита безопасности — усиление функций безопасности. 2.2.1 Обязательно использовать не-root пользователя для запуска Node.js
2.3.1 Обязательно запретить жёсткое кодирование аутентификационных данных
2.3.2 Обязательно запретить жёсткое кодирование IP-конфигурации
Почему это необходимо?
Жёсткое кодирование IP может привести к дополнительным работам при последующем изменении или удалении машин, что влияет на надёжность системы.
2.3.3 Обязательно запретить жёсткое кодирование чувствительной информации о сотрудниках
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )