-
Notifications
You must be signed in to change notification settings - Fork 0
Security Solution
See here for more information on the organization's structure.
This solution focuses primarily on the prevention of Distributed Denial of Service attacks and common web application exploits.
Here we establish current vulnerabilities of the organization.
SQL injection occurs when an attacker submits malicious SQL queries into a user-interactable text-field tied to an SQL table. This can be used to add, see, change, or delete items in the connected table and so is important to prevent.
On the customer service page of the organization, the user may submit their email and list an issue they've been having. We can use SQL injection to alter the values of previous tickets. See the original php code below.
$conn->query("INSERT INTO help_tickets (email, issue) VALUES ('$email', '$issue')");
Say when we process the 'issue' part of the submission, we limit it to 200 characters, and we do this to manage how much space ..... COME BACK TO
A botnet attack is a type of Distributed Denial of Service attack in which an attacker recruits a network of "zombies," or systems that the attacker has gained control of in such a way that they may coordinate those systems to generate an inordinate amount of traffic to a web server. The botnet devices will often continue to operate as normal for month until they are "awakened" and begin sending high rates of requests to a singular web server or a group of webservers owned by the target. This overwhelms the web server, either causing it to crash or taking up so much space that those who are not in the botnet (actual users) can no longer access the site. This could also be used to submit an overwhelming amount of fake help tickets or sales, drowning out our actual users and rendering our data useless. When we are overwhelmed by an amount of requests, that is called resource exhaustion.
The goal of this solution is going to be to make sure that anyone who visits our site is an actual user and to prevent unwanted traffic. We will do this by setting up a Captcha System through AWS WAF which will require all users pass through a Captcha before actually getting to our website. Thus, connections without a human entity behind them will fail to reach our site and input poor data or overwhelm it. W
- We first set up our Web Application Firewall Access Control List as shown here
- Navigate to the Rules tab of your Web ACL
- Click Add rule and create your own rule
- Name your Rule something like "CAPTCHA_ALL"
- Change "If a request..." to (OR)
- Add in the following configuration in order to capture all traffic:
- In the action section, select CAPTCHA.
- Select "Custom Immunity Time for This Rule" and lower it as much as it will go. For me, that was 60 seconds.
- Create the Rule
- If we try to visit the website through the load balancer's DNS name now, we will have to pass a CAPTCHA to use the website.
Spoofing attacks are a type of Denial of Service attack in which an attacker sends web packets to a server, but instead of putting their IP address into the packet source information, they put a victim's IP address. The attacker sends a ton of web packets to the server, which when they are responded to get sent to the victim's IP, overloading their system and either causing it to crash or prevent it from receiving other requests.
An amplification attack is a type of spoofing attack that refers to a specific type of request-response relationship. Here we are looking at a small request which generates a large answer. This could be something as simple as requesting a massive file located in the server and sending thousands of responses to the victim's IP containing this huge amount of information. This will quickly overwhelm the victim and use up all of their bandwidth, known as bandwidth exhaustion.
In the case of Spoofing and Amplification attacks, the malicious responses are typically coming from one or just a handful of servers. We cannot prevent the malicious requests to some other server from being made, but we can limit the responses we receive -- or at least how quickly we receive them. By limiting the amount or frequency of packets sent to our web server, we can spread out the huge amounts of data we receive into a manageable time frame.
Let us examine the behavior of our website before implementing our solution. You may have to disable the earlier CAPTCHA rule by temporarily changing it's action from 'block' to 'count'.
We will be using the "loadtest" tool to simulate a DoS attack like Spoofing and Amplification.
- In the termminal of an ec2 instance, download npm sudo yum install npm
- Install loadtest sudo npm install -g loadtest
- execute the following, replacing DNS_NAME with the DNS name of your load balancer loadtest -n 9000 -c 1 --rps 200 http://DNS_NAME
This command sends 9000 requests one time at a rate of 200 requests per second and gives a report of responses to those requests as well as latency. Executing the above command should give us an output like this: Observe that there are 0 Errors, meaning that all requests were successful connections
We will make use of AWS WAF created in the previous section to introduce a rate-limiting rule.
- Navigate to the Rules tab of your Web ACL
- Click Add rule and create your own rule
- Name rule something like "rate_limit_all"
- Select "Rate-based rule"
- Set your rate limit to 200 and your evaluation window to 2 minutes.
- Keep all other settings at default.
Now execute the same loadtest command from before and observe the output:
A majority of requests are now blocked, so our rate-limiting tool is successful.
Cross-site scripting is a type of web application exploit in which an attacker injects malicious code into an otherwise trustworthy website, typically so that it executes on another user's machine. Any part of a web server with user-input that is not validated or normalized is at risk to these attacks. There are two types of XSS or cross-site scripting: reflected and stored. Reflected XSS executes and appears immediately after it is submitted. This could be as simple as an alert appearing on the user's screen or redirecting them to a malicious site. For the purposes of this project, we will use reflected XSS on our self rather than a different end user. Stored XSS is javascript stored in a database such that it executes when that item is retrieved from the database.
For the purposes of creating a solution for XSS, we will be using a bash script executed in the terminal to alter .php files. It surrounds all user-inputs which are not correctly normalized with htmlspecialchars which will prevent scripts from being stored in a way understandable to html. I struggled to generalize this script to get more than just $_POST calls, but it eventually got there after a couple hours of consistent fiddling.
- In your EC2 instance on which your web server is hosted, cd into /var/www/html
- Run sudo touch xss_sol.sh
- Now alter that file to contain the bash script located here
- Run sudo chmod +x xss_sol.sh to allow the file to execute
- For each .php file you want to correctly validate, run the following command sudo ./xss_sol.sh input_file.php output_file.php where the input file is the php you are normalizing and the output file is the file which will contained the normalized version. These can be the same file if you would like.
Example: Say we have the following file, an unprotected early version of submit_ticket.php:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Thank You!</h1>
<p>Your help ticket has been submitted.</p>
<?php
// Database connection info
$servername = 'localhost'; // who is hosting the sql server
$username = "otherUser"; // MariaDB username
$password = "other"; // MariaDB password
$dbname = "org"; // name of database we are using
// connect to database
$conn = new mysqli('localhost', $username, $password, $dbname);
// if they sent a post request (used the form)
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// grab email and described issue
$email = $_POST['email'];
$issue = $_POST['issue'];
// let the customer know we will get back to them
echo "<p>A customer service agent will reach out to you at $email soon</p>";
# add information to database
$sql = "INSERT INTO help_tickets (email, issue) VALUES ('$email', '$issue')";
$conn->query($sql);
} else {
echo "<p>Request method is not POST.</p>";
}
// close connection to database
$conn->close();
?>
<p><a href="customer_service.php">Submit another ticket</a></p>
<p><a href="index.html">Back to Home</a></p>
</body>
</html>
Notice how when it grabs from POST it does not validate. If we run this through our script, it outputs:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Thank You!</h1>
<p>Your help ticket has been submitted.</p>
<?php
// Database connection info
$servername = 'localhost'; // who is hosting the sql server
$username = "otherUser"; // MariaDB username
$password = "other"; // MariaDB password
$dbname = "org"; // name of database we are using
// connect to database
$conn = new mysqli('localhost', $username, $password, $dbname);
// if they sent a post request (used the form)
if (htmlspecialchars($_SERVER["REQUEST_METHOD"]) == "POST") {
// grab email and described issue
$email = htmlspecialchars($_POST['email']);
$issue = htmlspecialchars($_POST['issue']);
// let the customer know we will get back to them
echo "<p>A customer service agent will reach out to you at $email soon</p>";
# add information to database
$sql = "INSERT INTO help_tickets (email, issue) VALUES ('$email', '$issue')";
$conn->query($sql);
} else {
echo "<p>Request method is not POST.</p>";
}
// close connection to database
$conn->close();
?>
<p><a href="customer_service.php">Submit another ticket</a></p>
<p><a href="index.html">Back to Home</a></p>
</body>
</html>
This script, as you will see below is now more resistant to XSS attacks when put through this solution script.
In this case, we will be using the below javascript enclosed in html <script> tags to redirect the user to this site. On the submission page, php script here displays the user's email back to them, but it does not validate that field at all, so we can enter some javascript in the email field as shown below.
<script>window.location.href = 'https://github.com/shselbst/DDoS-IPS/wiki/Security-Solution';</script>
It is difficult to show here, but when the user presses submit, they see the submitted ticket screen for a brief second before being redirected to this page.
The solution for this is incredibly simple and can be done in less than one line of code. The method htmlspechialchars takes some string as a parameter and replaces all instances of html significant characters like "<" and ">" with HTML entities, or string representations of these characters. Thus, our script above won't actually be rendered as javascript since the "<" and ">" will not be picked up by the HTML. We do this via the previously mentioned script.
We replace this line in submit_ticket.php
$email = $_POST['email'];
$email = htmlspecialchars($_POST['email']);
Now instead of being redirected we see the following on the next page:
With stored XSS, we will also be redirecting users to our website, but now we will do it for anyone who visits the website. Note that the website displays the recent issue submissions by other users, a great tool for telling if everyone is having an issue or just you. However, because whatever is stored as an "issue" in the help ticket database is retrieved on this page for all users, if we submit some javascript as our issue, that javascript will execute for every visitor unless we validate and normalize input.
Typically when someone views the submission page it looks like this:
note: we assume that at this point the script utilizes prepared statements as a solution to sql injection for demonstration of this vulnerability Let us submit the same javascript from the reflected XSS example as an issue:
Observe the javascript now is in our SQL table:
Just like before it is a bit difficult to show, but since this javascript in "<script>" tags is now displayed on every user's browser, everyone who visits the site will be redirected. In this case, we are also applying a denial of service to the customer service portion of the website.
To solve this issue, we must do the same as with the reflected XSS solution and add htmlspecialchars around all places in which we grab this variable from the POST superglobal array. We do this via the earlier script.
$issue = $_POST['issue'];
becomes
$issue = htmlspecialchars($_POST['issue']);
and
echo "<br />".$row['issue']."<br />";
becomes
echo "<br />".htmlspecialchars($row['issue'])."<br />";
Now, when we submit new tickets, we see the following page:
Thus, our solution works.
We can also