This shows you the differences between two versions of the page.
| — |
isc:lab-test2 [2026/10/03 18:40] (current) florin.stancu created |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Lab 01 - Recover the Grades Application ====== | ||
| + | ===== Objectives ===== | ||
| + | |||
| + | At the end of this lab, you should be able to: | ||
| + | |||
| + | * use basic Linux commands during a security investigation; | ||
| + | * use Python to automate repetitive tasks; | ||
| + | * inspect and repair files based on their format; | ||
| + | * identify hidden or embedded content; | ||
| + | * interact programmatically with a web application; | ||
| + | * use a new security analysis tool; | ||
| + | * relate practical security problems to the concepts discussed during the first lecture. | ||
| + | |||
| + | ===== Scenario ===== | ||
| + | |||
| + | The university has recovered an old application used for managing student grades. | ||
| + | |||
| + | Unfortunately, the administrator who maintained the application is unavailable and the documentation is incomplete. | ||
| + | |||
| + | You have received only two files from the administrator: | ||
| + | |||
| + | <code> | ||
| + | pass.txt | ||
| + | bla.zip | ||
| + | </code> | ||
| + | |||
| + | Your goal is to recover the application, start it, authenticate to it and find the forgotten administrative interface. | ||
| + | |||
| + | Each exercise continues from the previous one. | ||
| + | |||
| + | ===== Using an LLM ===== | ||
| + | |||
| + | You are encouraged to use an LLM during this lab, but use it as a technical assistant, not as a CTF solver. | ||
| + | |||
| + | Good questions include: | ||
| + | |||
| + | <code> | ||
| + | How can I use find to locate a file of exactly 987 bytes? | ||
| + | |||
| + | What does this output from the file command mean? | ||
| + | |||
| + | What is the header of a PNG file? | ||
| + | |||
| + | What does this Python exception mean? | ||
| + | |||
| + | How can I add a delay between HTTP requests in Python? | ||
| + | Do not paste the complete lab, upload the archive or ask: | ||
| + | |||
| + | <code> | ||
| + | Solve this exercise for me. | ||
| + | |||
| + | Here is the entire lab. Give me all the flags. | ||
| + | Try to formulate a small question about the specific problem you are currently trying to solve. | ||
| + | |||
| + | ===== Useful Tools ===== | ||
| + | |||
| + | * ‘‘man’’ | ||
| + | * ‘‘find’’ | ||
| + | * ‘‘file’’ | ||
| + | * ‘‘base64’’ | ||
| + | * ‘‘xxd’’ | ||
| + | * ‘‘hexedit’’ | ||
| + | * ‘‘unzip’’ | ||
| + | * ‘‘binwalk’’ | ||
| + | * ‘‘gzip’’ | ||
| + | * ‘‘bzip2’’ | ||
| + | * ‘‘tar’’ | ||
| + | * Python | ||
| + | * ‘‘requests’’ | ||
| + | * ‘‘curl’’ | ||
| + | * Docker / Docker Compose | ||
| + | |||
| + | ===== 01. Serious Security ===== | ||
| + | |||
| + | The administrator left the following message: | ||
| + | |||
| + | I am a serious security guy, so obviously I did not leave the passwords in plaintext. I protected them using Base64. Several times. | ||
| + | |||
| + | You received: | ||
| + | |||
| + | <code> | ||
| + | pass.txt | ||
| + | </code> | ||
| + | |||
| + | Determine how the contents were encoded and recover the original information. | ||
| + | |||
| + | You may find the following commands useful: | ||
| + | |||
| + | <code bash> | ||
| + | cat pass.txt | ||
| + | base64 -d | ||
| + | </code> | ||
| + | |||
| + | One decoding operation might not be enough. | ||
| + | |||
| + | Continue until you obtain readable information. | ||
| + | |||
| + | At the end of this exercise you should have a list of possible passwords. | ||
| + | |||
| + | Save the result as: | ||
| + | |||
| + | <code> | ||
| + | passwords.txt | ||
| + | </code> | ||
| + | |||
| + | You will need it in the next exercise. | ||
| + | |||
| + | ===== 02. Zip it good ===== | ||
| + | |||
| + | The second file provided by the administrator is: | ||
| + | |||
| + | <code> | ||
| + | bla.zip | ||
| + | </code> | ||
| + | |||
| + | Unfortunately, it is password protected. | ||
| + | |||
| + | Fortunately, the administrator appears to have used one of the passwords contained in ‘‘passwords.txt’’. | ||
| + | |||
| + | Your task is to find the correct password and extract the archive. | ||
| + | |||
| + | You could try every password manually, but that would be boring. | ||
| + | |||
| + | Write a small Python program that: | ||
| + | |||
| + | * reads the passwords from ‘‘passwords.txt’’; | ||
| + | * tries each password against ‘‘bla.zip’’; | ||
| + | * stops when the correct password is found; | ||
| + | * extracts the archive. | ||
| + | |||
| + | Python provides the following module: | ||
| + | |||
| + | <code python> | ||
| + | import zipfile | ||
| + | </code> | ||
| + | |||
| + | You may find the documentation for ‘‘ZipFile.extractall()’’ useful. | ||
| + | |||
| + | At the end of this exercise you should have a directory containing the recovered grades application. | ||
| + | |||
| + | ===== 03. Find the configuration ===== | ||
| + | |||
| + | You now have the application files. | ||
| + | |||
| + | Unfortunately, the administrator does not remember which file contains the application configuration. | ||
| + | |||
| + | Somewhere inside the extracted directory there is a file with all of the following properties: | ||
| + | |||
| + | * human-readable; | ||
| + | * exactly 987 bytes in size; | ||
| + | * not executable. | ||
| + | |||
| + | Find it. | ||
| + | |||
| + | Useful commands include: | ||
| + | |||
| + | <code bash> | ||
| + | find | ||
| + | file | ||
| + | ls | ||
| + | stat | ||
| + | </code> | ||
| + | |||
| + | Do not manually inspect every file. | ||
| + | |||
| + | Once you find the correct file, inspect its contents. | ||
| + | |||
| + | You should discover a server configuration similar to: | ||
| + | |||
| + | <code ini> | ||
| + | [server] | ||
| + | host = 0.0.0.0 | ||
| + | port = 0 | ||
| + | </code> | ||
| + | |||
| + | The configured port is invalid for this application. | ||
| + | |||
| + | Change it to: | ||
| + | |||
| + | <code ini> | ||
| + | port = 8080 | ||
| + | </code> | ||
| + | |||
| + | Now start the recovered environment: | ||
| + | |||
| + | <code bash> | ||
| + | docker compose up -d --build | ||
| + | </code> | ||
| + | |||
| + | Check whether the application is running: | ||
| + | |||
| + | <code bash> | ||
| + | curl http://localhost:8080 | ||
| + | </code> | ||
| + | |||
| + | If everything worked, you should receive a response from the grades application. | ||
| + | |||
| + | You can also open: | ||
| + | |||
| + | <code> | ||
| + | http://localhost:8080 | ||
| + | </code> | ||
| + | |||
| + | in your browser. | ||
| + | |||
| + | The application should now display a login page. | ||
| + | |||
| + | ===== 04. The corrupted screenshot ===== | ||
| + | |||
| + | The application works, but you do not know the administrator password. | ||
| + | |||
| + | Fortunately, the administrator remembers something: | ||
| + | |||
| + | I took a screenshot of the admin interface that contained the login information. | ||
| + | |||
| + | The recovered application files contain: | ||
| + | |||
| + | <code> | ||
| + | admin-screenshot.png | ||
| + | </code> | ||
| + | |||
| + | Unfortunately, the screenshot appears to have been corrupted while it was being transferred. | ||
| + | |||
| + | Try inspecting the file: | ||
| + | |||
| + | <code bash> | ||
| + | file admin-screenshot.png | ||
| + | </code> | ||
| + | |||
| + | Then inspect the first bytes: | ||
| + | |||
| + | <code bash> | ||
| + | xxd admin-screenshot.png | head | ||
| + | </code> | ||
| + | |||
| + | Something is wrong with the file header. | ||
| + | |||
| + | A valid PNG file starts with the following bytes: | ||
| + | |||
| + | <code> | ||
| + | 89 50 4E 47 0D 0A 1A 0A | ||
| + | </code> | ||
| + | |||
| + | Use a hex editor to repair the corrupted bytes: | ||
| + | |||
| + | <code bash> | ||
| + | hexedit admin-screenshot.png | ||
| + | </code> | ||
| + | |||
| + | After repairing the file: | ||
| + | |||
| + | * verify it again using ‘‘file’’; | ||
| + | * open the screenshot; | ||
| + | * recover the administrator username and password. | ||
| + | |||
| + | Use the credentials to log in to the grades application. | ||
| + | |||
| + | ===== 05. There is something strange about this screenshot ===== | ||
| + | |||
| + | Before continuing, look again at: | ||
| + | |||
| + | <code> | ||
| + | admin-screenshot.png | ||
| + | </code> | ||
| + | |||
| + | The screenshot is not particularly large or detailed. | ||
| + | |||
| + | However: | ||
| + | |||
| + | <code bash> | ||
| + | ls -lh admin-screenshot.png | ||
| + | </code> | ||
| + | |||
| + | shows that the file is considerably larger than expected. | ||
| + | |||
| + | Maybe the screenshot contains more than an image. | ||
| + | |||
| + | For this exercise you will use a new tool: | ||
| + | |||
| + | <code bash> | ||
| + | binwalk | ||
| + | </code> | ||
| + | |||
| + | Start by running: | ||
| + | |||
| + | <code bash> | ||
| + | binwalk admin-screenshot.png | ||
| + | </code> | ||
| + | |||
| + | Study the output. | ||
| + | |||
| + | If Binwalk detects additional content, try extracting it: | ||
| + | |||
| + | <code bash> | ||
| + | binwalk -e admin-screenshot.png | ||
| + | </code> | ||
| + | |||
| + | Inspect the extracted files. | ||
| + | |||
| + | Remember that filenames and extensions are not always trustworthy. | ||
| + | |||
| + | Use: | ||
| + | |||
| + | <code bash> | ||
| + | file <filename> | ||
| + | </code> | ||
| + | |||
| + | when you are unsure what a file actually contains. | ||
| + | |||
| + | Your goal is to recover: | ||
| + | |||
| + | <code> | ||
| + | admin-backup.hex | ||
| + | </code> | ||
| + | |||
| + | ===== 06. The great file squeeze ===== | ||
| + | |||
| + | The file recovered from the screenshot is: | ||
| + | |||
| + | <code> | ||
| + | admin-backup.hex | ||
| + | </code> | ||
| + | |||
| + | The administrator apparently had a complicated backup procedure. | ||
| + | |||
| + | The file is a hexdump of another file, which has then been compressed and archived several times using different formats. | ||
| + | |||
| + | Reverse the process. | ||
| + | |||
| + | First convert the hexdump back into binary data: | ||
| + | |||
| + | <code bash> | ||
| + | xxd -r admin-backup.hex > recovered | ||
| + | </code> | ||
| + | |||
| + | Then determine what kind of file you have: | ||
| + | |||
| + | <code bash> | ||
| + | file recovered | ||
| + | </code> | ||
| + | |||
| + | Depending on the output, you may need tools such as: | ||
| + | |||
| + | <code bash> | ||
| + | gzip | ||
| + | bzip2 | ||
| + | tar | ||
| + | mv | ||
| + | file | ||
| + | </code> | ||
| + | |||
| + | After every step, ask the system what the resulting file actually is: | ||
| + | |||
| + | <code bash> | ||
| + | file <filename> | ||
| + | </code> | ||
| + | |||
| + | Continue until there are no more compression or archive layers. | ||
| + | |||
| + | At the end you should recover: | ||
| + | |||
| + | <code> | ||
| + | web-paths.txt | ||
| + | </code> | ||
| + | |||
| + | Do not delete this file. | ||
| + | |||
| + | You will need it for the final challenge. | ||
| + | |||
| + | ===== 07. Where did the admin page go? ===== | ||
| + | |||
| + | You can now access the grades application and authenticate successfully. | ||
| + | |||
| + | However, the administrator remembers that there used to be an older administrative interface. | ||
| + | |||
| + | It is no longer linked anywhere in the application. | ||
| + | |||
| + | Nobody remembers its URL. | ||
| + | |||
| + | It may have been something like: | ||
| + | |||
| + | <code> | ||
| + | /admin | ||
| + | /old-admin | ||
| + | /maintenance | ||
| + | /internal | ||
| + | </code> | ||
| + | |||
| + | Fortunately, ‘‘web-paths.txt’’ contains a list of possible paths used during development. | ||
| + | |||
| + | Write a Python program that searches for the forgotten endpoint. | ||
| + | |||
| + | Your program should: | ||
| + | |||
| + | * read candidate paths from ‘‘web-paths.txt’’; | ||
| + | * request each path from the web application; | ||
| + | * inspect the HTTP status code; | ||
| + | * display interesting results. | ||
| + | |||
| + | You may use: | ||
| + | |||
| + | <code python> | ||
| + | import requests | ||
| + | </code> | ||
| + | |||
| + | For example: | ||
| + | |||
| + | <code python> | ||
| + | response = requests.get(url) | ||
| + | print(response.status_code) | ||
| + | </code> | ||
| + | |||
| + | A normal missing page returns: | ||
| + | |||
| + | <code> | ||
| + | 404 Not Found | ||
| + | </code> | ||
| + | |||
| + | You are looking for something different. | ||
| + | |||
| + | ==== One more problem ==== | ||
| + | |||
| + | The server contains a protection mechanism against aggressive automated clients. | ||
| + | |||
| + | If more than approximately three requests per second are sent from the same client, the network protection temporarily blocks that client. | ||
| + | |||
| + | The block lasts approximately 10 seconds. | ||
| + | |||
| + | A very aggressive script may therefore appear to suddenly stop working. | ||
| + | |||
| + | Your program should behave reasonably and deal with this limitation. | ||
| + | |||
| + | Useful Python functionality includes: | ||
| + | |||
| + | <code python> | ||
| + | import time | ||
| + | |||
| + | time.sleep(…) | ||
| + | You may also want to handle request errors rather than immediately terminating the program. | ||
| + | |||
| + | When you discover the forgotten administrative endpoint: | ||
| + | |||
| + | * open it; | ||
| + | * authenticate using the credentials recovered earlier; | ||
| + | * retrieve the final flag. | ||
| + | |||
| + | <code> | ||
| + | ISC{...} | ||
| + | </code> | ||
| + | |||
| + | ===== End-of-Lab Quiz ===== | ||
| + | |||
| + | Answer the following questions based on what you did during the lab. | ||
| + | |||
| + | ==== Q1 ==== | ||
| + | |||
| + | The administrator stored the password list using Base64. | ||
| + | |||
| + | Which property of the CIA triad was the administrator presumably trying to protect? | ||
| + | |||
| + | * A. Integrity | ||
| + | * B. Availability | ||
| + | * C. Authentication | ||
| + | * D. Confidentiality | ||
| + | |||
| + | ==== Q2 ==== | ||
| + | |||
| + | The ZIP archive was protected by a password, but the password could be found using a short wordlist. | ||
| + | |||
| + | What was the weakest link? | ||
| + | |||
| + | * A. The ZIP filename | ||
| + | * B. The weak password | ||
| + | * C. The size of the ZIP archive | ||
| + | * D. The operating system | ||
| + | |||
| + | ==== Q3 ==== | ||
| + | |||
| + | The application could not start because the configuration contained an incorrect port number. | ||
| + | |||
| + | Which CIA property was most directly affected when legitimate users could not use the application? | ||
| + | |||
| + | * A. Confidentiality | ||
| + | * B. Authentication | ||
| + | * C. Integrity | ||
| + | * D. Availability | ||
| + | |||
| + | ==== Q4 ==== | ||
| + | |||
| + | The administrator password was visible inside a screenshot. | ||
| + | |||
| + | Which CIA property was most directly affected? | ||
| + | |||
| + | * A. Confidentiality | ||
| + | * B. Integrity | ||
| + | * C. Availability | ||
| + | * D. Non-repudiation | ||
| + | |||
| + | ==== Q5 ==== | ||
| + | |||
| + | Sensitive information was hidden inside an image and later discovered using Binwalk. | ||
| + | |||
| + | Which statement is most accurate? | ||
| + | |||
| + | * A. Hiding information guarantees confidentiality. | ||
| + | * B. File extensions prevent unauthorized access. | ||
| + | * C. Hiding information is not a replacement for proper confidentiality controls. | ||
| + | * D. Binwalk provides encryption. | ||
| + | |||
| + | ==== Q6 ==== | ||
| + | |||
| + | The recovered backup contained several layers of hexadecimal encoding, compression and archives. | ||
| + | |||
| + | Does this represent defence in depth? | ||
| + | |||
| + | * A. Yes. Every additional file layer is automatically a security control. | ||
| + | * B. Yes. Compression guarantees confidentiality. | ||
| + | * C. No. Defence in depth requires meaningful and preferably independent security controls. | ||
| + | * D. No. Defence in depth can only be used for networks. | ||
| + | |||
| + | ==== Q7 ==== | ||
| + | |||
| + | The old administrator page was not linked from the application, but it could still be discovered by fuzzing possible paths. | ||
| + | |||
| + | What should actually protect an administrative endpoint? | ||
| + | |||
| + | * A. An unusual URL | ||
| + | * B. Proper authentication and authorization | ||
| + | * C. A longer HTML page | ||
| + | * D. A different filename extension | ||
| + | |||
| + | ===== Feedback ===== | ||
| + | |||
| + | {{page>:isc:lab-feedback&nofooter&noeditbutton}} | ||