I hack websites — 10 golden rules for full-stack beginners

Beranger Natanelic
10 min readJun 23, 2021

--

Having a side project is great, if it’s safe for the users

Warning

This article contains essential advice for beginners building their first web application, it also contains amateur hacking techniques that can considerably impact a web application. Use them with care, play a bit with them on others web applications but, Golden Rule 0 : “Don’t do unto others what you don’t want done unto you.”

Photo by Markus Spiske on Unsplash

IT students often want to code the next Airbnb, the next Facebook. As soon as they have some knowledge about how the internet works, they start following tutorials and create their first web app, reaching for the stars, thinking about their office in Silicon Valley.

As a student, I was one of them. I coded, in a few days, the next TripAdvisor+Airbnb+Maps+Rome2Rio. And I made coding and security mistake.

When I hear about a side project web app or even a startup release, I can’t help inspecting the source code and the network (Cmd+Opt+J). My previous CTO always said : “The truth is in the ‘Network’ tab.”

From all the freshly-born projects I saw, here is a compilation of common mistakes and how to create a more secure app:

Golden Rule 1 : No API key in frontend

Nope. Never. Niet. Nada.

“API Keys in the frontend” should raise a red flag in your mind.

I will go even further : No API key in code ! Frontend AND backend.

Keep in mind that everything you write in frontend code is readable by anyone (React itself says it). The frontend is in the user’s hands, he can change the design, change the content, read the code, read comments, read the logs.

When deploying a frontend application, you have to be sure that everything that you wrote (and copy-pasted!) can be read by Kevin Mitnick and isn’t a threat for your users.

On the last web app I looked into, the frontend was directly requesting Google Identity API, including the API Key in the request. It’s child’s play for us to create 1 000 000 fake users, with all the rate limit and financial consequences it can have for the API key owner. Don’t trust me? Check these stories about people who lost $50 000 this way.

I just said “No API key in code!”. API Key shouldn’t be present in back-end code as well. I assume you use GitHub or Gitlab to manage and share your code. That’s a big security threat to give them your credentials. Your API Key will then be visible by all developers. Even if you delete it, your API Key can be found in commits history.

What should you do?

Frontend : All requests to external APIs must be made by your server.

If you have to call Google API for example, call your server first, which will call the remote server, process the result and return it to the frontend. I detail this option in Golden Rule 2.

Backend: Create a .env file that includes all your API Keys, secret hashes… Add “.env” in the .gitignore file so that your file will stay on your computer.

When deploying your backend, don’t forget to manually add a .env file in the server (as it’s not cloned with Github). You can go even further: create an API Key for development purpose, shared with all your developers, and an API Key for production that only a few members have access to.

Golden Rule 2 : Centralise requests

As we saw in Golden Rule 1, all the requests involving external APIs should be made by your server.

This approach has many advantages :

  • Protect your API Keys: See Golden Rule 1
  • Keep your data providers secret: If you fear competitors and don’t want them to know your processes and your data providers
  • Preprocess the result: You only return what the user needs, and no sensitive information that might be returned by an external API
  • Whitelist your server IP to external API: That way, even if your API Key is stolen, a hacker can not directly call an external API pretending to be you (actually he/she can, but it’s harder)
  • Speed up operations: Users’ browsers are slower than your back-end server. There are exceptions, but let’s assume it’s a general truth: you should not perform any calculation (even formatting/concatenate…) on your visitor’s browser. It’s already a pain for them to load images, don’t mine bitcoin with a 15 year old computer!
  • Monitor: Every request going through your API can be measured and monitored. Maybe you don’t know now what you could do with this data, but one day you might need to analyse them, extract patterns, estimate growth… If all the requests are going through your server, you can record them.

Golden Rule 3: No personal data from the backend

Users’ personal data should not be visible by anyone!

A web app displaying a user list will identify them with a nickname (like Twitter), a first name (like Airbnb) or a full name (like Facebook).

But you will never see a public website displaying users’ phone numbers or emails; it’s called personal data that must be securely stored.

It should be the same from a backend point of view: a backend should never return sensitive data. Never.

This website displays a ranking on the right, all good 👌 But the API call returns additional data like user emails

Golden Rule 4: No personal data in JSON Web Token (JWT)

Yes, to create a JWT, you need a password that only you know.

Yes, to check a JWT, you need a password that only you know.

NO, to read a JWT you only need one website: jwt.io.

Let me say it again:

JSON Web Token can be read (easily)!

JWT is used to securely transmit information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret or a public/private key.

With this definition, beginners often think that JWT is protected by a secret/private key. But it’s not!

JWT is like a paper document covered by a sealed transparent cover: no one can modify it, but be sure that everyone can read it.

So, don’t even think about writing sensitive data if you use JWT as your authentication token!

The last web app I checked was doing it the right way: only storing user_id in the JWT for authentication.

BUUUUUUUUUUTTTTTTT

They were storing the JWT token INSIDE the database.

The main reason to use a JWT instead of a random token is that a JWT doesn’t need to be stored in a database as it can be automatically validated.

Golden Rule 5: Hash passwords — or don’t ask passwords

This Golden Rule is obvious and, generally, it’s the first thing developers learn. Maybe because they themselves use the same password for all websites and want to evaluate the risk (high).

When developing a web app involving user authentication, the password must be hashed as soon as the backend receives it. And then, only then, stored in a database.

I personally use the bcrypt algorithm to hash user’s passwords.

Passwordless authentication

Actually, that’s not totally true: I used to be a big fan of bcrypt, I now prefer passwordless authentication.

With passwordless authentication, the server send a code to the user by SMS or a link by email. The user then only has to copy the code or click on the link.

This method is better for the user (less password), safer (no same-password-everywhere issue) and easier for developing: no forgot password and change password features…

Let me tell you, passwords are dead.

Golden Rule 6: Don’t copy-paste blindly

When beginners want to build their first API, they often follow tutorials explaining how to create, update, list, delete records.

Fine.

But once a web application project is started, all the CRUD methods are not needed by all resources. Maybe the resource Books need a GET method to list all the books of a library. But the resource User should not have this method allowed!

When I check a web application, I enjoy understanding the database structure and listing what shouldn’t be listed, create what shouldn’t be created (with minor impact for the owner!!).

Let me give you an example : A few weeks ago, I checked a Shopping 2.0 website prototype. They were asking a code received by email to confirm an account. Once the code was validated, another route (POST /user) was called without any token check to create my account. How easy would it be to create 1B users with fake email addresses?

The rule to remember is the following: Start with absolutely nothing, and only explicitly allow what you do want.

Golden Rule 7: Don’t really know what you are doing ? Don’t Reinvent The Wheel.

Especially for a side project.

I like coding stuff and features myself. Authentication for example : I prefer managing my own database, storing my users and their password, sending myself (my server) the confirmation email.

But I know what I am doing and I have already tried the other alternatives (AWS Cognito and Google Identity).

But if you aren’t so sure about the processes => Go for a widespread tool. You will have time later to figure out and move to something where you have more control.

I give this advice because a web app I checked was using Google Identity to manage their users. That was a great decision not to put user’s passwords at risk as the owner seemed to be a beginner.

A web app side project is hard work. From frontend deployment to user authentication (if it has it), there are a lot of things to learn, it’s not shameful to delegate some crucial features to experts. It’s safer and faster.

Golden Rule 8: Validate all input on the backend side

Frontend validation is not enough.

I wonder the proportion of web applications that only check data on the frontend side.

All the possible regex to validate an email on the frontend side is useless if not made on the backend side.

It is the easiest thing for an attacker to POST to an API and change data format.

And if this happens… That’s not so good…

Firstly, if an attacker POST an unexpected format data, the server will crash. Because it will try to process a string but the attacker will send integer (or any other type). The attacker can add attributes or remove required attribute in the request. There might be some error handling but that’s not enough to protect a server.

Secondly, if the input data is not checked, the attacker can do SQL Injection. A SQL injection is an attack where the user can insert SQL statements into the input data. This SQL Statement can be interpreted as a command to be run on the database. SQL Injections is ranked number 1 in OWASP’s Top 10 for web vulnerabilities.

The famous rule to remember is: Never trust your user

Golden Rule 9: Monitor, Log and check

I guess many fresh websites don’t have any monitoring tools set up. Because weeks after I discovered and manipulated a certain website, there were still the same breaches.

If they had some monitoring and logging tools, they would have seen requests to the backend directly coming from a mysterious 193.XX.XX.XXX IP address.

Monitoring is the third eye of an application. In many different ways!

Monitoring helps to understand how users interact with the frontend. It helps to detect failures (if an IP ask 15 times the same thing, that’s not so good)…

Actually, I won’t make this article longer : - You heard that data is the new Oil right? Understand why and create data.

Monitoring helps me sleeping at night. My servers have complete monitoring set up; if one of them stops working, I will be notified within 2 minutes. If I’m not: no news, good news.

Above from the usefulness of monitoring, being able to see who is using our own app, what they are doing, for how long… it’s super motivating to keep coding!

Golden Rule 10: Implement an API Gateway

Some of the previous rules are long to implement and maintain: Monitoring, Logging, Rate-limiting. Implementing an API Gateway is a great solution if you want to act fast and safely.

An API Gateway is a facade that provides an API interface. It is like the front door of an application where all the requests made on a server are going through.

Having an API Gateway setup allows developers to focus their attention on this part. Developers often make the mistake to have a super-secured frontend, but frontend doesn’t need much attention compared to the API Gateway.

Additionally, an API Gateway fixes few of the issues discussed in this article :

  • Deciding specifically what routes are open to the world (even after having copy-pasted a CRUD logic with all your API entities (Golden Rule 3))
  • A default rate-limit that can easily be lowered
  • A default payload size limit (in some of them)
  • Monitoring and Logging : An API Gateway is like a toll, everything that uses your routes is logged and recorded
  • Other cool and cheesy easy stuff that make life easier

Golden Rule 11: Forget hammock

Security is a daily work, depending on the size of your audience, you should spend anywhere between a few hours to days verifying that everything is working well, reading logs, investigating to find suspect behavior.

Go further?

This list is only a subset of the best practices when developing a web application. Some Golden Rules listed here solve some of the OWASP’s Top 10 for web vulnerabilities but partially and not all of them. These Golden Rules will help beginners to build a more secure application but the work only starts here! I would love to have experts’ feedback to improve this article and correct it!

Think about your friends’ side projects: send them this article before I steal their users emails! 😜

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiSGV5ISBJZiB5b3Ugd2VudCB0aGF0IGZhciwgSSB0aGluayBJIGRlc2VydmUgc29tZSBjbGFwcyBvbiBNZWRpdW0hIDspIELDqXJhbmdlciJ9.gLlL1qC75B-_l3m8n98Xz9P1qYGvFgoqEvnobjCOYRU

--

--

Beranger Natanelic

Daily Google Cloud Platform user. I am sharing learnings of my tries, struggle and success.