Modern Password Policy

Myths and Best Practices

Password Complexity

Passwords have long served as the first line of defense in securing digital assets, but their strength is directly proportional to the usage habits of users and the security policies applied on them. Unfortunately, many such policies actively degrade password security by driving users towards compensatory strategies just to operate. With that risk in mind, let's discuss why the core of password strength lies in a balancing act between usability and complexity/randomness.

Two primary elements influence a password's entropy (degree of randomness and unpredictability): length and character set complexity. Brute-force attacks, where adversaries attempt every possible combination until success, rely on narrowing down the search space. Both length and complexity expand this space, but it's crucial to understand their relative impacts. Consider the following table, detailing hypothetical attack durations against passwords of varying types, given a conservative base of crackers achieving 10 trillion guesses per second (open source is pretty close):

August 19, 2023

(read more)

Python3 Type Checking

Scaling Python

Python is a great language for prototype development, but sometimes we want to develop production software with Python or we suffer the most recent cycle of prototypes becoming production. This is where the attributes that made Python a strong prototyping tool often interfere with the requirements of enterprise software (e.g. high reliability, complex deployment, multiple developers). Unittests go a long way towards ensuring robust execution of key mechanisms, but how can we catch typos in new code or nuanced return values?

Type Verification

PEP 3107 defined a grammar for arbitrary annotations on functions and variables across for Python 3.0+ and PEP 484 standardized the framing and interpretation for type annotations. Neither enforced any type-checking behavior, but instead made the type annotations available at run-time (via the __annotations__ attribute). mypy provides validation of type annotations with a reasonable type inference system that propagates types where appropriate (except for lists/dicts).

Example (from here)

import typing
def read(vStream : str) -> typing.Tuple[int, int]:
    rval = 0
    for idx in range(len(vStream)):
        rval = (rval * 128) + ord(vStream[idx])
        if not ord(vStream[idx]) & 128: return (idx+1,rval)
        rval = rval - 128 + 1
    return (0,rval)

September 15, 2019

(read more)

Manually Fix Firefox Add-ons

What happened?

Around midnight yesterday, Firefox add-ons around the world near-silently failed. NoScript disappeared and newly opened tabs loaded untrusted javascript freely. Mozilla released a blog post explaining that a relevant intermediate certificate expired causing installed add-ons to lose their root of trust (additional details on bug 1548973 here).

Just wait for a fix?

Per the blog post, users can allow Firefox to install and run studies to eventually receive the fix. Unfortunately, this requires both "Allow Firefox to send technical and interaction data to Mozilla" and waiting until the study eventually installs (potentially alongside other studies). I find this approach pretty disingenuous from Mozilla as they developed a hotfix, then hid an installation option behind an option with privacy impacts. That's a very disappointing move by Mozilla. We can workaround this.

May 04, 2019

(read more)

Simple Monero Droplet

Monero cryptocurrency

Monero is a cryptocurrency that distinguishes itself using a CryptoNote-derived algorithm to secure the blockchain such that transactions don't divulge the transaction amount, source, or destination. This clever combination means decentralized "public" miners mathematically validate "private" transactions while preserving the privacy of parties to the transaction. Fortunately, the standard Monero package provides monero-wallet-rpc which our existing servers can use to easily leverage Monero off a dedicated droplet.

Monero droplet selection

We're primarily reading the Monero blockchain, as opposed to mining it, which means the droplet can skimp on CPU/RAM for disk space (the current blockchain is ~56GB). I used the lowest-tier ($5/mo) option running 64-bit Ubuntu 18.04.2 with 25GB disk, then added Block Storage Volume for 100GB for the blockchain; this also makes expanding it in the future pretty simple (note that added volumes appear in /mnt with a region identifier such as "/mnt/volume_nyc3_01").

April 04, 2019

(read more)

Xubuntu reinstall into existing partitions

Non-standard install with mdadm, luks, and lvm

I recently had the pleasure of installing Xubuntu 16.04.1 with preexisting software RAIDs (mdadm), disk encryption (LUKS), and device mapping (lvm2). It didn't go great and first attempts were met with (initramfs) prompts on boot.

The first sign of trouble was discovering the Xubuntu 16.04.1 installer didn't read the software RAID, so it was time to "Try Xubuntu" for a Live CD installation environment. The Xubuntu 16.04.1 Live CD lacks the mdadm package and will require a network connection (or sneakernet .deb) to install it. Given a network connection, the following commands should make available the LVM volume groups to Xubuntu:

sudo apt-get install mdadm # install mdadm
sudo mdadm --assemble --scan # initialize the RAID devices (md0 and md1 in this case)
sudo cryptsetup luksOpen /dev/md1 cryptroot # /dev/md1 stores the LUKS volume group of interest
sudo lvm vgchange -a y # make the LVM volume groups from cryptsetup available to the system

September 09, 2016

(read more)

Qubes OS

Virtualize Everything

Qubes is a "security-oriented operating system" built atop the Xen hypervisor. Major functionality, including networking and user applications, is split across separate Virtual Machines ("domains" in xen-speak) which Qubes aims to securely integrate/orchestrate. The technical details are very interesting, and we'll get to some of them, but the first question is whether Qubes is ready for real-world use.



August 31, 2016

(read more)

Fault-Tolerant Word Extraction

Make Believe Words and Partial Keys

The Monoalphabetic Substitution solver used a depth-first search for fast text segmentation. While this approach is very efficient when word choices pass or fail cleanly, the worst case impact of pass/fail only becoming clear many choices later and may waste enormous amounts of computation. Fortunately, English text is highly localized and rapidly diffuses errors (segmentation-wise). For example, 'ANALYTICS' is not in the Linux /usr/share/dict/american-english dictionary causing 'ANALYTICS APPLIES STATISTICAL' to segment into 'ANALYTIC SAP PLIES STATISTICAL'.

A pathological input is one wherein a character late in the plaintext cannot be incoporated into a word (either due to key errors or incomplete dictionary). An example of this is visible when running segment_words on portions of some incorrectly accepted plaintext (alphabet "GZOWSYVETMBFQUIKNXHPJRLDAC") where e('DIVERSE') was decrypted to 'DIBERSE' at 213.

>>> l=213;s=time.time();wf=segment_words(ptxt,length_cap=l);e=time.time();print e-s,wf[1]
>>> l=214;s=time.time();wf=segment_words(ptxt,length_cap=l);e=time.time();print e-s,wf[1]
>>> ptxt[201:213]+' '+ptxt[213:220]+' '+ptxt[220:240]

July 05, 2016

(read more)

Faster Crib Detection

"Exclusive" Regex Wildcards

One might recall the find_cribs function from last week's Monoalphabetic Substitution solver:

def find_cribs_backref(words, data, min_length=8, min_repeats=3):
    crib_words = []
    words = filter(lambda x:len(x)>min_length,words)
    words = filter(lambda x:(len(x)-len(set(x)))>min_repeats,words)
    for word in words:
        pattern,letters = backref_pattern(word)
        for hit in re.findall(pattern,data):
            if len(hit) != len(set(hit)): continue # capture groups must be distinct
    return crib_words


This function scanned through the ciphertext to find letter patterns from interesting words (featuring repeated letters) with 4 steps:

  1. Find all words with 8+ characters and 3+ character repeats ('CODEPENDENT')
  2. Generate a regular expression pattern (r'(.)(.)(.)(.)(.)\4(.)\3\4\6(.)')
  3. Find all pattern matches in the ciphertext ([('ZSHPGPTHPTO','TUHPGPTHPTO'])
  4. Eliminate any non-distinct capture groups (charmap('TUHPGPTHPTO') => {'C':'T','N':'T'})

July 01, 2016

(read more)

Cracking Monoalphabetic Substitution

Monoalphabetic Substitution ciphers use a substitution alphabet to map plaintext characters to ciphertext characters. Although many common forms use a simple function to create the substitution alphabet (i.e., Caesar Cipher offsets the alphabet), the general case may create arbitrarily mixed substitution alphabets (aka deranged alphabets). Given the 15 oktillion alphabet orderings (21!), can cryptanalysis defeat a monoalphabetic substitution cipher with a deranged alphabet?

Monoalphabetic Encryption/Decryption

We can use an example to illustrate the operation of the Monoalphabetic Substitution and generating a test case for analysis. We select a Random Wikipedia article with sufficient length (1000+ characters) and few proper nouns for simpler cryptanalysis. The introduction for Data Analysis is a good match for our criteria (and nicely related).

Step 1. Generate the (secret) substitution alphabet:

import string
import random

June 27, 2016

(read more)

Bleichenbacher Chosen Ciphertext Attack

Exploiting an RSA PKCS #1 v1.5 Padding Oracle

The Bleichenbacher attack established the first practical Adaptive Chosen Ciphertext Attack (CCA2) and defeated SSL v3.0 by exploiting PKCS #1 v1.5 padding "errors" under RSA. More specifically, the attack uses a Padding Oracle to identify messages with valid padding among a large set of attacker-generated messages. Each attacker-generated message with valid padding reveals a bit more about the original message - eventually allows the attacker to recover the plaintext without the secret key.

Public Key Cryptography Standards #1 v1.5

PKCS #1 v1.5 defines the padding applied to messages for minimizing crib material (known plaintext). Under PKCS #1 v1.5, a pseudorandom non-zero padding string (PS) is generated of at least 8-bytes and prefixed to the plaintext (P) as follows: 0x00, 0x02, PS, 0x00, P. The Padding Oracle will identify if a given ciphertext decrypts to that structure correctly (a so called conforming message), revealing that the decrypted ciphertext starts with 0x00, 0x02.

June 22, 2016

(read more)

Ubuntu Network Interfaces

Solving New Names (or not)

Ubuntu 16.04 (Xenial Xerus) replaces the now familiar network interface names (e.g. eth0) with slightly less familiar Predictable Nework Interfaces Names (e.g. enp0s3). Although they appear less predictable (what slot is the NIC in a VM?), they do appear consistent across system restarts and MAC address changes (negating an old headache for cloning VMs).

May 10, 2016

(read more)

Ansible iptables Workaround


Ansible hangs after an iptables-restore even if the stateful connection would normally be allowed


Connection tracking isn't active by default, so the outbound connection is not considered established. This means the outbound SSH communications after an iptables-restore will be dropped. This is not normally an issue since interactive users will attempt to interact with the system (immediately triggering an inbound SSH packet and establishing the connection in netfilter's perspective). Ansible does not attempt this interaction and therefore hangs forever (listening for dropped packets).


iptables-restore an outbound-open ruleset first with connection tracking, then iptables-restore the outbound-restrictive ruleset.

April 27, 2016

(read more)

Pythonic Ansible

"I should have stuck with shell scripts"

Ansible is an automation platform for "app deployment, configuration management and orchestration - all from one system". Compared to competitors, it's also well-established and (supposedly) comes with the ability to be imported/executed from Python apps. StackOverflow provides a simple example:

import json
import ansible.runner
import ansible.inventory

inventory = ansible.inventory.Inventory('path/to/your/inventory')
pm = ansible.runner.Runner(module_name='debug',module_args='var=hostvars',timeout=5,inventory=inventory,subset='all')
out =
print json.dumps(out, sort_keys=True, indent=4, separators=(',', ': '))

Unfortunately, this example only works with Ansible <2.0. Ansible's documentation explains that Ansible 2.0 removed the "ansible.runner.Runner" interface and replaced it with a 45-line monstrosity touching nearly a dozen different Ansible components to simulate the initial example. Mucking through the monstrosity though, it fails on pretty much all counts; it only runs one Play within the Playbook, outputs everything as unicode strings, and barfs those into display with multiple lines per write. Perhaps we can do better?

February 18, 2016

(read more)

Samurai CTF Scrimmage
Train like you Pwn

Computer security CTFs seem to thrive in a fascinatingly near-professionalized space impermeated with high-tempo music and flashy visualizations. International teams fly across the world competing in dozens of contests every year for a chance to enter the de facto Cybersecurity Olympics at DEFCON. On the other hand, game environments (hardware, operating systems, rules) are intentionally kept secret and half the qualifying contests involve a fundamentally different type of competition (Jeopardy vs Attack-Defend). Top teams develop complex internal tool suites for Exploit Throwing, Flag Submission, Defensive Countermeasures, Service Patching, Network Superiority, Situational Awareness, and other familiar terms. Top teams then pray the game environment lottery doesn't render them all defunct.

December 22, 2015

(read more)

Entrepreneurial Costs
Business Creation Costs across the US

The U.S. Chamber of Commerce created a metric in 2014 called the Regulatory Climate Index which aims to provide a single number summarizing the vast complexity of creating and operating a small business as it relates to government bureaucracy. Unfortunately, the detailed information and massaging required to produce the RCI restricts comprehensive data to several select cities.

November 25, 2015

(read more)

Entrepreneurial Health
Business Creation across the US

The U.S. Census provides an overwhelming volume of surprisingly detailed data across the United States economy (among other sectors). I recently had the opportunity to work with some of the economic indicators, but found the data frequently inaccessible due to formatting and sheer volume (seriously, they make a TON of data available). Further discussion with several economically focused colleagues invited the creation of an interactive visualization on the Business Dynamic Statistics: Firm Statistics data set. These statistics present business creation and destruction on a state-by-state from 1977-2013.

Click to explore

November 13, 2015

(read more)

Constraint Satisfiability

Sudoku is a well-known puzzle involving a 9x9 grid filled with the digits 1-9 such that no row, column, or 3x3 subgrid contains any repeats. A Sudoku solver is a targeted constraint satisfiability solver (similar to boolean SAT solvers). In particular, such a solver relies heavily upon constraint propagation to identify solutions for every stage of the board.

A board may be viewed as a grid of "solved" numbers and "potential" numbers for each position. At the start, every position is either "solved" (provided by the initial puzzle) or has the full range of digits (1-9) potentially available. The "solved" numbers are then iterated over to constrain the "potential" value of every position in the same row, column, or square. Any positions with only "potential" solution are then marked "solved" with the remaining number and the process is repeated. For example, the middle-most position is constrained in-row by [1,3,4,8], in-column [1,2,6,7,8,9], and in-square by [2,3,6,8] which leaves a potential set of [5].

October 16, 2015

(read more)

Secure VM File Transfer
Without Guest Tools/Additions

Securely transferring files to a potentially compromised virtual machine is a well-known pain in the security community. Shared folders require guest additions, but historically that introduces virtual machine escape vulnerabilities. Host-only networking avoids that problem, but allows the virtual machine to attack the host more traditionally. Fortunately, there's a simple way to introduce files without either issue.

mkisofs -o filename.iso /path/to/dir

Add filename.iso as a cdrom image to the VM and enjoy secure file transfers without the extra attack surface.

August 18, 2015

(read more)

Marathon Complete

The marathon development sessions leading up to DEFCON are complete and the CTF has closed for another year, although LegitBS has yet to release final scores. This blog has also had an overhaul of backend technologies to be discussed in a future update.

August 17, 2015

(read more)


LegitBS recently announced that RuCTFE 2014 would be a pre-qualifier for the DEFCON 2015 CTF. We've previously competed in their sister competition, RuCTF, which was always a blast - so this should be great. In preparation for their 2014 CTF, let's take a look at one of last year's services.

As with most Attack-Defend CTFs, RuCTFE gives each team a set of services. Teams need to secure their services to maintain high Service-Levels and exploit vulnerabilities in other team's services to collect points. RuCTFE 2013 accomplished this with 3 virtual machines (Ubuntu OpenvPN Router, Ubuntu Access Point, and ArchLinux Hosting Server). Finding last year's Hosting Server was a bit of a pain - so we've mirrored them here.

Cryptoboard was a straight-forward service; users connect to the server and pass it commands to store/retrieve keys. The gotcha is that "get" requires a hash of the original data and "list" only sends a list of ID:EncryptedData. Fortunately, the decrypt function uses Cipher Block Chaining and fails differently with bad padding which makes for a trivial Padding Oracle Attack. Academic papers often leave these attacks difficult to conceptualize, but Ron Bowes wrote two excellent articles summarizing the details and even doing an example by hand. If you're at all unfamiliar with a Padding Oracle Attack, reading through those two links should really help.

December 15, 2014

(read more)

SecuInside - crypto - 200

Challenge Text

Before sleeping, wooyaggo always read weird articles from internet. All you got is some binaries(not perfect) and network traffic from following command.

wooyaggo@genius_anncc:~$ python pillow_reader.pyc 5151 "secret" [AdminKey]

Follow instructions in the "secret" to get a flag.

Challenge code available here.

Opening up the pcap shows a partially encrypted conversation:

Welcome to Pillow Reader. Here are some articles from online.

December 04, 2014

(read more)

PlaidCTF - crypto - 375

Challenge Text

Although it seems like The Plague's messaging service is secure, there are bound to be bugs in any 20th century crypto system. We've recovered a version of the block cipher The Plague implemented. Use their online encryptor tool, at, to break the cipher and figure out Plague's secret plans.

Challenge code available here

This was a really great challenge that required some extensive thinking to solve, but tackled some very interesting issues in cryptography. Normally on a CTF, I immediately dive into talking with the service before reading it's source code (when available). So let's jack in:

nc -vv 8193
Connection to 8193 port [tcp/*] succeeded!
We would first like some proof of work.
Send us a string starting with n7WzSynCCN5X5q7p, of length 21, such that its sha1 sum ends in ffffff
> no
Invalid proof of work!

November 29, 2014

(read more)

PlaidCTF - web - 200

Challenge Text

The Plague seems obsessed with internet memes, though we don't yet know why. Perhaps there is a clue to what he's up to on this server (epilepsy warning). If only you could break in.... Here is some of the source.

Reekee was a nice chance to explore and exploit a Django application. As the challenge suggests, the source code was provided (mirrored here). The webpage essentially just hosts user's content ("memes") for them to later peruse; typically a rich source for Path Traversal, File Inclusions, or (in the case of Django) Deserialization vulnerabilities.

A quick scan of shows multiple instances of accessing "/tmp/memes/"+username (a potential path traversal vulnerability), but the register function explicitly blacklists ["..","/"]. These sorts of blacklists are notoriously easy to circumvent and are normally a great source for closer investigation. The function immediately after register contains an even worse vulnerability though that skips the need to dig into that risky code.

September 07, 2014

(read more)

Raw HTTP Requests
Abusing Python's httplib

Part of a recent project involved sending HTTP connections over non-standard transportation networks. The problem is that all the usual offenders (urllib2, Requests, etc) don't provide an interface to either wrap the connection or extract the final product - but this is Python; we can monkeypatch it! The first step was figuring out how urllib2 requests actually get sent to a socket...

# urllib2 module
class AbstractHTTPHandler(BaseHandler):
    def do_open(self, http_class, req):
        h = http_class(host, timeout=req.timeout) # will parse host:port
            h.request(req.get_method(), req.get_selector(),, headers)
        except socket.error, err: # XXX what error?
            raise URLError(err)

class HTTPHandler(AbstractHTTPHandler):
    def http_open(self, req):
        return self.do_open(httplib.HTTPConnection, req)
    http_request = AbstractHTTPHandler.do_request_

# httplib module
class HTTPConnection:
    def request(self, method, url, body=None, headers={}):
        """Send a complete request to the server."""
        self._send_request(method, url, body, headers)
    def _send_request(self, method, url, body, headers):
        if body is not None and 'content-length' not in header_names:
        for hdr, value in headers.iteritems():
            self.putheader(hdr, value)
    def endheaders(self, message_body=None):
        """Indicate that the last header line has been sent to the server."""
    def _send_output(self, message_body=None):
        """Send the currently buffered request and clear the buffer."""

July 19, 2014

(read more)

SQLi WhatsCat
PlaidCTF - web - 300

Challenge Text

The Plague is using his tremendous talent for web applications to build social websites that will get bought out for billions of dollars. If you can stop his climb to power now by showing how insecure this site really is, (on IPv6 at 2001:470:8:f7d::1) maybe we will be able to stop his future reign of terror. Here's some of his source.

As the challenge says this is a web-based problem which provides source code and an IPv6 red herring. A quick review of the source code reviews two potential SQLi vulnerability in the password reset mechanism...

  elseif (isset($_POST["reset"])) {
    $q = mysql_query(sprintf("select username,email,id from users where username='%s'", mysql_real_escape_string($_POST["name"])));
    $res = mysql_fetch_object($q);
    $pwnew = "cat".bin2hex(openssl_random_pseudo_bytes(8));
    if ($res) {
      echo sprintf("<p>Don't worry %s, we're emailing you a new password at %s</p>", $res->username,$res->email);
      echo sprintf("<p>If you are not %s, we'll tell them something fishy is going on!</p>", $res->username);
      $details = gethostbyaddr($_SERVER['REMOTE_ADDR']).print_r(dns_get_record(gethostbyaddr($_SERVER['REMOTE_ADDR'])),true);
      mail($res->email,"whatscat password reset",$message.$details,"From:\r\n");
      mysql_query(sprintf("update users set password='%s', resetinfo='%s' where username='%s'",$pwnew,$details,$res->username));

July 12, 2014

(read more)

SQLi Quine
CodegateCTF - web - 350

This was one of the very interesting challenges brought back for us from the Codegate Finals - sans challenge text. Using a php vuln, a copy of the source code was acquired - here's the relevant piece

<form method=get action="index.php"><div><h1>Login</h1>
ID <input type=text name=id> PW <input type=text name=pw> <input type=submit value='Submit'> <input type=button onclick=location.href='index.phps' value='Source'>
$q=@mysql_fetch_array(mysql_query("select id,pw from mem where id='$_GET[id]'"));

if($_GET['id'] && $_GET['pw'])
    if(!$q['id']) exit();
        echo("<br>hi! ".htmlspecialchars($q['id'])."<br><br>");
        if(!$q['pw']) exit();
        if($q['pw']==md5($_GET['pw'])) { echo("<p class=msg>Password is ????</p>"); }
        else { echo("<p class=error>Wrong pw</p>"); }

July 05, 2014

(read more)

Touch and Go
BackdoorCTF - web - 300

Challenge Text

H4x0r is making a new website and has decided to give you beta access! Head over here to register. Flag format: md5_string

This was an interesting challenge due to a nice trick for detecting automated tools - see below

$ curl ''
  <title>Register Here</title>
  <h3 class="text-center">Register Now!</h3>
  <form action="./register.php" method="POST">
    <input type="text" name="username" placeholder="Select Username"><br>
    <input type="password" name="password" placeholder="Select Password"><br><br>
    <input type="submit" value="Register">

July 05, 2014

(read more)

BackdoorCTF - web - 250

Challenge Text

Markdown to HTML Convertor

Our special markdown convertor supports yaml-frontmatter and underscore style templating.

This problem is almost identical to another BackdoorCTF web100 challenge and also povides its source code.

        <title>Markdown to HTML Convertor</title>
        <style rel="stylesheet" type="text/cs" href="//"></style>
        <h1>Markdown to HTML Convertor</h1>
        <form action="/convert" method="POST">
            <p>Our special markdown convertor supports yaml-frontmatter and underscore style templating.</p>
            <textarea name="markdown" rows="30" cols="70" placeholder="Enter markdown here">...</textarea>
            <input type="submit" value="Convert!">
        <p>Source code for this is available at</p>

July 04, 2014

(read more)

BackdoorCTF - web - 100

In this problem, the challenge text just provided us a URL to the page,, which linked us to the source code on github.

        <title>Underscore Template Tester</title>
        <style rel="stylesheet" type="text/cs" href="//"></style>
        <h1>Underscore Template Tester</h1>
        <form action="/templatize" method="POST">
            <p>This app takes in JSON data and a template and mashes them together using underscore.js</p>
            <textarea name="json" rows="10" cols="30" placeholder="Enter JSON data">{"package":"underscore_test","version": "2.9.12"}</textarea>
            <textarea name="template" rows="10" cols="30" placeholder="Enter your template here">The name of the package is <%=package%> and its version is <%=version%></textarea>
            <input type="submit" value="Convert!">
        <p>Source code for this is available at</p>

July 04, 2014

(read more)

BackdoorCTF - web - 100

Challenge Text

H4x0r, tired of his hacking attempts is hosting a simple contest to rate the images of every user. Head on here to take part in the contest and impress him.

This challenge involved a pretty straight-forward web service which leaked referrer information. Here's the landing page:

  <title>Upload Image</title>
  <h3>Give the link for your profile picture</h3>
  <form action="./submit.php" method="POST">
    <input name="url" placeholder="Enter link" type="url"><br>
    <input value="Submit" type="submit">

July 04, 2014

(read more)

PlaidCTF - crypto - 200

Challenge Text

In this era, block ciphers hadn't even been invented. The Plague created this system based on problems he knew to be NP hard, but there must be something you can do to decode his messages.

Encrypts a message using super secure, NP-hard graph stuff.

Encryption works like this: take a graph, split your message up into
N numbers, such that the sum of all the numbers is equal to your message.
Assign each vertex to one of these N numbers.

Then ciphertext[v] is the sum of v's N, and all of the N's from v's neighbors

July 03, 2014

(read more)

Defcon16 - crypto

This Defcon 16 (2008) challenge came without flavor text, just a binary in need of some remote code execution. A quick check w/ file and checksec show a 32-bit FreeBSD binary with symbols. That never happens! We'll take advantage of that pretty soon!

$ file kryptod
kryptod: ELF 32-bit LSB  executable, Intel 80386, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 6.3, not stripped

$ --file kryptod
No RELRO	No canary found	NX enabled	No PIE	No RPATH	No RUNPATH	kryptod

$ ldd kryptod
kryptod: => /lib/ (0x2806a000) => /lib/ (0x281f5000)

...and it looks like some crypto!

July 02, 2014

(read more)

PlaidCTF2014 - crypto250

Challenge Text

The Plague is running a betting service to build up funds for his massive empire. Can you figure out a way to beat the house? The service is running at

This was a great challenge that demonstrated just how thoroughly and completely researchers have broken MD5. The challenge is to make bets at a cryptographic gambling house to win a billion dollar. That's pretty straight-forward, so let's dig into the details a little bit.

April 15, 2014

(read more)

Variable Length Quantities
Dynamically Encoding Unsigned Values
Assume an arbitrary sized buffer of arbitrary data, how should the length be encoded? Is it small (<256)? Prepend with an 8-bit length field! Will it always be below 16,000? A 16-bit field should suffice. What about 4 billion? 32-bits then. What if we start combining transmissions though? We better be safe and use 64-bits (18 billion billion), but now we're using 8x more space per number. Someone also noted the normal case would have a lot of 0-bytes in each size field providing easier cryptanalysis, but you did remember to compress THEN encrypt, right? Deciding how many bytes to use to describe a field is always a tradeoff between flexibility (large numbers) and resource constraints (small representations). What if we made the length field arbitrary size too?

Smart folks have looked at this problem and found many ways to represent Variable-Length quantities, including 645,000 patents. elicarter (via provided a sample implementation and a good decription of the problem including the risk of non-unique representations. Taking a similar tack, we've developed simple C/C++ and python encoder/decoders to tackle the problem.

September 22, 2013

(read more)

Remote Interactive Python
Going Interactive during Threaded Development
One of Python's best kept secrets is the ability to regain an interactive console in the middle of non-interactive code. Using code.interact, we've saved thousands of development hours by instantly checking assumptions and playing with data in ways logging just can't match. It's been particularly effective inside error handling routines to quickly identify what went wrong and develop a fix on the spot. Here's what we've been using:

def interactiveShell(local, banner='interactive shell'):
    import code
    local = dict(globals(),**local) if local else globals()

August 15, 2013

(read more)

Going Below Exclusive Locks
WinXP Exclusive File Lock Workaround
The previous article addressed working around Exclusive File Locks in Windows XP by directly accessing a target's in-memory file handle. This quick solution meant minimal development time and immediate results, but also guaranteed periodic crashes due to the potential race condition. Specifically, we couldn't ensure the application didn't read or write while we were reading/writing with its file handle.

As recap from last article, .NET System.IO.File.Open opens files exclusively locks by default. This has made a lot of people very angry and been widely regarded as a bad move. We previously presented three routes to workaround the problem, relisted below,  but today we'll take option 1 and go beneath the Exclusive Lock to access our data.

  1. Ignore the lock via raw disk access
  2. Ignore the lock via custom kernel driver
  3. Borrow the exclusively locked file handle

June 29, 2013

(read more)

Breaking the Exclusive Lock
WinXP Exclusive File Lock Workaround
By default, .NET System.IO.File.Open exclusively opens and NO_SHARE locks files. While not regularly a problem for developers, this can frustrate interested parties down the line, and here we are. There are essentially three ways to get around an exclusive file lock and they all suck.

  1. Ignore the lock via raw disk access
This solution sucks; writing raw disk access applications requires substantial development overhead and brings an entire universe of gotchas with it. The Win32 API provides access to this option via CreateFile on an MS-DOS device name [technically, it returns a Direct Access Storage Device handle usable by DeviceIoControl and standard Win32 APIs like WriteFile]. Note: 2008/Vista+ restrict direct disk access

  1. Ignore the lock via custom kernel driver
This approach sucks less, but writing an entire kernel driver as a workaround  to an exclusive lock sucks, not to mention security implications or signing requirements. That said, Eldos apparently recognized this problem and provide a commercial solution, RawDisk, which doesn't look terrible.

  1. Borrow the exclusively locked file handle
How much this approach sucks depends on the operating environment. A truly generic solution is extremely difficult and will probably flag antivirus someday. A highly specific solution can be quick and pretty easy, but any changes in the program/environment risk breakage.

February 08, 2013

(read more)

HTTPS Proxy and Script Beautifier
Minification helps developers protect their intellectual property and reduce bandwidth, but gets in the way of finding high-quality XSS or other-code-injection holes like indirect evals off XmlHttpRequests. This article adds a new hammer to the toolbox to assist against the problem; an integrated HTTP/HTTPS proxy (w/o ssl strip), inline beautifier, and local caching.

$ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem
$ #add browser CA (Firefox: Preferences -> Advanced -> Encryption -> View Certificates -> Import -> Trust CA to identify websites
$ #set browser proxy (Firefox: Preferences -> Advanced -> Network -> Settings -> Manual Proxy -> HTTP Proxy Port 8080
$ python 8080 mycert.cert

January 15, 2013

(read more)

DLL Proxy MITM Maker
A DLL proxy stands in for, or interfaces to, a normal DLL. In security, these tend to be custom-made DLLs which reimplement key functionality of application or system DLLs. They might do so to enhance games (DirectX overlay), cheat at games (Direct3D proxy), subvert the browser (IE proxy), or just gain execution (Fax Malware). As the interaction between callee and caller, in practice, relies on assembly-level calls; building a DLL proxy tends to be a highly specialized task.

Some folks have generously made publicly available ones though, such as Michael Chourdakis. These make it a lot easier to make a DLL proxy! They don't make it much easier to actually Man-in-the-Middle (MITM) individual calls though. The latter requirement tends to be much more challenging. This DLL proxy generator provides a mirror copy of exports with scaffolding to mitm calls in, and results from, the original DLL.

$ python
usage: <TargetDLL> <ProxyFileBase> [<TargetFunctions>]
$ python inetcfg.dll InetProxy InetSetProxy ConfigureSystemForInternet

January 11, 2013

(read more)

Amazon Price Check
A friend of mine, enthralled with her new tablet, took to scanning each of the books in my little library. The app takes a snapshot of the ISBN and looks up the book online to get all the other details (author, title, category, etc). I figured that, given a huge CSV, it'd be an interesting experiment to figure out how much all my books were worth - were I to get market price for them, today.

$ #acquire .csv of books w/ 4th element being ISBN
$ #fill AWS account credentials into
$ python

December 14, 2012

(read more)

Cloning Linux VMs - Consistent Interfaces
When cloning a Linux virtual machine, reinitializing the MAC address renames the network interfaces. For example, "eth0" stops referencing a valid device and "eth1" now references the first ethernet device. This doesn't work well with clones though; I like reinitializing MAC addresses for concurrency, but I dislike new names and particularly dislike waiting 120+ seconds for "new" interfaces to "start".

October 06, 2012

(read more)

Defense Office of Hearings and Appeals
Improved Search Interface

Legal precedents oft lead down weird paths.

Greene v. McElroy essentially forced due process upon the DoD when adjudicating access / security clearances. The Defense Office of Hearings and Appeals now handles all those adjudications and even publishes them online, but they're difficult to search in any comprehensive manner.

Others have recognized this problem in the past and at least one person, Dino Beslagic, has made a much better interfaces. Unfortunately, one of the questions I wished to ask (how prolific are several clearance-specialized lawyers) wasn't possible at that time. That seemed readily resolvable and provided an excuse to play with Rails, an old itch I've been meaning to scratch. And here's the result: it isn't particularly pretty, but does expose a fairly thorough [if syntactically limited] search interface.

DOHA Search

Top 10

Pro Se11346
Alan V. Edmunds186
Sheldon I. Cohen69
William F. Savarino62
David P. Price59
Thomas Albin45
Elizabeth L. Newman35
Richard Murray32
Joseph Testan29
John F. Mardula29

DOHA now provides their own search engine:

September 14, 2012

(read more)

PingFS: Living in the Rain
aka How to get blackholed by Google
Phuby was introduced to an unsuspecting world by two programmers back in 2009. This has made a lot of people very angry and been widely regarded as a bad move. The developers do a great job explaining why, but as they point out the product is engineered quite well. The GoSmart Clip fills a similar niche; a driving companion that makes txting behind the wheel a snap! So inspired, my friends and I stumbled upon a similarly counter-productive, useless, yet programmatically interesting project (thanks Kurt). Thus was the Ping Filesystem born. PingFS is like holding up the clouds by swatting the rain back up.

PingFS is a set of python scripts which, in Linux, provide virtual disk storage on the network. Each file is broken up into 64-1024 byte blocks, sent over the wire in an ICMP echo request, and promptly erased from memory. Each time the server sends back your bundle of joy, PingFS recognizes its data and sends another gift [the data]. Download at the bottom of the page.

[drop all the files in one directory (via unzip or individual download)]
# mkdir mount_dir/
# python mount_dir
# ls mount_dir
# echo cats > mount_dir/reddit
# cat mount_dir/reddit

April 01, 2012

(read more)