好!
在本文的第一部分中,我们看到了什么是正则表达式,什么是规则。如果您尚未访问您的这一部分,以在本文第二部分的前进之前进行背景化。
要访问它,请单击AQUI。
跟我来,现在我们将解决这个问题ð
缓解风险
美丽!我们知道什么规则以及他如何完成,现在让我们看看我们能做什么来解决这种情况。
有一些可能的解决方案,例如验证正则表达式以查看它是否脆弱。一部分很难100%确保给定表达式是100%安全的,因为此攻击是基于用户发送的条目,并且有无限的可能性。
我们还可以尝试限制输入的大小,但这也无效,有一些区域模式可以锁定3个或更小的字符串!那么该怎么办?简单!
让我们使用Micro VM在主线程之外的另一个线程上编译正则条件的区域,以防我们无法评估的有效负载,我们的应用程序不会受到损害。
,但足以说话!跟我来,我将在实用中向您展示。
测试项目
为了测试这种情况,我们将使用使用Express Minimalist框架在NODEJS中构建的简单API。
有关Express AQUI的更多信息。
将是一个API,必须使用正则表达式验证电子邮件和密码的格式。
它有3个端点,为:
/validate-form-unsafe :此端点使用用于进行验证的 *表单。将用于显示这可能对系统产生负面影响。
/验证形式安全:该终点将用于测试我们的解决方案的建议是否有效。
/test-server :此端点将用于测试服务器的响应能力。
记住这只是一个示例API,所以有些事情可以做得更好,但是我们不会专注于此,好吗?
如果要下载或进行替换克隆,请单击AQUI
在我们的示例中,我们将使用以下言论:
/^([a-zA-Z0-9])(([\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/"gm"
如果字符串日期是一封徒劳的电子邮件,而其他常规的目的是验证其目的:
/^(([a-z])+.)+[A-Z]([a-z])+$/
用于验证知情密码是否以点为点格式,例如“ a.b.c.zz”或“ ab.cc.zd”
睾丸
当我们测试端点/validate-form-unsafe 以徒劳的条目,例如:
{
"email":"emailvalido@gmail.com",
"password":"a.b.Cz"
}
一切正常流动。
porti©m如果我们发送恶意有效载荷,例如:
{
"email":"email-valido@gmail.com",
"password":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
这就是发生的事情:
咨询端点/test-Service 我们发现我们的API根本不起作用。
但是发生了什么?
好吧,让我们看看答案的答案。使用正则验证错误方式的功能,以下:
function unsafeValidateForm(email, password) {
const isEmailValid = validadeEmailRegex.exec(email) !== null;
const isPasswordValid = validadePasswordRegex.exec(password) !== null;
return isEmailValid && isPasswordValid;
}
soluã§o
好吧,我们该怎么办才能解决这个问题?
让我们使用一个非常酷的功能,即节点VM的
如果您不知道这是什么,这里有一个简洁的解释:
vm 是一种机制仍执行,但能够访问和修改本地变量的能力。每个VM都有自己的执行线程,独立于主线程执行。
接下来,我们具有密码验证功能的修改版本。
async function safeValidateForm(email, password) {
try {
validateData(email, password);
const vmVariables = {
regexResult: false,
};
const context = vm.createContext(vmVariables);
const regexScript = new vm.Script(
`regexResult = new RegExp(${validadePasswordRegex}, "gm").exec("${password}") !== null &&
RegExp(${validadeEmailRegex},"gm").exec("${email}") !== null`
);
regexScript.runInContext(context, {
timeout: maxRegexEvaluationTimeoutInMillissecons,
});
return vmVariables.result !== null;
} catch (error) {
if (error.code == InternalErrorMessages.TIMEOUT) {
throw new TimeoutError("ValidateForm");
}
throw error;
}
}
这种方法是要在线程分开上执行此检查的原理,因此我们在此处使用VM为此,因此我们没有阻塞主线程的危险,因此导致API的完整锁定。
让我们看一下新功能并检查其功能。早期,我们有以下摘录来自Córib:
try {
validateData(email, password);
const vmVariables = {
regexResult: false,
};
const context = vm.createContext(vmVariables);
在这里,我们正在创建一个新的执行环境,要在我们将使用的VM中使用。如果我们想将任何值从当前上下文传递给VM,则在此阶段,我们应该在上下文中插入我们要注入的信息中创建的信息。
!!!!
从用户收到的输入永不,应直接传递给系统,而无需先接受治疗。 验证的函数我在这里做的是空的,因为这只是为了提醒您,在生产时,您必须始终处理收到的输入,好吗? 接下来我们有以下内容: 在这里,我们转到字符串VM将执行的脚本。请注意,此脚本正是对我们需要的正则表达式的评估,正是电子邮件和 password 我们需要评估的常规和用户。<<<<<<<< br>
请注意,在脚本中,我们有以下摘录“ RegexResult = new Re ...”此 RegexResult 与我们在上下文中声明的相同,并且将获得结果的值我们的操作£o。当处理此微VM结束时,我们可以通过执行 vmvariables.regexresult 来访问此结果。 ð 最后我们有成本: 在这里,我们使用创建的上下文在Micro VM中执行上方创建的脚本,我们可以访问Regex的执行结果 vmvariables.regxResult.regxResult 。 基本上,这就是我们可以对待常规的方式,我们不知道我是否会锁定或不锁定,甚至可能损害我们的应用程序。 现在,我们已经看到了如何解决这个问题,让我们测试解决方案,看看它是否确实有效。
在这里,我不会坚持这一点,因为焦点是另一个。
const regexScript = new vm.Script(
`regexResult = new RegExp(${validadePasswordRegex}, "gm").exec("${password}") !== null &&
RegExp(${validadeEmailRegex},"gm").exec("${email}") !== null`
);
摘录
regexScript.runInContext(context, {
timeout: maxRegexEvaluationTimeoutInMillissecons,
});
return vmVariables.result !== null;
} catch (error) {
if (error.code == InternalErrorMessages.TIMEOUT) {
throw new TimeoutError("ValidateForm");
}
throw error;
}
这里重要的是要注意超时属性< /strong>,这正是使我们能够继续处理事物的原因,即使此微VM结束,因为它达到 maxregevaluction millincons < / Strong>,在我们的情况下为50配置,VM已死亡,并且启动错误。此错误在捕获块中启动并捕获,我们对此进行了处理,引发了个性化的超时错误。
但这是第3部分,因为这里有很多信息。在下面,您将找到指向本文的第三部分也是最后一部分的链接。我希望你能。