#jquery #ajax #asp.net-mvc #forms
#jquery #ajax #asp.net-mvc #формы
Вопрос:
Я создал форму на основе Ajax в своем веб-приложении .Net MVC, но я не могу перестать быть взломанным и использоваться для отправки мне спам-сообщений.
@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, а также, например, отправлять пустые значения в теме.
И в контакте.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");
});
});
Комментарии:
1. Где в вашем серверном коде вы проверяете результат reCAPTCHA? Я вижу здесь только код на стороне клиента.
2. Если вы полагаетесь на то, что клиент сообщит вам, является ли он действительным или нет, это объясняет, почему он взломан. Хакер просто говорит вам, что он действителен. Вы должны проверить ответ пользователя с помощью Google , чтобы убедиться, что они действительно разгадали капчу, а не просто говорят вам, что они это сделали.
3. Клиенту не требуется выполнять JavaScript или даже взаимодействовать с ним в веб-браузере. Они могут отправлять на ваш сервер любой запрос, который им нравится. Проверка этого запроса зависит от вашего серверного кода. Никогда не доверяйте ничему, что исходит от клиента.
4. По сути, когда пользователь отправляет форму на сервер, эта форма должна включать токен ответа reCAPTCHA. В коде на стороне сервера вы должны проверить форму (вернуть ошибку, если недопустимо), затем проверить токен с помощью Google (вернуть ошибку, если недопустимо), затем, если все правильно, вы обрабатываете форму.
5. Может быть, а может и нет. Вам решать, как обрабатывать любую данную ошибку. Возможно, в проверке на стороне клиента была ошибка, возможно, на мгновение возникла проблема с подключением к reCAPTCHA и т. Д. Вам не нужно предполагать, что пользователь делает что-то вредоносное, просто обработайте проверку соответствующим образом. Поэтому, если они не делают что-то вредоносное, они видят полезную ошибку. И если они делают что-то вредоносное, все , что они видят, это полезная ошибка.
Ответ №1:
Я не могу перестать быть взломанным и использоваться для отправки мне спам-сообщений
Суть проблемы отражена в комментарии к вопросу:
форма никогда не переходит на серверную часть, пока она не станет действительной, и из документов, которые я видел в документации Google, я был убежден, что могу выполнить проверку только на стороне клиента
Происходит то, что вы полагаетесь на то, что клиент сообщает серверу, что все действительно. Так что любой хакер может просто… сообщите серверу, что все действительно.
Никогда не доверяйте неявно тому, что исходит от клиента. Всегда проверяйте.
Для reCAPTCHA Google возвращает ваш клиентский код с токеном, и вы должны проверить этот токен из своего серверного кода. Помните, что проверка этого токена выполняется в той же операции на стороне сервера, что и обработка формы. В конце концов, если сначала клиент отправит токен на сервер и получит действительный / недопустимый ответ, а затем отправит форму на сервер, вы вернетесь в то же место, что и раньше… Клиент может просто отправить форму на сервер и заявить, что она действительна.
Не вдаваясь слишком глубоко в примеры, общий поток должен быть:
- Пользователь выполняет reCAPTCHA, ваш клиентский код получает токен от Google.
- Клиентский код проверяет форму перед отправкой на сервер. (Это не шаг безопасности, это просто для UX, поэтому пользователю не нужно ждать ответа сервера для проверки.)
- Пользователь отправляет форму на сервер. Сюда входят все данные формы и токен reCAPTCHA, полученный вашим клиентским кодом от Google.
- Серверный код проверяет форму. По сути, это та же проверка, что и в шаге 2 выше, просто перепроверьте ее, поскольку вы не можете предположить, что данные действительны.
- Серверный код проверяет токен reCAPTCHA с помощью Google.
- Если все проверено, обработайте форму и продолжайте работу с приложением.
Любой шаг, который завершается неудачей, вы обрабатываете эту ошибку так, как считаете нужным. В большинстве случаев вы просто возвращаете клиенту некоторый ответ об ошибке, либо перенаправляя на страницу с ошибкой, либо возвращая ошибку AJAX и корректно обрабатывая ее в клиентском коде. Вам не нужно предполагать, что какая-либо ошибка вызвана попыткой взлома. Просто покажите дружественную ошибку, вот и все. Пока злоумышленник не может продвинуться дальше, для них не имеет значения, что говорит ошибка.