Simple Image Steganography

StegIm is a simple program for image steganography. For example, I encoded the phrase Hello world!!! into tree.png to create encodedTree.png. When looking at the below images it is impossible to tell the difference between them despite additional data being hidden in the second one.



Source is available on Github here.

Building Signal Desktop In Docker (And Skipping The Line for the Beta!)

Be warned, Signal Desktop is in a closed beta. This program pulls from master and builds Signal Desktop so is in no way guaranteed to work or to be secure. Use at your own risk.

Why? Signal Desktop is in beta and there are over 10,000 people ahead of me in line to join the beta. Open Whisper Systems wants me to invite people in order to jump ahead in line, which I'd rather not do so this is my solution.

First, make sure you have Docker installed. Then git clone To build Signal Desktop: docker build -t signal ..

Currently this Dockerfile is setup to build Signal Desktop then set it up to work with NW but the NW version is stateless (so you have to login every time you use it) so it is recommended to import it as a Chrome extension. To do so, run the container: docker run -ti --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --cidfile=temp.cid signal. Then cat temp.cid to get the ID of the container. Then we need to copy the extension so docker cp [Container ID]:/ ./. Then unzip into a folder. Open chrome://extensions in Chrome and click on "Load unpacked extension..." to load the extension.

Make sure to re-build the container periodically to keep Signal Desktop up to date.

I uploaded a copy of Signal Desktop to my KBFS folder here.

To view the Dockerfile, go here.

Credit to Tim Taubert for his original post on building Signal Desktop.

Website Hosting with KBFS

KBFS is great not only for storing and signing files, but also for hosting a signed mirror of a website. By default is configured to look for a index.html or a So to mirror your static website in KBFS, just copy it all over into a folder in your public directory. For example, my blog and my website are both mirrored in KBFS.

To set this up with Nikola (which I use to host my blog), you just need to modify to set up the nikola deploy command. To do so:

     'default': [
         "nikola github_deploy",
         "nohup cp -a blog /keybase/public/dworken/ &",

So now when I run nikola deploy it will automatically deploy to both Github Pages ( and KBFS (

Slope Field Generator

In my BC Calculus class we were talking about slope fields and Euler's method, so I wanted to program my own slope field generator.



KBFS On Linux

By default, the KBFS will only run on linux. This is a short guide on how to setup and install KBFS on Linux (tested on Ubuntu 15.10 with a BTRFS root). Note that this is unsupported (KBFS is still in beta!) and takes a little bit of work to get it to work.

Start by making sure you have the most recent version of Keybase. Assuming you installed from the .deb, run sudo apt-get upate then sudo apt-get install keybase.

So now we need to set up the filesystem for KBFS. Start by killing keybase so it doesn't mess with anything as we go: sudo killall keybase. So now you need to create the /keybase folder so run sudo mkdir /keybase. Then we need to change the owner of /keybase to your user (from root) so that keybase can modify this. So run sudo chown username:username /keybase. Once that is done you can test it by cding into the directory.

So now just start the keybase daemon by running run_keybase. A box will pop up asking you to unlock your device key so KBFS can run. From here you can cd into /keybase/ to play around.

Note that ls and cd have some weird behavior in this folder. Since it is a FUSE it doesn't follow all the normal specifications. For example, if you cd /keybase/public/ and ls you will not see a dworken folder, but if you cd dworken you will enter my public folder. So when playing around don't expect KBFS to follow your normal expectations on how cd and ls work.

On a sidenote,'s prelease builds are all available here. In my experience these weren't necessary to get KBFS working, but it is still valuable information.

(Ab)using Google’s Unlimited Photo Storage for Fun and Profit

'Unlimited' Storage

Google has recently made unlimited free storage available on google photos. At first glance this seems truly amazing (and ripe for abuse). The one caveat to this claim is that all photos uploaded to Google Photos are compressed with lossy compression. This means that any photos uploaded to Google Photos are automatically compressed thereby loosing some detail.

At first glance, it would appear that this would prevent people from abusing their service since it would make it impossible to upload arbitrary files to their servers since lossy compression would destroy any files uploaded. This also means that many types of steganography would fail if one were to try to store arbitrary data on Google Photos.

The Workaround

By uploading images of text to Google Photos, we are able to upload arbitrary data. This is because whatever type of lossy image compression Google is using will leave all text in photos intact (as would be expected by the users of Google Photos).

So this means that in order to store arbitray data on Google Photos, all you have to do is:

  1. Base64 encode a file.
  2. Create a series of images containing the above text (Google Photos only allows images under 16 megapixels)
  3. Upload the images

And conversely, when retrieving the data from Google Photos, all that has to be done is:

  1. Run image recognition on each photo to get the text.
  2. Base64 decode the text
  3. Concatenate the base64 decoded text from each image into one big file

The Code

I have written a custom python program to implement the above. The code for it is here. To use it import is as a library and call getImages('fileToBackup') and it will generate the photos for you to upload to Google Photos. To recover the file, download the images from Google Photos into your current dir and call getMessage('fileToBackup').

So What?

There are two main uses of this. The first use would be to use this to scheme to upload images to Google Photos thereby preventing Google from running their lossy compression algorithm on your photos.

The other use of this would be as a true back up service. Since one can upload arbitray files to Google Photos, one can use this as a long term backup solution. One could even write a FUSE filesystem so as to allow for Google Photos to be mounted onto a computer as an external hard drive.

Bug Bounties List!

The List

Over the past 2 months, I've spent some time working on bug bounties. In the past two months, I have found vulnerabilities in the following websites:

  • AT&T
  • Adobe
  • Dyn
  • Go Daddy
  • Western Union
  • Symantec
  • IBM
  • Vistaprint
  • Hobby King
  • Tumblr
  • Haiku Learning
  • Mozilla
  • Maret
  • eBay
  • iFixIt
  • MailChimp
  • Amazon
  • Steam
  • Netflix
  • Appcelerator

So far most of these companies have responded and they have either patched or they are actively working towards patching the vulnerabilities. Once these companies approve public disclosure, I will be adding write ups for each vulnerability to the bottom of this blog post.

Using XSScrapy to Scan for XSS Vulnerabilities

Using XSScrapy to Scan for XSS Vulnerabilities

XSScrapy is an amazing tool for the aspiring cyber security researcher. Entering the cyber security field used to be challenging and full of hours of wasted research with nothing to show for it. With XSScrapy, that is no longer true.

So what is an XSS Vulnerability

A XSS vulnerability is what happens when a website displays user input without escaping this. If this makes sense to you, continue to the next section.

A common example of when this would happen is if the website returned the following HTML:

<a href="[Link to the current page]">

So on, this would display:

<a href="">

By loading"><script>alert(0)</script><", the HTML becomes:

<a href=""><script>alert(0)</script><"">

Which when indented properly looks like:

<a href="">

All of which is valid HTML and will run properly. In this case, we have injected javascript code to display a popup box. While a popup box is not dangerous, the javascript can be used to do a number of other malicious things. For example, the injected javascript could automatically exfiltrate cookies back to an attacker owned server (thus giving the attacker access to the victim's account).

So what is XSScrapy?

XSScrapy is an XSS scanner written by Dan McInerney in Python. XSScrapy works by using scrapy to create a web spider to download the HTML of all pages on a given domain name. Scrapy finds URLs by automatically following all of the links on the website until it has scanned every single URL. Once the HTML for a page is downloaded, XSScrapy automatically searches the page for XSS vulnerabilities.

This is done by looking for a number of common injection points and injecting the string 9zqjxel'"(){}<x>:9zqjxel;9. The important part of this string is '"(){}<x>:;. This string contains pretty much every possibly "dangerous" character. So if the HTML is rendered without those characters being escaped, it is likely that there is an XSS vulnerability.

Ok, let's start scanning!

First, follow the installation instructions here. Once you have done that, let's find a website to scan.

Never run XSScrapy against a domain that you do not own or have permission to penetration test. So if you are looking for a website to practice your new found skills on, try any website that offers a bug bounty. Look on websites like Bug Crowd, Hacker One, or CrowdCurity to find websites that allow for automated scanning.

Once you found one, run: -u

Once the scan is finished, let's look through the xsscrapy-vulns.txt file. So run cat xsscrapy-vulns.txt. (Assuming the program found some potential vulnerabilities) This should give you a nice list of vulnerabilities in the form of:

URL: [URL of the Vulnerability]
response URL: [URL of the Vulnerability]
Unfiltered: [The code causing the problem]
Payload: [What was injected to trigger the problem]
Type: [Type of Vulnerability]
Injection point: [Where the payload was injected]
Possible payloads: [A suggested payload to exploit: Note this is often incorrect]
Line: [The problematic line of HTML code]

So now lets go through an example vulnerability report line by line. 

response URL:'"(){}<x>:9zqjxxe;9
Unfiltered: '"(){}<x>
Payload: 9zqjxxe'"(){}<x>:9zqjxxe;9
Type: form
Injection point: q
Possible payloads: x"/onmouseover=prompt(9)/", x"x><svG/onLoad=prompt(9)>, x" onmouseover=prompt(9) "
Line:  <input type="hidden" name="q" value="9zqjxgm'"(){}<x>:9zqjxgm;9

[<span class="octicon octicon-link"></span>](#developing-the-exploit-if-type--form)Developing the Exploit (if Type == form)

Take the URL from the first line and load it in your browser `'"(){}<x>:9zqjxxe;9`

Now modify the URL to ``

Then look at the the last line of XSScrapy's vulnerability report: 

<pre>`Line:  <input type="hidden" name="q" value="9zqjxgm'"(){}<x>:9zqjxgm;9

So based off of the above except from the HTML, we can tell that we want to first add a " to escape from the value variable followed by a > to escape out into the HTML. Together, these two characters will get all following text to be interpreted as HTML. So now that we have that done, we simply tack a standard <script>alert(0)</script> onto the end of "> making our final input "><script>alert(0)</script>. So now we have our payload.

Take that payload and add it on to the URL we got earlier ( to make"><script>alert(0)</script>. Then load that URL, and you should get a pop up box displaying 0!

Now that you have gotten this far, the final step is to report the vulnerability to the website. Create an account on what ever bug bounty website they use and submit it. If you've gotten this far, then Congratulations! You've reported your first vulnerability.



For a while now I've been wanting to make my own interface to WMATA's API. WMATA (Washington Metropolitan Area Transit Authority) has a pretty good API that allows for you to get anything from current train locations, a path between two stations on the same line, elevator/escalator/rail incidents, even an API endpoint for stations near a location.

The one thing that is lacking is an API to go from any one station to another. Their API does have an endpoint to get a list of stations between any two given stations with the caveat that this only works if the supplied stations are on the same line.

So I wrote my own wrapper around their API in python that implements this and much much more.

Scanning for Malicious Proxies

In the past few years, there has been a lot of press about HTTP proxies that transparently modify traffic to inject javascript for malicious purposes. There have been multiple presentations at DEFCON and blackhat about this topic and a variety of ways of exploiting it including: DDOS, credential theft, and even a distributed method of storage. 

Due to this, I decided to write a script to automatically scan proxies for malicious behavior such as: injecting javascript, modifying forms, and editing HTML. 

The first step was to get a list of proxies that are currently up and freely accessible. For this, I used a modified version of Dan McInerney's Elite Proxy Finder. Originally, this script allowed for automated speed testing and discovery of elite proxies. I modified this script so as to: 

  1. Output all types of proxies, not just elite proxies (since anonymity is not an issue).
  2. Output proxies that support only http. This was done because proxies are not able to modify resources transmitted over SSL, so support for a protocol that I will not be testing is not needed.
  3. Export a list of proxies and their ports

From there, I had a list of approximately 1000 active free proxies. While this is a relatively small number, I decided to move on with the experiment to see if there was any malicious behavior to be observed even in this small sample size. So on to the results!

~In all 1500 proxies, there was no malicious traffic. What I mean by this is that no proxies transparently edited the traffic without making it very clear that one was not reaching the requested website. There was no injection of javascript. There was no modification of forms. Absolutely no interesting modifications.~

~Thus the next step is going to be to use masscan to scan the ipv4 address space to look for free proxies, then once again search for malicious behavior.~

The code used for this post is posted here 

Update: I updated the script slightly so as to increase the number of proxies it discovered. With the addition of the updated script, I have discovered a number of malicious proxies that are currently active. 

Here is a list of all proxies detected with errant behavior and a description of their errant behavior.

The proxy server at

modifies HTML sent over HTTP to add the following code to every webpage

<script type='text/javascript' charset='utf-8' src=''></script>

Sadly, the domain is not currently accessible, so I cannot view the injected javascript. Based off of the URL of the injected javascript, two conclusions can be made. 

  1. It is javascript used to automatically inject ads into websites accessed over HTTP. This seems to be the most obvious solution since the domain is "" and the javascript file is stored in the "adscript" folder and is called "adfocus.js". This would make sense since it is a free proxy, the owners of the proxy are likely trying to monetize the business. 
  2. However, it seems like this might be what we are supposed to think. I say this because the javascript is hosted on the domain, very similar to the legitimate It might be that the administrators of this proxy are attempting to capture the reputation of so as to prove the legitimate nature of the injected code. This makes me wonder whether this code serves a more malicious purpose. The injected javascript could do anything from exploit the computer to be part of a botnet to be part of a distributed filesystem.

The proxy server at

automatically strips all HTML comments from the transmitted data. While this does not have any obvious negative effect, it still modifies the transmitted HTML which is an inherently bad thing for any proxy server to do. 

The proxy server at

modifies HTML sent over HTTP to add the following code to every webpage

<script type="text/javascript" charset="utf-8" mediaproAccountID="0" mediaproSlotID="0" usermac="" src="/7b26d4601fbe440b35e496a0fcfa15f7/000c4347fbe8/w1/i.js" async="async" defer></script><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

The interesting this about this javascript, is that the source of the javascript is on / (aka the server itself). At first glance, this seems impossible, but it turns out what the proxy is doing is hijacking all requests to 7b26d4601fbe440b35e496a0fcfa15f7/000c4347fbe8/w1/i.js (hence the long randomly generated string) and replying with a javascript file that is actually not hosted on the webserver of the page you are trying to access.

The proxy server at

modifies HTML sent over HTTP to add the following code to every webpage

<link rel="stylesheet" type="text/css" href="" /><div id="center_xad" class="cwindow_xad">    <div class="center_title_xad">          <img onclick="closeWindow()" width="15px" height="15px" src="">    </div>  <div id='center_xad_cnt' class="injection_content"></div></div><div id="right_xad" class="window_xad">  <div class="right_title_xad"><img onclick="closeWindow()" width="15px" height="15px" src=""></div><div id='right_xad_cnt' class="injection_content"></div></div><script type="text/javascript" src=""></script></body>

This code does a number of interesting things. First of all, it adds a new CSS style sheet. While the style sheet does not do anything malicious (instead choosing to allow the page to appear normally) it is clearly malicious in its purpose, the stylesheet is not the key to the malicious code.The interesting part is here. As my knowledge of javascript is quite limited, I'm going to stop my analysis here. But based off of a quick read through of the code, it seems to be malicious in nature considering the injection of a flash object attempting to download an exe.

So far, I have only analyzed a few select malicious proxies. A full data dump from running this script is available in the Github repo here if anyone wants to give an automated analysis a shot (6500+ lines).