Search code examples
c#asp.netsecurityrecaptchacaptcha

How to fix Captcha vulnerability error in ASP.NET


We use a captcha (re-captcha) in our legacy, here is the captcha code in one of our ASPX pages that conducts user registration with help of Synec, Inc services

<div class="col-sm-4 form-group">
    <div class="g-recaptcha" data-sitekey="6Ld6ALQUAAAAAAW2GDkJiP9xKrfTvyEVDtYBO-kp"></div>
</div>

The vulnerabilities report says the following issues have been discovered during the scan.

  1. The application is implementing a weak CAPTCHA scheme, allowing for the submission with a CAPTCHA.
  2. This CAPTCHA is on the Registration Submission function for the website and is not implemented on a onetime-use basis.

IMPACT

  1. The lack of proper implementation defeats the purpose of the sites CAPTCHA scheme, allowing for the automation of subsequent requests utilizing the same Captcha code value.
  2. This could lead to: a malicious user spamming the server with multiple requests and the creation of wasteful resources/man-hours for the organization.
  3. Specifically, since this is on a Registration Submission

RECOMMENDED FIX

It is recommended to implement a more robust CAPTCHA scheme, such as Google reCAPTCHA.

  1. Implement proper logic in "if and else" clauses, which could differentiate between valid and invalid answers.
  2. Validate the CAPTCHA code server-side not allowing it to be resused more than once

To recreate the issue with the Captcha the Burp Intercept tool was used, which I can't use on my machine

I am a bit stuck and not sure what direction to go to since especially since we can't use Burp Intercept.

Can some one please help find the right direction to address this vulnerability?


Solution

  • Here is something that worked for me

        protected bool Validate()
        {
            string Response = Request["g-recaptcha-response"];//Getting Response String Append to Post Method
    
            if ((txtUsername.Text != (Session["PreviousLoginUsername"] ?? string.Empty).ToString() ||
                txtPassword.Text != (Session["PreviousLoginPassword"] ?? string.Empty).ToString()) &&
                (Response == (Session["PreviousLoginCaptcha"] ?? string.Empty).ToString()))
            {
                return false;
            }
    
            bool Valid = false;
            //Request to Google Server
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create
            (" https://www.google.com/recaptcha/api/siteverify?secret=6Ld6ALQUAAAAAIVP2u4dTDCnSFG5Yxa8bG8P9rFm&response=" + Response);
            try
            {
                //Google recaptcha Response
                using (WebResponse wResponse = req.GetResponse())
                {
    
                    using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
                    {
                        string jsonResponse = readStream.ReadToEnd();
    
                        JavaScriptSerializer js = new JavaScriptSerializer();
                        MyObject data = js.Deserialize<MyObject>(jsonResponse);// Deserialize Json
    
                        Valid = Convert.ToBoolean(data.success);
                    }
                }
    
                if (Valid)
                {
                    Session["PreviousLoginCaptcha"] = Response;
                    Session["PreviousLoginUsername"] = txtUsername.Text;
                    Session["PreviousLoginPassword"] = txtPassword.Text;
                }
    
                return Valid;
            }
            catch (WebException ex)
            {
                throw ex;
            }
        }