반응형
stackoverflow 등의 웹사이트에서는 본문에 첨부된 코드를 실행시킬 수 있는 기능이 있다.
만약 이러한 기능을 필요로 할 때, 외부 코드를 안전하게 실행시킬 수 있는 방법들은 크게 다음과 같다.
1. JS 처리기를 JS 내부에서 구현...
2. 서버의 격리공간에서 실행 후 결과를 반환
3. 클라이언트의 격리공간에서 실행 후 결과를 반환
첫 번째 방법은 매우 고된 작업이고... 두 번째 방법은 서버에 부하가 클 수 있기에 주로 세 번째 방법을 사용한다.
// worker.js
const [global, permits] = [this, new Set([
// variables
"self",
"global",
"permits",
// functions
"eval",
"console",
"onmessage",
"postMessage",
// classes
"Date",
"Array",
"Object",
"Number",
"String",
"Boolean",
"Function",
"RegExp",
// errors
"Error",
"URIError",
"EvalError",
"TypeError",
"RangeError",
"SyntaxError",
"ReferenceError",
// URI utils
"decodeURI",
"decodeURIComponent",
"encodeURI",
"encodeURIComponent",
// type check
"isNaN",
"isArray",
"isFinite",
// type converstion
"parseInt",
"parseFloat",
// libs
"Math",
"JSON",
// values
"NaN",
"Infinity",
"undefined",
])];
for (const property of Object.getOwnPropertyNames(global))
{
if (!permits.has(property)) secure(global, property);
}
for (const property of Object.getOwnPropertyNames(global.__proto__))
{
if (!permits.has(property)) secure(global.__proto__, property);
}
global.addEventListener("message", (event) =>
{
for (const [key, value] of Object.entries(event.data.variables))
{
Object.defineProperty(global, key,
{
get()
{
return value;
},
configurable: true,
});
}
try
{
postMessage(eval("\"use strict\";" + event.data.script)); // or new Function
}
catch (error)
{
postMessage(error);
}
});
function secure(target, property)
{
const descriptor = Object.getOwnPropertyDescriptor(target, property);
if (!descriptor?.configurable ?? true) return;
Object.defineProperty(target, property,
{
get()
{
throw new Error(`Security Eerror: cannot access ${property}`);
},
configurable: false,
});
}
...
import workerJS from "file-loader?name=[name].js!@/prototypes/functions/execute/worker.js";
/** @see https://stackoverflow.com/questions/10653809/making-webworkers-a-safe-environment/10796616 */
export function execute(script: string, variables: Record<string, unknown> = {})
{
return new Promise((resolve, reject) => {
let timeout: NodeJS.Timeout;
const worker = new Worker(workerJS);
worker.addEventListener("message", (event) =>
{
// bye bye
worker.terminate();
// sayonara
clearTimeout(timeout);
if (event.data instanceof Error)
{
reject(event.data);
}
else
{
resolve(event.data);
}
});
worker.postMessage({ script, variables });
timeout = setTimeout(() => { worker.terminate(); return reject(); }, 1000 * 60);
});
}
Object.defineProperty(window, "execute", { value: execute });
(JS를 이용한 보안 취약점 공격은 매우 다양하고 중학생때 짠 코드라서... 간단한 예시로만 봐주세요)
반응형
'프로그래밍 > JS&TS' 카테고리의 다른 글
불편한 WebWorker 통신 (0) | 2024.09.10 |
---|