Network attacks
Brute force, denial of service, data interception and SQL injection, and detecting a flood.
Do this lesson in the simulatorSome attacks go straight at the network and its computers. This lesson covers the ones on the exam: guessing passwords by brute force, flooding a service until it falls over, listening in on data as it travels, and tricking a database with SQL injection. You will build a detector that spots a flood of requests.
Brute force
A brute force attack tries every possible password until one works. A four-digit PIN has only 10,000 possibilities, which a computer tries in a moment. The longer and more varied a password, the more combinations there are, and the longer brute force takes.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
secret = "3742"
for guess in range(10000):
attempt = str(guess).zfill(4) # 0000, 0001, ... 9999
if attempt == secret:
print("cracked:", attempt, "after", guess + 1, "tries")
break
A four-character password using lower-case letters has 26 to the power 4, about 457,000 combinations; add capitals, digits and symbols and it climbs fast. That is why length and variety matter, and why systems lock you out after a few wrong tries.
Denial of service
A denial of service (DoS) attack floods a system with so many requests that it cannot answer real users: availability is broken. A distributed denial of service (DDoS) does it from thousands of hijacked computers at once, called a botnet, which makes it much harder to block.
Data interception
Data travelling across a network can be intercepted and read by someone listening in, using software called a packet sniffer. On open Wi-Fi this is easy, which is why sensitive data is encrypted (lesson F11.6): intercepted, it is unreadable.
SQL injection
A website that builds a database query out of what you type can be tricked. If a login box puts your input straight into a query, typing something like ' OR '1'='1 can make the query always true, letting an attacker in without a password. This is SQL injection. The fix is never to trust user input, and to use queries that keep the input separate from the command (lesson F7.3).
Detecting a flood
You cannot always stop an attack, but you can spot it. A sudden burst of requests from one source, far more than normal, is a sign of brute force or a flood. Count them and raise the alarm:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
requests = ["10.0.0.5", "10.0.0.5", "10.0.0.9", "10.0.0.5", "10.0.0.5", "10.0.0.5"]
counts = {}
for address in requests:
counts[address] = counts.get(address, 0) + 1
for address, n in counts.items():
if n >= 4:
print("BLOCK", address, "-", n, "requests")
else:
print("allow", address, "-", n, "requests")
Task: flood detector
Count how many requests come from each address in requests. Print <address>: <n> for each, sorted from the most requests to the fewest. Any address with 5 or more requests is an attack: print BLOCK on its line, and at the end print blocked: <addresses>, the blocked addresses joined by ,.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
requests = [
"10.0.0.5", "10.0.0.9", "10.0.0.5", "10.0.0.5", "10.0.0.2",
"10.0.0.5", "10.0.0.5", "10.0.0.9", "10.0.0.5", "10.0.0.5",
]
Challenges
- How many tries does brute force need, at most, for a 6-digit PIN?
- Why is a DDoS from a botnet harder to block than a DoS from one computer?
- Explain in one sentence how SQL injection lets someone log in without a password.