This book is new. If you'd like to go through it, then join the Learn Code Forum to get help while you attempt it. I'm also looking for feedback on the difficulty of the projects. If you don't like public forums, then email email@example.com to talk privately.
Exercise 51: lessweb
We are nearing the end of the book, so I'm going to give you one project in the final two exercises. You are going to create a web server. In this exercise you simply learn about the Python http.server module and how to create a simple web server using it. You'll be given instructions and then expected to read the documentation to figure out how to do it. There won't be too much guidance as, by now, you should be able to do most everything on your own.
Once you've created your web server you will then write a set of tests to attempt to hack you web server. I'll give you some guidance on this in the Breaking It section, but by now you should be very comfortable in finding flaws in code you write.
You'll need to read the Python 3 http.server documentation to start. You should also read the Python 3 http.client documentation as well as the documentation for Requests. You'll be using either requests or http.client to write tests for the http.server you create.
Next, your job is to create a web server using http.server that can do the following:
- Be configured from a configuration file
- Run continuously and handle requests it receives
- Serve up files from configured directories
- Respond to requests for websites and serve the correct content
- Log all requests coming in to a file to read later
If you read the example in the documentation you can probably get most of this working in a basic way. Part of this exercise is how to hack a naive web server, so you should just get it barely working and then we'll move to the next part.
Your job in this section is to attack your web server any way you can. You can start with the OWASP Top 10 Vulnerabilities list and then move on to other common attacks. You will also want to read the Python 3 os module documentation to implement some of the fixes. Here's an additional list of mistakes I'm positive you'll make:
- Unwanted directory traversal. You are probably taking the basic path from the URL (/some/file/index.html) and simply opening it as requested. Maybe you're adding the full path of the file on the OS (/Users/zed/web/some/file/index.html) and think you're good. Try accessing a file outside this directory by using .. path specifiers. If you can request /../../../../../../../../etc/passwd then you win. Try to explain why this happens and what can you do to fix it.
- Not handling unwanted requests. You most likely look for GET and POST, but what happens if someone does HEAD or OPTIONS?
- Sending a giant HTTP header. See if you can make the Python http.server explode or slow down by sending it a really large HTTP request header.
- Not raising an error when an unknown domain is requested. Some people take it as a feature (cough, Nginx) that a "random" website is served when the server doesn't recognize the domain. Your server should be white list only, and if it doesn't recognize the domain it should give a 404 error.
These are just a few of the small mistakes people make. Study as many others as you can, and then write automated tests for your server to demonstrate them before you fix them. If you can't find any of these errors in your server, then create them on purpose. It's also instructive to learn how these errors are made.
- Read about the os.chroot function in the Python 3 os documentation.
- Research how you would use that function and other os module functions to create a "chroot jail".
- Using as many of the functions in os, and any modules you can find, rewrite your server to properly chroot jail and drop privileges to a safe user (not root). On Windows this may be very difficult, so either try it out on a Linux computer or just skip this entirely.