Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Liam Dilley 90 posts 236 karma points
    Nov 10, 2020 @ 04:00
    Liam Dilley
    0

    Umbraco Forms spam issue

    We have have the latest Umbraco forms and a few versions down on a number of Umbraco 8 sites. We also have version 7 sites.

    In the last few weeks our agency have been hit with many of our clients reporting spam issues.

    Every form being spammed has reCaptcha installed and we are not able to submit the forms in testing as a user without the server side validation taking place.

    • Each site has unique keys in the config and not the same or one that comes with umbraco forms config.
    • Recaptcha field added and not sent to sensitive or mandatory (because they cause issues as documented and making it mandatory does nothing in this issue)
      • Sites hosted on AWS

    All issues have only occurred in the month only some form/site setups over a year+ old did not have the issue before.

    A lot of it is all Russian, Some sites are being hit every 5 minutes.

    I have made a support ticket in Git on Umbraco forms but not got any update there yet. I am reaching out to the community to see if anyone else has seen this or have any workarounds they may have done?

    One option is to use the handler class on form submission provided and do an email white list. That would get it partly but many have randomised gmail emails for example.

    It is just really odd we been hit across multiple sites at the same time only recently. Does anyone know if the forms use a Nuget Package for the captcha element, maybe that has a vulnerability being used? Or anything else?

  • Amir Khan 1186 posts 2533 karma points
    Nov 10, 2020 @ 19:51
    Amir Khan
    0

    Have you looked at your recacapcha dashboard to see if there are any trends? Also, are all of these sites hosted on the same server within AWS or is it different environments?

  • Liam Dilley 90 posts 236 karma points
    Nov 10, 2020 @ 22:48
    Liam Dilley
    0

    Hi Amir, Same AWS region across two hosts.

    I have been looking at the recaptcha trends. Some sites just have the average and have for a while and the sites with issues have a lot of fails but the problem is not that it fails as that is blocking them but the fact that the pass rate as well is crazy high.

    We have one site which uses a different solution and I know it uses one of the most commonly used Nuget packages for reCaptcha. My current thoughts are leading to that package possibly having a flaw that is being utilised and that Umbraco forms may be using the same thing? It is likely a bot that on success just then hammers the sites it has come across?

  • Adam Werner 15 posts 166 karma points c-trib
    Nov 10, 2020 @ 22:59
    Adam Werner
    0

    I ran into a similar problem with a v7 site with the reCAPTCHA allowing spam to pass through.

    I did find a a post on the old issues.umbraco.org -- https://issues.umbraco.org/issue/CON-941

    The Umbraco implementation was using the Recaptcha2.cs class in the App_Code directory. We used one of the comments as guidance and updated line 77 in the Recaptcha.cs file from

    var error = field.Settings["ErrorMessage"];
    

    to

    var error = (field.Settings.ContainsKey("ErrorMessage")) ? field.Settings["ErrorMessage"] : string.Empty;
    

    After updating that line of code we have not seen any more spam to date.

    If you're using that reCAPTCHA implementation in Umbraco Forms, this could be the solution needed.

  • Liam Dilley 90 posts 236 karma points
    Nov 25, 2020 @ 01:14
    Liam Dilley
    0

    Thanks, with Umbraco forms that is all in the dll's now but I passed that on in my git issue to see if that is what they are still doing alone with the code you provided that helped you. Thanks.

  • Markus Johansson 1689 posts 4814 karma points c-trib
    Nov 17, 2020 @ 21:58
    Markus Johansson
    0

    We like to avoid recaptcha to keep convensions at the highest possible rate.

    Our solution is a timer in the form, if it’s posted in 10-15 seconds since the page load we consider it spam as no normal user would post the form so fast. After using this for about 5 months and logging all spam we haven’t seen no real email in the spam-logs :)

  • Liam Dilley 90 posts 236 karma points
    Nov 25, 2020 @ 00:21
    Liam Dilley
    0

    Where do you hook that into on Umbraco forms Markus? Or are you referring to custom built forms?

  • Markus Johansson 1689 posts 4814 karma points c-trib
    Nov 27, 2020 @ 08:49
    Markus Johansson
    100

    @Liam, well we made some some small modifications in the form-cshtml and then we're using a custom Workflow that internally use lots of stuff from Umbraco's build in Workflow.

    In the forms cshtml:

    We add two fields

    • A input-text that we move out of screen with CSS (like position: absolute; top:1500px; or something) This is expected to always be empty since no user would be able to fill it out. Good practice to not name it name, zip, city or something since autofill in browser might fill this out.
    • A input-hidden with a timestamp of when the form was loaded.

    The Workflow:

     public class SendEmailEnhancedWorkflow : WorkflowType
     {
    
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IFieldTypeStorage _fieldTypeStorage;
    
        [Umbraco.Forms.Core.Attributes.Setting("",
            Name = "Receiver Email(s)",
            Description = "Enter receiver email(s), separate with semicolon if more than one.",
            Alias = "receiverEmails",
            PreValues = "",
            View = "TextArea")]
        public string ReceiverEmails { get; set; }
    
        [Umbraco.Forms.Core.Attributes.Setting("",
            Name = "Subject",
            Description = "Enter a subject for the e-mail. If empty a generic subject will be used.",
            Alias = "subject",
            PreValues = "",
            View = "TextString")]
        public string Subject { get; set; }
    
        public SendEmailEnhancedWorkflow(
            IHttpContextAccessor httpContextAccessor,
            IFieldTypeStorage fieldTypeStorage
            )
        {
    
            _httpContextAccessor = httpContextAccessor;
            _fieldTypeStorage = fieldTypeStorage;
    
    
            this.Id = new Guid("F3D257D0-E203-452B-BA83-D5A6E7356AF5");
            this.Name = "Send Email (Enhanced)";
            this.Description = "Sends email with enhanced details in the body (ie Page Url).";
            this.Icon = "icon-message";
    
        }
    
        public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e)
        {
            // Checks both a "meta field" (a text box moved out of screen with css) and the timing between form load and posting.
            // If honeypot if not passed we return completed without sending a email. The PassedHoneyPot-method also removes
            // the entry from the database
            if (!UmbracoFormsWorkflowHelper.PassedHoneyPot(_httpContextAccessor, record))
                return WorkflowExecutionStatus.Completed;
    
            var emailSubject = "From website";
            if (!string.IsNullOrEmpty(this.Subject))
                emailSubject = this.Subject;
    
            UmbracoFormsWorkflowHelper.SendEmail(this.ReceiverEmails, emailSubject, record, _fieldTypeStorage, _httpContextAccessor);
    
            return WorkflowExecutionStatus.Completed;
        }
    
        public override List<Exception> ValidateSettings()
        {
            if(string.IsNullOrEmpty(this.ReceiverEmails))
                return new List<Exception>(){new ArgumentException("Receiver Email's can't be empty. Add at least one receiver.")};
    
            return UmbracoFormsWorkflowHelper.ParseExceptionsFromDelimitedEmailString(this.ReceiverEmails);
        }
    
    }
    

    Parts of the the helper:

    namespace Site.Web.Forms.Workflow
    {
      public class UmbracoFormsWorkflowHelper
      {
    
        public static bool PassedHoneyPot(IHttpContextAccessor httpContextAccessor, Record record)
        {
            // Perform checks and make sure that the meta input is empty and that X time has passed between the form was loaded and posted.
    
            if (didPass)
            {
                return true;
            }
            else
            {
                // Log rejected form post
                StringBuilder sb = new StringBuilder();
                foreach (var field in record.RecordFields)
                {
                    sb.Append($"{field.Value.Alias}: {field.Value.ValuesAsString()}\n");
                }
                var postedFormValues = sb.ToString();
    
                DependencyResolver.Current.GetService<ILoggerStructured>().Warn<UmbracoFormsWorkflowHelper>("Form submission was caught by HoneyPot: {honeyPotCaptureType}", honeyPotCaptureType, postedFormValues);
    
    
                Task.Run(() => DeleteRecordWithDelay(record.UniqueId.ToString(),record.Form.ToString()));
    
                return false;
            }
    
        }
    
        public static async Task DeleteRecordWithDelay(string recordId,string formId)
        {
    
            await Task.Delay(2500);
    
            try
            {
                IRecordService recordService = DependencyResolver.Current.GetService<IRecordService>();
                IRecordStorage recordStorage = DependencyResolver.Current.GetService<IRecordStorage>();
                IFormService formService = DependencyResolver.Current.GetService<IFormService>();
    
                var form = formService.GetForm(Guid.Parse(formId));
                var record = recordStorage.GetRecordByUniqueId(Guid.Parse(recordId), form);
    
                recordService.Delete(record, form);
            }
            catch (Exception e)
            {
    
                var exception = e.Message;
                throw;
            }
    
        }
    }
    

    }

    Hope these pointers was helpful =D

Please Sign in or register to post replies

Write your reply to:

Draft