And Hypothetically Speaking About ASN.1…

Thomas Ptacek | January 30th, 2006 | Filed Under: Bitching About Protocols, Development, Matasano

If you had yourself a program “asn1 int” that consumed its arguments and printed to standard output the binary BER representation of an ASN.1 integer, like so:

$ asn1 int 0 | hexify 020100

and you had yourself a program “asn1 seq” that consumed its standard input and printed to standard output that data wrapped in a BER ASN.1 sequence, like so:

$ asn1 int 0 | asn1 seq | hexify 3003020100

then you could generate yourself a random RSA private key block on the command line, like this:

$ ( asn1 int 0 ; asn1 int 1 ; asn1 int 11 ; asn1 int 2 ; asn1 int 3 ; asn1 int 3 ; asn1 int 3 ; asn1 int 3 ; asn1 int 3 ) | asn1 seq | hexify 301b02010002010102010b020102020103020103020103020103020103

Of course, that’s not very realistic. So you’d extend “asn1 int” to consume its own standard input when needed:

$ dd if=/dev/random bs=1 count=50 | asn1 int -r 020a807321825fa8a1c87516

And now it’s starting to get interesting:

#!/bin/sh # randkey.sh r8() { dd if=/dev/random bs=1 count=$1 2>/dev/null } echo "-----BEGIN RSA PRIVATE KEY-----" ( asn1 int 0 ; r8 256 | asn1 int -r ; asn1 int 11 ; r8 256 | asn1 int -r ; r8 128 | asn1 int -r ; r8 128 | asn1 int -r ; r8 128 | asn1 int -r ; r8 128 | asn1 int -r ; r8 128 | asn1 int -r ; ) | asn1 seq | b64 echo "-----END RSA PRIVATE KEY-----"

So we can do:

$ ./randprivkey | openssl rsa -text Private-Key: (2048 bit) modulus: 00:87:49:f1:dd:33:4c:45:aa:fa:62:bd:a6:c5:65: # and so on

and we’d start to be a little impressed by the Unix shell. Of course, we wouldn’t need to stop there; we could add another parameter to the “asn” commands, “-L” to specify, not sense, the BER length. Then our “randkey” might look like:

#!/bin/sh r8() { dd if=/dev/random bs=1 count=$1 2>/dev/null } r8r() { j=`random` r8 `expr $j % $1` } echo "-----BEGIN RSA PRIVATE KEY-----" ( asn1 int 0 ; r8r 1000 | asn1 int -r ; asn1 int -L `random` 11 ; r8 256 | asn1 int -r ; r8r 128 | asn1 int -r ; r8r 1280 | asn1 int -r ; r8r 1280 | asn1 int -r ; r8r 1280 | asn1 int -r ; r8r 128 | asn1 int -r ; ) | asn1 seq -L `random` | b64 echo "-----END RSA PRIVATE KEY-----"

and we’re fuzzing DER private key parsers on the command line.

But why would we stop there? We could add support for OIDs:

$ asn1 oid 1.2.3.4 06032a0304

and for strings:

$ asn1 string helu world 040a68656c7520776f726c64

and then we could write this script:

#!/bin/sh # snmpget.sh snmpget() { asn1 seq -T cC0 } ( asn1 int 0 ; asn1 string private ; ( asn1 int 12131415 ; asn1 int 0 ; asn1 int 0 ; ( ( asn1 oid 1.2.3.4 ; asn1 null ) | asn1 seq ) | asn1 seq ) | snmpget ) | asn1 seq

and run it like this:

$ snmpget.sh | nc -u 1.2.3.4 161

and, if we were watching in tcpdump, we’d see this:

10.0.1.5.53456 > 1.2.3.4.snmp: [udp sum ok] { SNMPv1 C=private { GetRequest(23) R=12131415 .iso.2.3.4 } }

and we’d start to wonder if there wasn’t something to this whole ASN.1 thing after all.

Right before we started hurling random bizarre SNMP GETs all over the place and watching what broke.

We’ll race you. Who can write “asn1 int,string,oid,seq” in AWK first?

4 Comments so far

  • Anonymous

    January 30th, 2006 11:26 pm

    throw in

    | asn1 explicit

    and

    | asn1 implicit

    to wrap up LDAP and Kerberos 5 PDUs and
    aim higher

  • Adam

    January 31st, 2006 9:50 am

    Race me? But Oulu University Secure Programming group already finished! ;)

  • tqbf

    January 31st, 2006 11:30 am

    @anonymous: IIRC, there’s no BER encoding for “explicit” and “implicit”. It just changes the tag numbers. Most “high level” BER types are just ASN.1 “sequence” with special tags. So I’m not sure you can’t do LDAP already (though I haven’t tried).

    @adam: Oulu did NOT write their SNMP fuzzer in Bourne Shell and Awk. In fact, I can’t even pronounce “Oulu”. I don’t even have evidence that there is such a place. “Oulu”? Sounds made up to me.

  • Anonymous

    February 2nd, 2006 8:37 am

    @tqbf

    my bad about the implicit and explicit
    things; i’d neglected to notice you had
    the -T option to rewrite the tags for
    your universal types already

    and i do understand sorta what you’re
    getting at. your ASN.1 shelltools for
    generating BER (DER, actually, i sup-
    pose, but, hmm, now wouldn’t it be fun
    to start throwing arcane but valid BER
    encodings at things. appropos of no-
    thing, one thing i notice about Micro-
    soft LDAP PDUs is that their integers
    are always encoded as 4 octets. wonder
    if that gets shoved into a signed or
    unsigned?) are every bit as lucid as
    the original ASN.1 specification, if
    not more so, just bottom up (or maybe
    bottom left)

    yeah, i’ll shut up now

  • Leave a reply