Почему плохая практика вызывает индекс массива с переменной?
В настоящее время я разрабатываю небольшую игру на Javascript, и я использую Codacy, чтобы просмотреть мой код и помочь очистить его.
Одной из наиболее часто встречающихся ошибок является приемник Generic Object Injection (безопасность / обнаружение объекта-инъекция).
Это происходит, когда я пытаюсь получить доступ к значению в массиве с помощью переменной. Как в этом примере:
function getValString(value)
{
var values = ["Misérable", "Acceptable", "Excellente", "Divine"];
return values[value];
}
Эта функция используется для отображения на экране строки значения элемента. Он получает "значение", которое может быть 0, 1, 2 или 3, и возвращает строку значения.
Теперь вот моя проблема:
Codacy говорит мне, что использование var [var] должно быть запрещено, потому что это вызывает проблемы с безопасностью, и, поскольку я довольно новичок в javascript, мне было интересно, почему и каковы хорошие практики в такой ситуации.
1 ответ
Что плохо в доступе по индексу: в этом индексе может отсутствовать элемент.
Что касается вашего кода, я бы сделал предустановленную карту:
const preset = {
0: 0.5,
1: 1.5,
2: 2,
3: 3
};
А затем использовать его в функции:
function sellPotato(x, player) {
// This additional check gives you more confidence in accessing element of and array by index
if (player.inventory.length < x) return;
if (preset[player.inventory[x].value]) {
player.money += player.inventory[x].price * preset[player.inventory[x].value];
}
player.inventory.splice(x, 1);
display(player);
}
Проблема безопасности заключается в том, что строковое значение
value
может получить доступ к свойству, унаследованному от объекта
__proto__
иерархический прототип, а не фактическое свойство самого объекта.
Например, рассмотрим сценарий, когда
value
является строковым литералом
"constructor"
.
const property = "constructor";
const object = [];
const value = object[property];
Результат
value
в этом контексте будет разрешено
Array()
функция, которая наследуется как часть прототипа объекта, а не фактическое свойство объекта
object
переменная. Кроме того, объект, к которому осуществляется доступ, мог переопределить любой из унаследованных по умолчанию
Object.prototype
свойства, потенциально для злонамеренных целей.
Это поведение можно частично предотвратить, выполнив
object.hasOwnProperty(property)
условная проверка, чтобы убедиться, что объект действительно имеет это свойство. Например:
const property = "constructor";
const object = [];
if (object.hasOwnProperty(property)) {
const value = object[property];
}
Обратите внимание: если мы подозреваем, что объект, к которому осуществляется доступ, может быть злонамеренным или переопределить
hasOwnProperty
может потребоваться использовать Object hasOwnProperty, унаследованный от прототипа напрямую:
Object.prototype.hasOwnProperty.call(object, property)
Конечно, это предполагает, что наш
Object.prototype
еще не был изменен.
Это не обязательно полная картина, но она демонстрирует точку зрения.
Ознакомьтесь со следующими ресурсами, в которых более подробно описывается, почему это проблема, и некоторые альтернативные решения:
Само по себе это неплохая практика, потому что вы действительно хотите разработать систему и сделать ее безопасной. Трудно представить себе более высокий риск для безопасности системы, чем тот, который приводит к ее отсутствию.
Тем не менее, запрет на использование переменной для динамического создания / использования / обновления индекса практически уменьшает ваши возможности жесткого кодирования любых индексов, которые вы можете использовать для ссылки на элементы массива или члены объекта.
Отказ от использования индексов значительно уменьшает ваши возможности, настолько, что это угрожает отсутствием какой-либо системы, которую вы, возможно, захотите создать на Javascript. Давайте посмотрим на некоторые варианты использования:
Пронумерованные петли:
for (let index = 0; index < arr.length; index++) {
//do whatever with arr[index]
}
Конечно, это верно
while
петли.
в петлях
for (let index in variable) {
//do whatever with arr[index]
}
петель
for (let item of variable) {
// do whatever with item
}
динамический поиск значения
Это практически используется почти бесконечно многими способами, все приведенные выше примеры являются частными случаями этого. Пример:
function getItem(arr, index) {
return arr[index];
}
резюме
Страх перед эксплойтами из-за динамической индексации эквивалентен страху перед попаданием метеорита в точное место и точное время, в котором он находится. Конечно, мы не можем этого исключить, но нельзя жить в постоянном страхе перед маловероятным катастрофы. Точно так же невозможно программирование из-за необоснованных параноидальных страхов. Таким образом, вместо того, чтобы полностью отказываться от динамического индексирования из-за возможности использования эксплойтов, мы должны обратиться к реальным эксплойтам, которые могут быть возможны. Если нам не разрешено использовать динамические экземпляры, то любая система, которую мы должны разработать, если она не проста, как пирог, не будет существовать. Поэтому от любых угроз, которых мы боимся, нужно защищаться в противном случае.
Пример: вы получаете значения из источника данных и имеете поле для IBAN кредитной карты. Да, если это показано пользователю, который не является владельцем, это высокий риск. Но вы должны защититься от этого, сделав IBAN недоступным путем простого использования индекса внешними источниками, такими как запросы POST, отправленные браузером пользователя.