.Net MVC - 无法阻止我的 Ajax.BeginForm 被黑客入侵
Posted
技术标签:
【中文标题】.Net MVC - 无法阻止我的 Ajax.BeginForm 被黑客入侵【英文标题】:.Net MVC - Can't Stop my Ajax.BeginForm to be hacked 【发布时间】:2021-03-18 17:33:08 【问题描述】:我已经在我的 .Net MVC Web 应用程序中构建了一个基于 Ajax 的表单,但我无法停止被黑客攻击并被用来向我发送垃圾邮件。
@using (Ajax.BeginForm("ContactSend", "Home", null, new AjaxOptions OnBegin = "Contact.submitOnBegin", OnSuccess = "Contact.submitOnSuccess" , new id = "contact-form" ))
@html.AntiForgeryToken()
<input id="contact-cta" type="hidden" name="cta" value="@ViewBag.CTA" />
<label class="form-label" for="nome">@Resources.Contact_Form_Name <span class="mandatory">*</span></label>
<div class="form-input-ctn">
<input id="contact-name" type="text" name="name">
<div class="mandatory-error">@Resources.Contact_Form_Mandatory</div>
</div>
<label class="form-label" for="email">@Resources.Contact_Form_Email <span class="mandatory">*</span></label>
<div class="form-input-ctn">
<input id="contact-email" type="text" name="email">
<div class="mandatory-error">@Resources.Contact_Form_Mandatory</div>
<div class="invalid-error">@Resources.Contact_Form_Invalid</div>
</div>
<label class="form-label" for="phone">@Resources.Contact_Form_Phone <span class="mandatory">*</span></label>
<div class="form-input-ctn">
<input id="contact-phone" type="text" name="phone">
<div class="mandatory-error">@Resources.Contact_Form_Mandatory</div>
<div class="invalid-error">@Resources.Contact_Form_Invalid</div>
</div>
if (!string.IsNullOrEmpty(ViewBag.Subject))
<label class="form-label" for="subject">@Resources.Contact_Form_Subject</label>
<div class="form-input-ctn">
<input id="contact-subject" type="text" name="subject" value="@ViewBag.Subject">
<div class="mandatory-error">@Resources.Contact_Form_Mandatory</div>
</div>
<label class="form-label" for="message">@Resources.Contact_Form_Message <span class="mandatory">*</span></label>
<div class="form-input-ctn">
<textarea id="contact-message" class="form-textarea" name="message">@ViewBag.Message</textarea>
<div class="mandatory-error message-mandatory-error">@Resources.Contact_Form_Mandatory</div>
</div>
<label class="form-label"><span class="mandatory">*</span> @Resources.Contact_Form_Mandatory</label>
<div class="form-input-ctn">
<div id="contact-recaptcha-mandatory-error" class="recaptcha-mandatory">@Resources.Contact_Form_Mandatory</div>
<div id="contact-recaptcha" class="g-recaptcha" data-callback="reCaptchaOnValidCallback"></div>
</div>
<br />
<input id="contact-submit-btn" class="form-submit" type="submit" value="@Resources.Contact_Form_Send_Button" data-sending-message="@Resources.Contact_Form_Sending_Button">
我还加入了 Google reCaptcha,但没有任何改变。
在我的 Contact.submitOnBegin jQuery 代码中,我进行了所有验证以避免空白值和无效值:
var _submitOnBegin = function ()
_isFormValid();
if (isFormValid)
$submitBtn.prop('disabled', true);
var sendingMessage = $submitBtn.data("sending-message");
$submitBtn.addClass("submitting");
$submitBtn.val(sendingMessage);
else
return false;
;
在 isFormValid 函数中,我对每个输入进行所有测试:
var _isFormValid = function ()
// Reset
isFocusOn = false;
isFormValid = true;
// Name
if ($contactName.val() == "")
_showErrorMessage($contactName, contactErrorMandatoryCls);
// Email
if ($contactEmail.val() == "")
_showErrorMessage($contactEmail, contactErrorMandatoryCls);
else if (!_isEmailValid())
_showErrorMessage($contactEmail, contactErrorInvalidCls);
// Phone
if ($contactPhone.val() == "")
_showErrorMessage($contactPhone, contactErrorMandatoryCls);
else if (!_isPhoneValid())
_showErrorMessage($contactPhone, contactErrorInvalidCls);
// Message
if ($contactMessage.val() == "")
_showErrorMessage($contactMessage, contactErrorMandatoryCls);
// reCaptcha
var reCaptchaResponse = grecaptcha.getResponse();
if (reCaptchaResponse.length == 0)
isFormValid = false;
$("#contact-recaptcha-mandatory-error").addClass(contactErrorRecaptchaMandatoryCls);
;
var _reCaptchaRender = function ()
grecaptcha.render('contact-recaptcha',
'sitekey': 'XXX'
);
;
var _reCaptchaValid = function ()
$contactRecaptchaMandatoryError.removeClass(contactErrorRecaptchaMandatoryCls);
;
var _showErrorMessage = function (el, msg)
el.addClass(contactErrorMandatoryCls);
el.parent().find("." + msg).fadeIn();
if (!isFocusOn)
el.focus();
isFocusOn = true;
isFormValid = false;
;
更奇怪的是,他们能够使用 reCaptcha 破解表单,还可以在主题中发送空值。
如果一切正常,我会在 Contact.SubmitOnSuccess 中提交:
var _submitOnSuccess = function (ajaxResult)
sentResultOk = ajaxResult.Success;
$sentModal.load("/home/contactsent?cta=" + $contactCTA.val(), function ()
if (sentResultOk == true)
$("#" + sentModalOkId).show();
else
$("#" + sentModalErrorId).show();
$sentModal.fadeIn(function ()
$contactForm[0].reset();
grecaptcha.reset();
$submitBtn.removeClass("submitting");
$submitBtn.prop('disabled', false);
$submitBtn.val("Enviar");
);
);
【问题讨论】:
在您的服务器端代码中,您在哪里验证 reCaptcha 结果?我在这里只看到客户端代码。 如果您依靠客户端来告诉您它是否有效,那么这就解释了它被黑客入侵的原因。黑客只是告诉你它是有效的。你必须verify the user's response with Google 来验证他们确实解决了验证码,而不仅仅是告诉你他们已经解决了。 客户端不需要执行 javascript,甚至不需要在 Web 浏览器中与之交互。他们可以向您的服务器发送他们喜欢的任何请求。由您的 服务器端 代码来验证该请求。永远不要相信来自客户的任何东西。 基本上当用户向服务器提交表单时,该表单应该包含 reCaptcha 响应令牌。在服务器端代码中,您将验证表单(如果无效则返回错误),然后使用 Google 验证令牌(如果无效则返回错误),然后如果一切都有效,则处理表单。 也许,也许不是。如何处理任何给定的错误取决于您。也许客户端验证有一个错误,也许 reCaptcha 暂时存在连接问题等。您不需要假设用户正在做一些恶意的事情,只需适当地处理验证即可。因此,如果他们没有做恶意的事情,他们会看到一个有用的错误。如果他们正在做一些恶意的事情,他们看到的所有都是一个有用的错误。 【参考方案1】:我无法停止被黑客入侵并被用来向我发送垃圾邮件
问题的核心体现在对问题的评论中:
表单在有效之前永远不会进入服务器端,从我在 Google 文档中看到的文档中,我确信我只能从客户端进行验证
发生的事情是您依赖客户端告诉服务器一切都是有效的。所以任何黑客都可以简单地......告诉服务器一切都是有效的。
永远不要暗中相信来自客户的东西。始终验证。
对于 reCaptcha,Google 会使用令牌返回您的客户端代码,而您会 validate that token from your server-side code。请记住,此令牌的验证是在与处理表单相同的服务器端操作中完成的。毕竟,如果您首先让客户端将令牌发送到服务器并获得有效/无效响应,然后然后将表单发送到服务器,那么您将回到与以前相同的位置.. . 客户端只需将表单发送到服务器并声明它是有效的。
在不深入示例的情况下,整体流程应该是:
-
用户执行 reCaptcha,您的客户端代码从 Google 获取令牌。
客户端代码在发布到服务器之前验证表单。 (这不是安全步骤,这仅适用于 UX,因此用户不必等待服务器响应进行验证。)
用户将表单发布到服务器。这包括所有表单数据和您的客户端代码从 Google 收到的 reCaptcha 令牌。
服务器端代码验证表单。这与上述第 2 步的验证基本相同,只是再次检查它,因为您不能假设数据是有效的。
服务器端代码使用 Google 验证 reCaptcha 令牌。
如果一切顺利,请处理表单并继续申请流程。
任何失败的步骤,您都可以按照您认为合适的方式处理该错误。在大多数情况下,您只需将一些错误响应返回给客户端,要么通过重定向到错误页面,要么通过返回 AJAX 错误并在客户端代码中优雅地处理它。您无需假设任何错误是由于黑客攻击造成的。只是显示一个友好的错误,仅此而已。只要攻击者无法继续前进,错误内容对他们来说并不重要。
【讨论】:
以上是关于.Net MVC - 无法阻止我的 Ajax.BeginForm 被黑客入侵的主要内容,如果未能解决你的问题,请参考以下文章
SmtpClient.SendAsync 阻止我的 ASP.NET MVC 请求
如何通过更改 ASP.NET MVC 中的 Url 来阻止对控制器的访问?
从.net mvc api控制器下载角度应用程序中的文件时被CORS策略错误阻止