Software developers have to keep a lot of information in their head. There are many questions to ask when it comes to building a website or application: What technologies to use? How will the structure be set up? What functionality do we need? What will the user interface look like? Especially in the software market, where the production of applications is more like a race for reputation than a well-thought-out process, one of the most important questions that often remains at the bottom of the “Critical List”: How will our product be protected?

If you are using a reliable, open source framework to build your product (and if one is available and usable, why not?), Then basic security issues like CSFR attacks and password encryption may already be solved for you.

However, it will be useful for fast-growing developers to brush up on common threats to avoid newbie mistakes. Usually the weakest point in the security of your software is you.

Who can hack? There is an ethical hacker – someone who looks for possible security weaknesses and privately tells them to the creators of the project.

And the black hacker, also called the “cracker”, is one who uses these weaknesses for extortion or for his own good.

These two kinds of hackers can use the same set of tools and, in general, try to get to places where the average user cannot get. But white hackers do it with permission, and in the interest of strengthening protection, not destroying it. Black hackers are bad guys.

Some examples of the most common attacks that exploit security vulnerabilities are: SQL Injection and XXS Cross-Site Scripting.


SQL Injection (SQLi) is a type of injection attack that allows you to execute malicious SQL commands to retrieve data or crash an application. Basically, attackers can send SQL commands that affect your application through some input to your site, such as a search box that fetches results from your database. PHP-coded sites can be particularly susceptible to them, and a successful SQL attack can be devastating to software that relies on the database (for example, your users table is now empty space).

You can check your own site to see how susceptible it is to these types of attacks. (Please only test sites that you own, as running SQL where you don’t have permission to do so might be illegal in your area; and definitely not very funny.) The following payloads can be used for tests :

  • ' OR 1='1 evaluates to a constant true, and if successful, returns all rows in the table
  • ' AND 0='1 evaluates to a constant false, and returns no rows on success.

Fortunately, there are ways to mitigate SQL attacks, and they all boil down to one basic concept: Don’t trust user input .


To effectively contain attacks, developers must prevent users from successfully submitting raw SQL commands to any part of the site.

Some frameworks will do most of the hard work for you. For example, Django implements the concept of object-relational mapping, or ORM, using querysets. We will consider them as wrapper functions that help your application query the database using predefined methods, avoiding the use of raw SQL.

However, being able to use a framework is never a guarantee. When we deal directly with the database, there are other techniques we can use to safely abstract our SQL queries from user input, although they vary in efficiency. They are presented in order from more to less important:

  1. Variable bind prepared statements (or parameterized queries)
  2. Stored procedures
  3. Whitelisting or escaping user input

If you are looking to implement the above methods, then these cheat sheets are a great starting point to explore in more depth. Suffice it to say that using these methods to retrieve data instead of using raw SQL queries helps to minimize the chances of SQL being processed by any part of your application that accepts input from users, thereby mitigating SQL attacks.


If you are a hacker, then JavaScript is pretty much your best friend. The right commands will do everything that a regular user can do (and even some things they shouldn’t) on a web page, sometimes without any interaction from the real user.

Cross-site scripting attacks, or XSS , occur when JavaScript code is injected into a web page and changes its behavior. Its consequences can range from nasty jokes to more serious authentication bypasses or stealing credentials.

XSS can take place on the server or on the client side and typically comes in three flavors: DOM (Document Object Model) based on stored and rendered XSS. The differences come down to where the attack payload is injected into the application.


DOM-based XSS occurs when a JavaScript payload affects the structure, behavior, or content of a web page loaded by a user into their browser. They are most often performed through modified URLs, such as in phishing emails.

To see how easy it would be for injected JavaScript to manipulate the page, we can create a working example with an HTML web page. Try to create a file on your local system called xss-test.html(or whatever) with the following HTML and JavaScript code:

        <title> My XSS Example </title>
        <h1 id = "greeting"> Hello there! </h1>
                var name = new URLSearchParams ( .get ('name');
                if (name! == 'null') {
                    document.getElementById ('greeting'). innerHTML = 'Hello' + name + '!';

This web page will display the title "Hello!”unless it receives a URL parameter from a query string with a value name. To see the script working, open the page in a browser with the URL parameter added, for example:

file: ///path/to/file/xss-test.html? name = Victoria

Our unsafe page takes the value of the URL parameter for the name and displays it in the DOM. The page expects the value to be a nice friendly string, but what if we change it to something else? Since the page belongs to us and exists only on our local system, we can test it as much as we want. What happens if we change the parameter to name, say,:

<img + src + onerror = alert ("pwned")>

This is just one example that demonstrates how an XSS attack can be performed. Funny pop-up alerts can be funny, but JavaScript can do a lot of harm, including helping attackers steal passwords and personal information.


Stored XSS occurs when the payload of an attack is stored on a server, such as a database. The attack affects the victim whenever this stored data is retrieved and displayed in the browser.

For example, instead of using a URL query string, an attacker could update their profile page on a social site to inject a hidden script, say, in the About Me section. A script that is incorrectly stored on the site server will run successfully as long as another user is viewing the attacker’s profile.

One of the most famous examples of this is the Samy worm, which practically took over MySpace in 2005. It spread by sending HTTP requests that copied it to the victim’s profile page whenever an infected profile was viewed. In just 20 hours, it spread to over a million users.

Reflected XSS similarly occurs when input is sent to the server, but the malicious code is not stored in the database. Instead, it is immediately returned to the browser by the web application.

Such an attack can be carried out by luring the victim to follow a malicious link, which sends a request to the server of the vulnerable website. The server will then send a response to the attacker as well as to the victim, which could lead to the attacker being able to obtain passwords or perform actions that allegedly come from the victim.


In all of these cases, XSS can be contained through two key strategies: validating form fields and preventing direct user input on a web page.


Frameworks can help us again when it comes to making sure user submitted forms are up to date. One example is Django’s built-in field classes, which provide fields that validate some commonly used types and also set normal defaults.

For example, Django’s email field uses a set of rules to determine if the input provided is valid email. If the submitted string contains characters that are not normally found in email addresses, or if it does not mimic the general format of an email address, then Django will not consider this field valid and the form will not be submitted.

If you cannot rely on the framework, you can implement your own input validation. This can be done using several different methods, including type conversion, for example, ensuring that the number is of a type int(); checking the minimum and maximum values ​​of the range for numbers and string lengths; using a predefined array of options, which avoids arbitrary input, for example, months of the year; and checking data against strict regular wording.

Fortunately, we don’t have to start from scratch. Available open source resources, such as the OWASP regex repository validation, which provides templates for matching against some common forms of data, will help. Many programming languages ​​offer validation libraries specific to their syntax, and we can find many such libraries on GitHub.

While it may seem tedious, properly implemented input validation can protect our application from XSS susceptibility.


Application elements that directly return user input to the browser may not be obvious to normal validation. We can identify areas of the application that might be at risk by examining several questions:

  1. How does the data flow through the application?
  2. What does the user expect when they interact with this input?
  3. Where does the data appear on our page? Do they become inline in a string or attribute?

Here are some examples of payloads we can play with to validate inputs on our site (again, only on our own site!). Successful execution of any of these samples may indicate a possible XSS vulnerability due to direct input.

  • "><h1>test</h1>
  • '+alert(1)+'
  • "onmouserover="alert(1)
  • http://"onmouseover="alert(1)

Generally, if you can bypass direct data entry, do so. Also, make sure you fully understand the effectiveness of the chosen methods; for example, using innerText instead of innerHTML in JavaScript ensures that the content is set as plain text instead of (potentially vulnerable) HTML.


Software developers are clearly at a disadvantage when it comes to competing with black hackers. Despite all the work done to protect every input that could potentially compromise our application, an attacker only needs to find the one we missed. It’s like installing bolts on all doors, but leaving the window open!

However, by learning to think in the same vein as an attacker, we can better prepare our software to face the bad guys. As fun as it is to add features as quickly as possible, we can avoid a lot of cybersecurity debt by thinking ahead of our application flow, tracking the data, and paying attention to our inputs.