<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>VSzA techblog</title>
	<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/"/>
	<link rel="self" type="application/atom+xml" href="http://techblog.vsza.hu/atom.xml"/>
	<updated>2013-05-02T17:34:15+02:00</updated>
   <generator uri="http://github.com/stef/utterson">utterson v0.4</generator>
   <id>http://techblog.vsza.hu/</id>
	<entry>
		<title>Using Android emulator with Burp Suite</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/Using_Android_emulator_with_Burp_Suite.html"/>
		<updated>2013-05-02T17:34:15+02:00</updated>
      <id>http://techblog.vsza.hu/posts/Using_Android_emulator_with_Burp_Suite.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>I still find <a href="http://portswigger.net/burp/">Burp Suite</a> the best tool for web-related penetration testing,
and assessing Android applications are no exception. In the past, I used my
phone with iptables, but lately – especially since the emulator <a href="http://developer.android.com/tools/devices/emulator.html#accel-graphics">supports
using the host OpenGL for graphics</a> – I started to prefer the emulator.</p>

<p>First of all, setting an emulator-wide proxy is really easy, as <a href="http://fas.mide.dk/2011/11/make-android-emulator-ready-for-ssl.html">Fas wrote</a>,
all I needed was the <code>-http-proxy</code> command line argument. Because of this, I
had to start the emulator from command line – I've only used the GUI provided
by <code>android</code> before. I looked at the output of <code>ps w</code> for hints, and at first,
I used a command line like the following.</p>

<pre><code class="no-highlight">&#x24; tools/emulator64-arm -avd Android17 -http-proxy http://127.0.0.1:8081
emulator: ERROR: Could not load OpenGLES emulation library: lib64OpenglRender.so: cannot open shared object file: No such file or directory
emulator: WARNING: Could not initialize OpenglES emulation, using software renderer.
</code></pre>

<p>Since using the Android emulator without hardware rendering would've been like
using Subversion after Git, I looked into the matter and found that I just had
to set the <code>LD_LIBRARY_PATH</code> path to the <code>tools/lib</code> subdirectory of the SDK.
Now I could intercept various TCP connections using Burp, but in case of SSL
connections, certificate mismatch caused the usual problem.</p>

<p>Luckily, Burp provides really easy ways of exporting the its root CA
certificate in the last few releases, I chose to export it into a DER file by
clicking on the <code>Certificate</code> button on the <code>Options</code> subtab of the <code>Proxy</code>
tab, and selecting the appropriate radio button as seen below.</p>

<p><img src="http://techblog.vsza.hu/images/burp-root-ca-cert-export.png" alt="Exporting root CA certificate from Burp Proxy" title="" /></p>

<p>Android 4.x stores root CA certificates in <code>system/etc/security/cacerts/</code> in
PEM format, so running the following command gives a chance to review the
certificate before adding and the output can be used directly by Android.</p>

<pre><code class="no-highlight">&#x24; openssl x509 -in burp.cer -inform DER -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1296145266 (0x4d419b72)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=PortSwigger, ST=PortSwigger, L=PortSwigger, O=PortSwigger, OU=PortSwigger CA, CN=PortSwigger CA
        Validity
            Not Before: Jan 27 16:21:06 2011 GMT
            Not After : Jan 22 16:21:06 2031 GMT
        Subject: C=PortSwigger, ST=PortSwigger, L=PortSwigger, O=PortSwigger, OU=PortSwigger CA, CN=PortSwigger CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:a0:c2:98:2b:18:cf:06:42:4a:7b:a8:c9:ce:ab:
                    1d:ec:af:95:14:2a:dd:58:53:35:9d:68:18:86:a5:
                    3a:84:6e:6c:32:58:11:f3:d7:bf:b4:9e:29:d2:dc:
                    22:d2:7f:23:36:16:9d:10:c4:e5:4c:69:55:4d:95:
                    05:9f:9b:f8:33:37:8d:9f:d0:23:0f:61:d4:53:d7:
                    40:fd:da:6d:f0:04:75:2c:ef:75:77:0a:4a:8c:34:
                    f7:06:6b:4e:ea:58:af:a7:89:51:6b:33:a2:89:5c:
                    6b:64:cb:e6:31:a7:7f:cf:0a:04:59:5b:a4:9e:e3:
                    96:53:6a:01:83:81:2b:0b:11
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                FE:2F:6C:CD:EB:72:53:1E:24:33:48:35:A9:1C:DC:C7:D6:42:6F:35
            X509v3 Basic Constraints: critical
                CA:TRUE, pathl&#x65;n:0
    Signature Algorithm: sha1WithRSAEncryption
         1e:f0:92:13:bd:05:e8:03:33:27:72:3d:03:93:1e:d9:d6:cc:
         f0:bd:ae:e2:a3:8f:83:e0:65:5e:c7:03:9d:25:d4:d2:8f:6e:
         bc:3e:7d:5c:28:2d:b3:dd:c0:8b:8e:60:c5:a8:8c:26:dc:19:
         50:db:da:03:fb:39:e0:72:01:26:47:a7:ea:c4:58:f5:c9:71:
         bf:03:cd:af:16:07:6d:a5:36:72:4c:b5:8d:4f:86:4a:bc:60:
         1c:01:62:eb:e5:48:a0:83:c6:1c:ea:b9:36:d6:b1:f1:de:e6:
         19:4a:2a:76:7e:d3:d2:39:70:64:a3:63:ce:89:da:2e:7d:17:
         ff:52
-----BEGIN CERTIFICATE-----
MIICxDCCAi2gAwIBAgIETUGbcjANBgkqhkiG9w0BAQUFADCBijEUMBIGA1UEBhML
UG9ydFN3aWdnZXIxFDASBgNVBAgTC1BvcnRTd2lnZ2VyMRQwEgYDVQQHEwtQb3J0
U3dpZ2dlcjEUMBIGA1UEChMLUG9ydFN3aWdnZXIxFzAVBgNVBAsTDlBvcnRTd2ln
Z2VyIENBMRcwFQYDVQQDEw5Qb3J0U3dpZ2dlciBDQTAeFw0xMTAxMjcxNjIxMDZa
Fw0zMTAxMjIxNjIxMDZaMIGKMRQwEgYDVQQGEwtQb3J0U3dpZ2dlcjEUMBIGA1UE
CBMLUG9ydFN3aWdnZXIxFDASBgNVBAcTC1BvcnRTd2lnZ2VyMRQwEgYDVQQKEwtQ
b3J0U3dpZ2dlcjEXMBUGA1UECxMOUG9ydFN3aWdnZXIgQ0ExFzAVBgNVBAMTDlBv
cnRTd2lnZ2VyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgwpgrGM8G
Qkp7qMnOqx3sr5UUKt1YUzWdaBiGpTqEbmwyWBHz17+0ninS3CLSfyM2Fp0QxOVM
aVVNlQWfm/gzN42f0CMPYdRT10D92m3wBHUs73V3CkqMNPcGa07qWK+niVFrM6KJ
XGtky+Yxp3/PCgRZW6Se45ZTagGDgSsLEQIDAQABozUwMzAdBgNVHQ4EFgQU/i9s
zetyUx4kM0g1qRzcx9ZCbzUwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0B
AQUFAAOBgQAe8JITvQXoAzMncj0Dkx7Z1szwva7io4+D4GVexwOdJdTSj268Pn1c
KC2z3cCLjmDFqIwm3BlQ29oD+zngcgEmR6fqxFj1yXG/A82vFgdtpTZyTLWNT4ZK
vGAcAWLr5Uigg8Yc6rk21rHx3uYZSip2ftPSOXBko2POidoufRf/Ug==
-----END CERTIFICATE-----
</code></pre>

<p>As <a href="http://stackoverflow.com/a/12134348">rustix wrote</a>, the file name needs to be the the hash of the subject of
the certificate, in case of the above certificate, it can be calculated as the
following.</p>

<pre><code class="no-highlight">&#x24; openssl x509 -noout -subject_hash_old -inform DER -in burp.cer
9a5ba575
</code></pre>

<p>Now all we need is to upload the file using <a href="http://developer.android.com/tools/help/adb.html">adb</a>.</p>

<pre><code class="no-highlight">&#x24; adb push burp.cer /system/etc/security/cacerts/9a5ba575.0
failed to copy 'burp.cer' to '/system/etc/security/cacerts/9a5ba575.0':
    Read-only file system
</code></pre>

<p>The error message was fairly straightforward, <code>/system</code> is mounted read-only,
all we need to do is remounting it in read-write (rw) mode.</p>

<pre><code class="no-highlight">&#x24; adb shell
root@android:/ # mount -o rw,remount /system
root@android:/ # ^D
&#x24; adb push burp.cer /system/etc/security/cacerts/9a5ba575.0
failed to copy 'burp.cer' to '/system/etc/security/cacerts/9a5ba575.0':
    Out of memory
</code></pre>

<p>That's a tougher one, but easily solveable by resizing the system partition
using the emulator command line argument <code>-partition-size</code>. With this change as
well as the library path for OpenGL, the full command line looks like the
following (of course, <code>64</code> should be removed if you're using a 32-bit OS).</p>

<pre><code class="no-highlight">&#x24; LD_LIBRARY_PATH=tools/lib/ tools/emulator64-arm -avd Android17 \
    -http-proxy http://127.0.0.1:8081 -partition-size 512
</code></pre>

<p>Since restarting the emulator wiped my changes from <code>/system</code>, I had to upload
the certificate again, and finally, it appeared in the list of system
certificates.</p>

<p><img src="http://techblog.vsza.hu/images/burp-android-sys-ca.png" alt="Burp Proxy root CA in Android System CA store" title="" /></p>

<p>This being done, all applications using SSL/TLS connections (except for those
that do <a href="https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning">certificate pinning</a>) will accept the MITM of Burp, as it can
be seen below with Google as an example. The top half is the certificate
viewer of the Android web browser, stating that Portswigger issuing a
certificate for <code>www.google.com</code> is perfectly valid, while the bottom half
is the Burp Proxy window, showing the contents of the HTTPS request.</p>

<p><img src="http://techblog.vsza.hu/images/android-browser-burp-ca.png" alt="Android web browser using the Burp CA" title="" /></p>
]]></content>
	</entry>
	<entry>
		<title>MWR BSides Challenge 2013 writeup</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/MWR_BSides_Challenge_2013_writeup.html"/>
		<updated>2013-04-27T12:32:48+02:00</updated>
      <id>http://techblog.vsza.hu/posts/MWR_BSides_Challenge_2013_writeup.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>On 11<sup>th</sup> March 2013, MWR Labs <a href="http://labs.mwrinfosecurity.com/blog/2013/03/11/bsides-chall&#x65;nge/">announced a chall&#x65;nge</a> that involved
an Android application called Evil Planner. I got the news on 12<sup>th</sup>
March around 17:00 and by 20:30 I found two vulnerabilities in the application
and had a working malware that could extract the data protected by the app.
The app I created as a proof-of-concept is available in its
<a href="https://github.com/dnet/evil-planner-solution">GitHub repository</a>, and below are the steps I've taken to assess the
security of the application.</p>

<p>The application itself was quite simple, and seemed secure at first sight. It
required the user to use a PIN code to protect information entered. Unlike
many application it even used this PIN code to encrypt the database, so even
if the device was stol&#x65;n, the user shouldn't have worried about it.</p>

<p>After downloading the APK, I unzipped it and converted the <code>classes.dex</code> file
containing the Dalvik bytecode to a JAR file using <a href="http://code.google.com/p/dex2jar/">dex2jar</a>. I opened the
resulting JAR with <a href="http://java.decompiler.free.fr/?q=jdgui">JD-GUI</a> and saw that no obfuscation took place, so all
class, method and member names were available. For example, the <code>Login</code> class
contained the following line, revealing where the PIN code was stored:</p>

<pre><code>private final String PIN_FILE = "/creds.txt";
</code></pre>

<p>Further static code analysis revealed that the PIN code was stored in the file
using a simple method of encoding (I wouldn't dare calling it encryption).</p>

<pre><code class="java">public static String encryptPIN(String paramString,
    TelephonyManager paramTelephonyManager)
{
    String str1 = paramTelephonyManager.getDeviceId();
    String str2 = paramString.substring(0, 4);
    byte[] arrayOfByte1 = str1.getBytes();
    byte[] arrayOfByte2 = str2.getBytes();
    return Base64.encodeToString(xor(arrayOfByte1, arrayOfByte2), 2);
}
</code></pre>

<p>Although variable names are not available to JD-GUI, it's still easy to see
what happens: the <code>getDeviceId</code> method <a href="http://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId()">returns the IMEI of the device</a>,
and this gets XOR'd with the PIN string. The result can have weird characters,
so it's Base64 encoded before being written to <code>creds.txt</code>.</p>

<p>As you can see, this method of encoding is easily reversible, but I wouldn't
even need to go that far, since there's a <code>decryptPIN</code> method as well that
performs the reverse of the code above. Thus acquiring the PIN code protecting
the application is only a matter of accessing the <code>creds.txt</code>, which has its
permissions set correctly, so it's only accessible to the Evil Planner.</p>

<p>However, using <a href="http://code.google.com/p/android-apktool/">apktool</a> to get readable XMLs from the binary ones used in
APK files revealed that the application exposes two <a href="http://developer.android.com/guide/topics/providers/content-providers.html">content providers</a>
whose security implications <a href="http://techblog.vsza.hu/posts/Seesmic_Android_information_leak.html">I already mentioned with regard to Seesmic</a>.</p>

<pre><code>&lt;provider android:name=".content.LogFileContentProvider" 
    android:authorities="com.mwri.fileEncryptor.localfile" /&gt;
&lt;provider android:name="com.example.bsidechall&#x65;nge.content.DBContentProvider"
    android:authorities="com.example.bsideschall&#x65;nge.evilPlannerdb" /&gt;
</code></pre>

<p>Latter is more like the one used by Seesmic and would've provided some limited
access to the database, so I turned my attention to the other. Former is more
interesting since it implements the <code>openFile</code> method in a way that it just
opens a file received in a parameter without any checks, as it can be seen in
the decompiled fragment below. (I removed some unrelated lines regarding
logging to make it easier to read, but didn't change it in any other way.)</p>

<pre><code>public ParcelFileDescriptor openFile(Uri paramUri, String paramString)
    throws FileNotFoundException
{
    // removed logging from here
    String str5 = paramUri.getPath();
    return ParcelFileDescriptor.open(new File(str5), 268435456);
}
</code></pre>

<p>Since the content provider is not protected in any way, this makes it possible
to access any file with the privileges of the Evil Planner. In the
proof-of-concept code, I used the following function to wrap its functionality
into a simple method that gets a path as a parameter, and returns an
<code>InputStream</code> that can be used to access the contents of that file.</p>

<pre><code>protected InputStream openFile(String path) throws Exception {
    return getContentResolver().openInputStream(Uri.parse(
                "content://com.mwri.fileEncryptor.localfile" + path));
}
</code></pre>

<p>Having this, reading the contents of <code>creds.txt</code> only took a few lines (and
even most of those just had to do with the crappy IO handling of Java).</p>

<pre><code class="java">InputStream istr = openFile(
            "/data/data/com.example.bsidechall&#x65;nge/files/creds.txt");
InputStreamReader isr = new InputStreamReader(istr);
BufferedReader br = new BufferedReader(isr);
String creds = br.readLine();
</code></pre>

<p>Since I had access to every file that Evil Planner had, the rest was just
copy-pasting code from JD-GUI to decrypt the PIN, get the database file in
the same way, decrypt that using the PIN, and dump it on the screen. All of
the logic can be found in <a href="https://github.com/dnet/evil-planner-solution/blob/master/src/hu/vsza/bsides/malware/Main.java">Main.java</a>, and the result looks like the
following screenshot.</p>

<p><img src="http://vsza.hu/mwr-chall&#x65;nge-pin-db.png" alt="Working proof-of-concept displaying sensitive information" title="" /></p>

<p>I'd like to thank the guys at MWR for creating this chall&#x65;nge, I don't
remember any smartphone app security competitions before. Although I felt
that the communication was far from being perfect (it's not a great feeling
having the solution ready, but having no address to send it to), it was fun,
and they even told me they'll send a T-shirt for taking part in the game.
Congratulation to the winners, and let's hope this wasn't the last
chall&#x65;nge of its kind!</p>
]]></content>
	</entry>
	<entry>
		<title>Four free software I started using in 2012</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/Four_free_software_I_started_using_in_2012.html"/>
		<updated>2013-02-02T00:11:06+01:00</updated>
      <id>http://techblog.vsza.hu/posts/Four_free_software_I_started_using_in_2012.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>At the end of 2012, I realized that two of the software I started using in that
year started with the letter 'm', and later, I remembered two other as well, so
here's this post to document what I used in 2013.</p>

<h4>mcabber (console XMPP a.k.a. Jabber client with built-in OTR support)</h4>

<p>In the last ten years, I always preferred IRC to XMPP/MSN Messenger/Skype since
although all of them has both the option to one-to-one and many-to-many chat,
latter is the common use-case for IRC while former is with all the others.
That's when <a href="https://www.ctrlc.hu/~stef/blog/">Stefan</a> showed me <a href="http://www.cypherpunks.ca/otr/">OTR</a> (Off-the-Record) messaging, which
provided strong autentication and encryption along with deniability afterwards.
We started experimenting with version 1 on IRC using <a href="http://irssi-otr.tuxfamily.org/">irssi-otr</a>, but found
it to be quite unstable, and another big problem was that I prefer to run irssi
on a remote server, which defies the whole purpose of the end-to-end security
OTR aims to provide.</p>

<p>So I decided to give it a try with XMPP, especially since
<a href="http://hsbp.org/">H.A.C.K.</a> has its own server – with registration available to anyone – at
<code>xmpp.hsbp.org</code>. Stefan recommended me <a href="http://mcabber.com/">mcabber</a> as a client, and although
it has its limitations (for example, it cannot connect to multiple servers and
I had to use <a href="http://pidgin.im/">Pidgin</a> for registration), I found it perfect for my
use-cases, as it has built-in support for OTR up to version 2, and has a nice
console UI.</p>

<p><img src="http://techblog.vsza.hu/images/mcabber-shot.png" alt="mcabber in action" title="" /></p>

<h4>minidlna (lightweight DLNA/UPnP media server)</h4>

<p>I didn't know what DLNA was before I got my hands on a device that actually
supported it, then I started using <a href="http://www.serviio.org/">Serviio</a>, but it had its limitations.
It required Java, updated the local repository really slow, had an awful and
complicated GUI – and had I mentioned it ran on Java? After a week, I started
looking for alternatives, I naïvely typed <code>apt-cache search dlna</code> and
that's how I <del>met</del> found <a href="http://sourceforge.net/projects/minidlna/">minidlna</a>, which was quite the opposite
of Serviio.</p>

<p>It consisted of a single native executable, a config file
and some docs, and since it's targeted at embedded systems, it ran quite fast
on my dual i3 notebook. The Debian version runs as an unprivileged user by
default, and I added my user to the <code>minidlna</code> group, so I can just drop/link
files into the <code>/var/lib/minidlna</code> directory, and they just become accessible
for any DLNA consumer. In case of content from Bittorrent, I can even
download it to a remote server, mount it with <a href="http://fuse.sourceforge.net/sshfs.html">sshfs</a> (also one of my
favorite solutions), symlink it into the directory, and the TV magically plays
the file from the remote server via my notebook over the home Wi-Fi, which
works suprisingly well even in case of HD contents. Also, on Debian, the DLNA
icon is a Debian swirl logo, so it even looks great in the TV menu. :)</p>

<p><img src="http://techblog.vsza.hu/images/minidlna-allshare.jpg" alt="minidlna in action" title="" /></p>

<h4>mosh (SSH <del>replacement</del> extension for roaming clients and laggy connections)</h4>

<p>I think SSH is one of those software that demonstrate the power of “the Unix
way” the best. I use it for lots of purposes, but at the same time, I've found it
really hard to use in case of laggy connections. I cannot even decide, which
one I hate better, both cellular data connections (GPRS, EDGE, 3G, etc.) and
suboptimal Wi-Fi networks can make me want to smash the keyboard. After using
<a href="http://mosh.mit.edu/">mosh</a> while uploading huge videos over a consumer-grade asymmetric uplink,
I also found that networks without QoS can also make the interactive SSH
experience turn into a text-based RPG.</p>

<p>I installed mosh on the two boxes I
most regularly log into via SSH, and found it really useful, especially since
<a href="http://dan.drown.org/android/mosh/">Daniel Drown patched mosh support into ConnectBot</a>, an Android terminal
emulator and SSH client, which makes sense, since handheld devices have the
most chance to be connected to networks matching the description above. Although
some say it breaks interactive applications like VIM, I had no problems with
version 1.2.3 I downloaded and compiled almost two months ago, so if you also
find yourself connected to laggy networks, give it a try!</p>

<p><img src="http://vsza.hu/mosh-android.png" alt="mosh in action on Android" title="" /></p>

<h4>mutt (the mail user agent that sucks less)</h4>

<p>I've been a <a href="http://userbase.kde.org/KMail">KMail</a> user since around 2007 and although I saw many of my
friends using <a href="http://www.mutt.org/">mutt</a> with server-side magic, I used it just like my
window manager and my shell – a tool, which I used until it worked without
a hassle. When it <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=588979">misbehaved</a> or <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=590124">crashed</a> (it did so <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=622986">quite a</a>
<a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=687382">few times</a>), I sent bugreports, partly to make myself feel better, partly
to evade “and have you reported it” questions, but I also hoped that they'll
fix these properly. Then one day, during an IMAP mass move operation, KMail
crashed, and did so even after restart. I've had quite an experience in
bruteforcing KMail into a working state from the past, but when I couldn't
change the situation in half an hour, I decided that it's time to change.</p>

<p>I had three mailboxes on two IMAPS servers with two distinct SMTPSA MTAs to
send mails through, and I also used client-side filtering extensively.
I migrated latter functionality to <a href="http://www.procmail.org/">procmail</a> on one of the servers,
and as of February 2013, I use a transitional setup with on-line IMAP
mailboxes and a local header cache. In the near future, I plan to migrate
online IMAP access to a solution based on <a href="http://offlineimap.org/">offlineimap</a> and run a
local MTA that forwards mail to the appropriate SMTP server, preferably
through a tunnel/VPN to avoid password authentication and my endpoint IP
address appearing in the MIME envelope.</p>

<p>I only had one problem so far, it
seems that the online IMAP functionality is not so well-tested in mutt, so
even though I use Debian testing, it crashed in around 30% of the cases
when changing IMAP directories, but I managed to solve it by compiling
Mutt from source, including the <a href="http://www.lunar-linux.org/mutt-sidebar/">folder sidebar patch</a>. Here's how it
looks with the current config, displaying the Python SOAP mailing list.</p>

<p><img src="http://techblog.vsza.hu/images/mutt-shot.png" alt="mosh in action on Android" title="" /></p>
]]></content>
	</entry>
	<entry>
		<title>Restricting SSH access to rsync for Android</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/Restricting_SSH_access_to_rsync_for_Android.html"/>
		<updated>2012-11-30T12:10:59+01:00</updated>
      <id>http://techblog.vsza.hu/posts/Restricting_SSH_access_to_rsync_for_Android.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>I like to synchronize photos taken with my Android phone with my notebook, and
since I dislike centralized solutions (mostly for reasons of privacy), I
installed <a href="https://play.google.com/store/apps/details?id=eu.kowalczuk.rsync4android">rsync for Android</a>, which is easy to install from Play Store,
and <a href="http://android.kowalczuk.eu/rsync4android/">with SSH public key authentication</a>, syncing the images is easy and
secure at the same time.</p>

<p>My problem was that still hadn't collected enough information to trust my phone
with powerful public keys (even though I use <a href="http://thialfihar.org/projects/apg/">APG</a>, I only added public keys
so far), and having a key on my phone that could allow anyone to log into my
notebook through SSH was unacceptable for me, even though I set up a separate
user account, and SSH wasn't set up to start at boot.</p>

<p>To solve this problem, I logged what command the application started upon
connecting via SSH, and added the following line to the <code>authorized_keys</code> file
in the <code>.ssh</code> subdirectory of the home directory of the dedicated user (<code>foo</code>).
The lines are split only for easier readability, there should be no line break
or whitespace between <code>no-port-forwarding,</code> and <code>no-agent-forwarding</code>.</p>

<pre><code>command="rsync --server -vlHDtre.i . /home/foo/images",no-port-forwarding,
    no-agent-forwarding,no-X11-forwarding,no-pty ssh-dss AAAA...
</code></pre>

<p>This way, the private key on the phone can only be used for rsyncing a specific
directory, and cannot be used to</p>

<ul>
<li>open a shell or start any other program, or</li>
<li>forward TCP ports, SSH agent or X11 connections from/to my notebook.</li>
</ul>

<p>Thanks to <a href="https://rhapsodhy.hu/">rhapsodhy</a> for <a href="http://pastebin.com/ivrxjnwC">the inspiration</a>.</p>
]]></content>
	</entry>
	<entry>
		<title>Seesmic Android information leak</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/Seesmic_Android_information_leak.html"/>
		<updated>2012-11-13T23:38:08+01:00</updated>
      <id>http://techblog.vsza.hu/posts/Seesmic_Android_information_leak.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>In the August 2012 <a href="http://hekkcamp.net/">hekkcamp</a> I hunted for security vulnerabilities in
several Android applications and <a href="https://play.google.com/store/apps/details?id=com.seesmic">Seesmic Android</a> happened to be one
of them. I originally heard about it from <a href="https://rhapsodhy.hu/">rhapsodhy</a>, and it's one of
those multi-platform social network clients, this one having the advantage of
not requesting crazy privileges, unlike the official Twitter and Facebook apps.
<a href="http://0x90.freeblog.hu/">Zsombor</a> told me about <a href="http://labs.mwrinfosecurity.com/tools/2012/03/16/mercury/">Mercury</a>, a FLOSS Android vulnerability
assessment tool, so I checked out the latest development version from
<a href="https://github.com/mwrlabs/mercury">their GitHub repo</a> since 1.0.0, the only version available then happened
to be incompatible with recent Android releases.</p>

<p>Using Mercury, I found that Seesmic offers several <a href="http://developer.android.com/guide/topics/providers/content-providers.html">content providers</a> that
not only had interesting names and fields, but were available for reading to
any other application running on the device. As Android separates applications
pretty strictly, these providers are the favorable way of sharing structured
information between apps, and although <a href="http://developer.android.com/guide/topics/providers/content-provider-creating.html#Permissions">they can be protected</a> with
application-specific permissions, many developers tend to forget about such
things. In case of Seesmic, I used the <code>finduri</code> command of Mercury in the
<code>provider</code> module.</p>

<pre><code class="no-highlight">*mercury#provider&gt; finduri com.seesmic

/data/app/com.seesmic-2.apk:
content://cal&#x65;ndar/cal&#x65;ndars
content://cal&#x65;ndar/events
content://cal&#x65;ndar/reminders
content://com.android.cal&#x65;ndar/cal&#x65;ndars
content://com.android.cal&#x65;ndar/events
content://com.android.cal&#x65;ndar/reminders
content://com.google.plus.platform/ads
content://com.google.plus.platform/token
content://com.seesmic.aggregate/aggregate_authors
content://com.seesmic.aggregate/aggregate_timelines
content://com.seesmic.facebook/facebook_authors
content://com.seesmic.facebook/facebook_feeds
content://com.seesmic.facebook/facebook_friendlists
content://com.seesmic.facebook/facebook_page_profiles
content://com.seesmic.facebook/facebook_people
content://com.seesmic.facebook/facebook_profiles
content://com.seesmic.facebook/facebook_updates
content://com.seesmic.twitter/accounts
content://com.seesmic.twitter/attachs
content://com.seesmic.twitter/authors
content://com.seesmic.twitter/dm
content://com.seesmic.twitter/list_info
content://com.seesmic.twitter/lists
content://com.seesmic.twitter/mute
content://com.seesmic.twitter/search_results
content://com.seesmic.twitter/searches
content://com.seesmic.twitter/timelines
content://com.seesmic.twitter/topics
content://com.seesmic.twitter/tweets
content://com.seesmic.twitter/userlists
content://com.seesmic.twitter/users
</code></pre>

<p>In order to inspect the extracted data and provide a nice and simple
proof-of-concept, I developed a small application called CoProLeak
(CoPro = Content Provider) that could show the two of the most problematic
leaks in the Seesmic application. It's worth noting that the application
doesn't require any permissions – as it can be seen on the left frame of the
screenshot below – so it could lurk inside any kind of application or game.</p>

<ul>
<li>The <code>content://com.seesmic.facebook/facebook_people</code> provider made all the Facebook friends of the user available with name, Facebook ID and full contact information. This can be seen in the middle frame of the screenshot below, clicking on a person's name displayed his/her photo using the Facebook graph API in a browser window.</li>
<li>The <code>content://com.seesmic.twitter/accounts</code> provider made all the accounts configured in the application available with username and password or OAuth token and secret. This can be seen in the right frame of the screenshot below, these credentials are enough for anyone to impersonate the user account.</li>
</ul>

<p><img src="http://techblog.vsza.hu/images/cpl-poc.png" alt="Working proof-of-concept displaying sensitive information" title="" /></p>

<p>For example, displaying the list of friends required the following snippet.
(The <code>relationship_type</code> filter was necessary to exclude liked pages that
were also available from the content provider.)</p>

<pre><code>final Uri SEESMIC_FB_PEOPLE_URI = Uri.parse(
        "content://com.seesmic.facebook/facebook_people");
final String[] projection = { "_id", "full_name" };
final String selection = "relationship_type = ?";
final String[] selectionArgs = { "1" };
final String sortOrder = "full_name";

final Cursor cur = getContentResolver().query(SEESMIC_FB_PEOPLE_URI,
        projection, selection, selectionArgs, sortOrder);

final String[] from = { "full_name" };
final int[] to = { android.R.id.text1 };
setListAdapter(new SimpleCursorAdapter(this,
            android.R.layout.simple_list_item_1, cur, from, to));
</code></pre>

<p>As it turned out, contacting a social media related company with such delicate
matter wasn't trivial. For purposes of feedback, they had a public forum,
which was obviously not the place to describe vulnerabilities in detail. On
their <a href="https://seesmic.com/about/">about site</a>, I found the e-mail address <em>ContactUs at Seesmic dot com</em>,
and sent them a mail right after the proof-of-concept worked. I waited for a
month, then tried contacting them on <a href="https://www.facebook.com/SeesmicPage">their Facebook page</a>, where they
replied 5 days later, and said to <a href="https://seesmic.zendesk.com/tickets/new/">open a ticket in their Zendesk system</a>.</p>

<p>After I did so, they replied that they'll “let [their] Dev Team know about this
as [they]'ll review the issue”. I waited for another two months, and then one
day, I just opened the notification on my Android phone that a new version of
Seesmic was available, that contains “security improvements”. Since they
haven't released an update through the Play Store since summer, I immediately
tried CoProLeak and I was pleased to found that both functions of the
proof-of-concept application crashed with permission problems.</p>

<p><img src="http://techblog.vsza.hu/images/cpl-update.png" alt="Updated version notification and crashing proof-of-concept" title="" /></p>

<p>To be sure, I checked the logs with ADB, and it's pretty clear that the
application gets terminated because of (unhandled) permission denial.</p>

<pre><code>I/ActivityManager(  246): START {cmp=hu.sil&#x65;ntsignal.android.coproleak/.SeesmicAccountsList u=0} from pid 8388
W/ActivityManager(  246): Permission denied: checkComponentPermission() owningUid=10073
W/ActivityManager(  246): Permission Denial: opening provider com.seesmic.data.DbProvider from ProcessRecord{422e6d78 8388:hu.sil&#x65;ntsignal.android.coproleak/u0a46} (pid=8388, uid=10046) that is not exported from uid 10073
D/AndroidRuntime( 8388): Shutting down VM
W/dalvikvm( 8388): threadid=1: thread exiting with uncaught exception (group=0x414dc300)
E/AndroidRuntime( 8388): FATAL EXCEPTION: main
E/AndroidRuntime( 8388): java.lang.RuntimeException: Unable to start activity ComponentInfo{hu.sil&#x65;ntsignal.android.coproleak/hu.sil&#x65;ntsignal.android.coproleak.SeesmicAccountsList}: java.lang.SecurityException: Permission Denial: opening provider com.seesmic.data.DbProvider from ProcessRecord{422e6d78 8388:hu.sil&#x65;ntsignal.android.coproleak/u0a46} (pid=8388, uid=10046) that is not exported from uid 10073
E/AndroidRuntime( 8388): Caused by: java.lang.SecurityException: Permission Denial: opening provider com.seesmic.data.DbProvider from ProcessRecord{422e6d78 8388:hu.sil&#x65;ntsignal.android.coproleak/u0a46} (pid=8388, uid=10046) that is not exported from uid 10073
E/AndroidRuntime( 8388):        at android.os.Parcel.readException(Parcel.java:1425)
E/AndroidRuntime( 8388):        at android.os.Parcel.readException(Parcel.java:1379)
E/AndroidRuntime( 8388):        at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:2354)
E/AndroidRuntime( 8388):        at android.app.ActivityThread.acquireProvider(ActivityThread.java:4219)
E/AndroidRuntime( 8388):        at android.app.ContextImpl&#x24;ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:1703)
E/AndroidRuntime( 8388):        at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1099)
E/AndroidRuntime( 8388):        at android.content.ContentResolver.query(ContentResolver.java:354)
E/AndroidRuntime( 8388):        at android.content.ContentResolver.query(ContentResolver.java:313)
E/AndroidRuntime( 8388):        at hu.sil&#x65;ntsignal.android.coproleak.SeesmicAccountsList.onCreate(SeesmicAccountsList.java:38)
E/AndroidRuntime( 8388):        at android.app.Activity.performCreate(Activity.java:5008)
E/AndroidRuntime( 8388):        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
E/AndroidRuntime( 8388):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
E/AndroidRuntime( 8388):        ... 11 more
W/ActivityManager(  246):   Force finishing activity hu.sil&#x65;ntsignal.android.coproleak/.SeesmicAccountsList
W/ActivityManager(  246):   Force finishing activity hu.sil&#x65;ntsignal.android.coproleak/.Main
</code></pre>
]]></content>
	</entry>
	<entry>
		<title>ADSdroid 1.2 released due to API change</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/ADSdroid_1.2_released_due_to_API_change.html"/>
		<updated>2012-10-18T14:45:07+02:00</updated>
      <id>http://techblog.vsza.hu/posts/ADSdroid_1.2_released_due_to_API_change.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>On October 6, 2012, Matthias Müller sent me an e-mail, telling me that
the download functionality of <a href="http://techblog.vsza.hu/posts/Unofficial_Android_app_for_alldatasheet.com.html">ADSdroid</a> was broken. As it turned out,
AllDataSheet changed their website a little bit, resulting in the following
exception getting thrown during download.</p>

<pre><code>java.lang.IllegalArgumentException: Malformed URL: javascript:mo_search('444344','ATMEL','ATATMEGA168P');
    at org.jsoup.helper.HttpConnection.url(HttpConnection.java:53)
    at org.jsoup.helper.HttpConnection.connect(HttpConnection.java:25)
    at org.jsoup.Jsoup.connect(Jsoup.java:73)
    at hu.vsza.adsapi.Part.getPdfConnection(Part.java:32)
    at hu.vsza.adsdroid.PartList&#x24;DownloadDatasheet.doInBackground(PartList.java:56)
    at hu.vsza.adsdroid.PartList&#x24;DownloadDatasheet.doInBackground(PartList.java:48)
    at android.os.AsyncTask&#x24;2.call(AsyncTask.java:264)
    at java.util.concurrent.FutureTask&#x24;Sync.innerRun(FutureTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    at android.os.AsyncTask&#x24;SerialExecutor.run(AsyncTask.java:208)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
    at java.util.concurrent.ThreadPoolExecutor&#x24;Worker.run(ThreadPoolExecutor.java:569)
    at java.lang.Thread.run(Thread.java:856)
 Caused by: java.net.MalformedURLException: Unknown protocol: javascript
    at java.net.URL.&lt;init&gt;(URL.java:184)
    at java.net.URL.&lt;init&gt;(URL.java:127)
    at org.jsoup.helper.HttpConnection.url(HttpConnection.java:51)
    ... 12 more
</code></pre>

<p>The address (<code>href</code>) of the link (<code>&lt;a&gt;</code>) used for PDF download has changed from
a simple HTTP one to a JavaScript call that <a href="http://jsoup.org/">JSoup</a>, the library I used for
HTML parsing and doing HTTP requests couldn't possibly handle. The source of
the <code>mo_search</code> function can be found in <code>js/datasheet_view.js</code>. The relevant
part can be seen below, I just inserted some whitespace for easier readability.</p>

<pre><code class="javascript">function mo_search(m1, m2, m3) {
    frmSearch2.ss_chk.value = m1;
    frmSearch2.sub_chk.value = m2;
    frmSearch2.pname_chk.value = m3;
    frmSearch2.action = 'http://www.alldatasheet.com/datasheet-pdf/pdf/'
        + frmSearch2.ss_chk.value + '/' + frmSearch2.sub_chk.value
        + '/' + frmSearch2.pname_chk.value + '.html';
    frmSearch2.submit();
}
</code></pre>

<p>That didn't seem that bad, so I wrote a simple regular expression to handle the
issue.</p>

<pre><code class="java">import java.util.regex.*;

Pattern jsPattern = Pattern.compile(
    "'([^']+)'[^']*'([^']+)'[^']*'([^']+)'");

final Matcher m = jsPattern.matcher(foundPartHref);
if (m.find()) {
    foundPartHref = new StringBuilder(
        "http://www.alldatasheet.com/datasheet-pdf/pdf/")
        .append(m.group(1)).append('/')
        .append(m.group(2)).append('/')
        .append(m.group(3)).append(".html").toString();
}
</code></pre>

<p>The regular expression is overly liberal on purpose, in the hope that it can
handle small changes in the AllDataSheet website in the future without
upgrading the application. I pushed version 1.2 to GitHub, and it contains
many other optimizations, too, including enabling ProGuard. The
<a href="http://vsza.hu/ad1.0.apk">resulting APK</a> is 30% smaller than previous versions, and it can be
downloaded by using the link in the beginning of this sentence, or using the
QR code below. It's also available from the
<a href="http://f-droid.org/repository/browse/?fdid=hu.vsza.adsdroid">F-Droid Android FOSS repository</a>, which also ensures automatic upgrades.</p>

<p><img src="http://techblog.vsza.hu/images/adsdroid-1.0-qr.png" alt="ADSdroid QR code" title="" /></p>
]]></content>
	</entry>
	<entry>
		<title>Installing CAcert on Android without root</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/Installing_CAcert_on_Android_without_root.html"/>
		<updated>2012-08-16T14:29:28+02:00</updated>
      <id>http://techblog.vsza.hu/posts/Installing_CAcert_on_Android_without_root.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>I've been using <a href="http://cacert.org/">CAcert</a> for securing some of my services with TLS/SSL, and
when I got my Android phone I <a href="http://techblog.vsza.hu/posts/Adding_certificate_checksum_to_K-9_Mail.html">chose K-9 mail over the stock e-mail client</a>
because as the <a href="http://wiki.cacert.org/FAQ/ImportRootCert#Android_Phones">certificate installation page on the official CAcert site</a>
stated, it required root access to access the system certificate store. Now,
one year and two upgrades (ICS, JB) later, I revisited the issue.</p>

<p>As of this writing, the CAcert site contains another method that also requires
root access, but as <a href="http://www.jethrocarr.com/2012/01/04/custom-ca-certificates-and-android/">Jethro Carr wrote in his blog</a>, since at least ICS,
it's possible to install certificates without any witchcraft, using not only
PKCS12 but also PEM files. Since <a href="http://packages.debian.org/sid/all/ca-certificates/filelist">Debian ships the CAcert bundle</a>, I used
that file, but it's also possible to download the files from
<a href="http://www.cacert.org/index.php?id=3">the official CAcert root certificate download page</a>. Since I have Android
SDK installed, I used <code>adb</code> (Android Debug Bridge) to copy the certificate to
the SD card, but any other method (browser, FTP, e-mail, etc.) works too.</p>

<pre><code class="no-highlight">&#x24; adb push /usr/share/ca-certificates/cacert.org/cacert.org.crt /sdcard/
2 KB/s (5179 bytes in 1.748s)
</code></pre>

<p>On the phone, I opened <em>Settings > Security</em>, scrolled to the bottom, and
selected <em>Install from storage</em>. It prompted for a name of the certificate,
and installed the certificate in a second without any further questions asked.</p>

<p><img src="http://techblog.vsza.hu/images/cacert-android-install.png" alt="Installing the CAcert root certificate on Android" title="" /></p>

<p>After this, the certificate can be viewed and by opening <em>Trusted credentials</em>
and selecting the <em>User</em> tab, and browsing an HTTPS site with a CAcert-signed
certificate becomes just as painless and secure as with any other built-in CA.</p>

<p><img src="http://techblog.vsza.hu/images/cacert-android-usage.png" alt="Using CAcert root certificate on Android" title="" /></p>
]]></content>
	</entry>
	<entry>
		<title>Unofficial Android app for alldatasheet.com</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/Unofficial_Android_app_for_alldatasheet.com.html"/>
		<updated>2012-04-17T19:35:22+02:00</updated>
      <id>http://techblog.vsza.hu/posts/Unofficial_Android_app_for_alldatasheet.com.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>In February 2012, I read the <a href="http://hackaday.com/2012/02/10/electrodroid-your-android-electronic-reference-app/">Hack a Day article about ElectroDroid</a>, and
the following remark triggered <a href="http://knowyourmeme.com/memes/chall&#x65;nge-accepted">chall&#x65;nge accepted</a> in my mind.</p>

<pre><code class="no-highlight">A ‘killer app’ for electronic reference tools would be a front end for
alldatasheet.com that includes the ability to search, save, and display
the datasheet for any imaginable component.
</code></pre>

<p>First, I checked whether any applications like that exists on the smartphone
application markets. I found several applications of high quality but tied to
certain chip vendors, such as <a href="https://play.google.com/store/apps/details?id=com.digikey.mobile">Digi-Key</a> and <a href="https://play.google.com/store/apps/details?id=com.nxp.android.app">NXP</a>. There's also one
that implies to be an <a href="http://www.alldatasheet.com/">alldatasheet.com</a> application, it even calls itself
<a href="https://play.google.com/store/apps/details?id=alldatasheet.froyo.refresh">Datasheet (Alldatasheet.com)</a>, but as one commenter writes</p>

<pre><code class="no-highlight">All this app does is open a web browser to their website.
Nothing more. A bookmark can suffice.
</code></pre>

<p>I looked around the alldatasheet.com website and found the search to be rather
easy. Although there's no API available, the HTML output can be easily parsed
with the MIT-licensed <a href="http://jsoup.org/">jsoup</a> library. First I tried to build a separate
Java API for the site, and a separate Android UI, with former having no
dependencies on the Android library. The API can be found in the
<a href="https://github.com/dnet/adsdroid/blob/master/src/hu/vsza/adsapi/">hu.vsza.adsapi</a> package, and as of version 1.0, it offers two classes.
The <code>Search</code> class has a method called <code>searchByParName</code> which can be used to
use the functionality of the left form on the website. Here's an example:</p>

<pre><code class="java">List&lt;Part&gt; parts = Search.searchByPartName("ATMEGA168", Search.Mode.MATCH);

for (Part part : part) {
    doSomethingWithPart(part);
}
</code></pre>

<p>The <code>Part</code> class has one useful method called <code>getPdfConnection</code>, which returns
an <code class="java">URLConnection</code> instance that can be used to read the PDF datasheet about
the electronics part described by the object. It spoofs the <code>User-Agent</code> HTTP
header and sends the appropriate <code>Referer</code> values wherever it's necessary to
go throught the process of downloading the PDF. This can be used like this:</p>

<pre><code class="java">URLConnection pdfConn = selectedPart.getPdfConnection();
pdfConn.connect();
InputStream input = new BufferedInputStream(pdfConn.getInputStream());
OutputStream output = new FileOutputStream(fileName);

byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) output.write(data, 0, count);

output.flush();
output.close();
input.close();
</code></pre>

<p>The Android application built around this API displays a so-called Spinner
(similar to combo lists on PCs) to select search mode and a text input to
enter the part name, and a button to initiate search. Results are displayed
in a list view displaying the name and the description of each part. Touching
a part downloads the PDF to the SD card and opens it with the default PDF
reader (or prompts for selection if more than one are installed).</p>

<p><img src="http://techblog.vsza.hu/images/adsdroid-screenshot.png" alt="ADSdroid version 1.0 screenshots" title="" /></p>

<p>You can download <a href="http://vsza.hu/ad1.0.apk">version 1.0</a> by clicking on the version number link or using
the QR code below. It only does one thing (search by part name), and even that
functionality is experimental, so I'm glad if anyone tries it and in case of
problems, contacts me in e-mail. The source code is available on <a href="https://github.com/dnet/adsdroid">GitHub</a>,
licensed under MIT.</p>

<p><img src="http://techblog.vsza.hu/images/adsdroid-1.0-qr.png" alt="ADSdroid version 1.0 QR code" title="" /></p>
]]></content>
	</entry>
	<entry>
		<title>Adding certificate checksum to K-9 Mail</title>
		<link rel="alternate" type="text/html" href="http://techblog.vsza.hu/posts/Adding_certificate_checksum_to_K-9_Mail.html"/>
		<updated>2011-07-16T17:53:31+02:00</updated>
      <id>http://techblog.vsza.hu/posts/Adding_certificate_checksum_to_K-9_Mail.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="http://techblog.vsza.hu"><![CDATA[
      <p>When I got my Android phone, I tried to make it work with my e-mail server which
supports TLS and SSL using a CAcert certificate. CAcert is not yet present in
the Android list of root certificates, and an
<a href="http://wiki.cacert.org/FAQ/ImportRootCert#Android_Phones">FAQ entry of the official CAcert site</a> along with two Android issues
(<a href="http://code.google.com/p/android/issues/detail?id=6207">6207</a> and <a href="http://code.google.com/p/android/issues/detail?id=11231">11231</a>) state, that since this list is
writeable to root only, it requires rooting of the phone, which I've considered
an overkill. I also found that the stock Mail application had only two
options for TLS or SSL security: either accept all certificates, thus creating
a false sense of security, or accept certificates only from the read-only list.</p>

<p><img src="http://techblog.vsza.hu/images/builtin-mail-ssl-options.png" alt="SSL/TLS options of the stock Android Mail application" title="" /></p>

<p>I tried an alternative mail client called <a href="http://code.google.com/p/k9mail/">K-9 mail</a>, which had more
options available, as it allowed the user to examine the certificate, and
accept it to be used in future communications. I configured the mailbox, and
got a nice dialog box asking me to confirm the details of the certificate.</p>

<p><img src="http://techblog.vsza.hu/images/k9mail-ssl-fail.png" alt="SSL/TLS certificate dialog in K-9 Mail" title="" /></p>

<p>Unfortunately, the only problem with this dialog box was making the whole
feature useless: it didn't contain the checksum (also known as fingerprint)
of the certificate, which is the only value not spoofable by a man in the
middle (MITM) attacker. There are point-and-click tools available on the web
that can create a rogue certificate matching the original one in every detail,
and the only difference is the public key, which affects the checksum.
I developed a <a href="https://github.com/k9mail/k-9/commit/dcf5d150a618b6b9b78b42d38943fca47cdc461b">patch to fix this problem</a>, which was <a href="https://github.com/k9mail/k-9/pull/10">accepted</a> after a
short discussion, and later made its way into the <a href="https://market.android.com/details?id=com.fsck.k9">Android Market</a>.</p>

<p>First, I found, that the checksum algorithm is SHA-1 most of the time,
since MD5 is considered broken for this purpose. To calculate the SHA-1
hashes of the certificates in the chain, I imported the necessary classes
and instantiated the SHA-1 MessageDigest class.</p>

<pre><code>import java.security.NoSuchAlgorithmException;
import java.security.MessageDigest;

...

MessageDigest sha1 = null;
try {
    sha1 = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
    Log.e(K9.LOG_TAG, "Error while initializing MessageDigest", e);
}
</code></pre>

<p>I spent most of the time figuring out how to extract the content of the
certificate that needs to be hashed. As <a href="http://stackoverflow.com/users/232024/roman-d">Roman D</a> figured out in a
<a href="http://stackoverflow.com/questions/4803799/how-to-calculate-x-509-certificates-sha-1-fingerprint">post on Stack Overflow</a>, “the hash is calculated over the DER-encoded
(again, not the PEM string) TBS part only, including its ASN.1 header
(the <code>ID 0x30 == ASN1_SEQUENCE | ASN1_CONSTRUCTED</code> and the length field)”.</p>

<p>Knowing this, I just needed to extract this information form the instances
of the <a href="http://download.oracle.com/javase/6/docs/api/java/security/cert/X509Certificate.html">X509Certificate</a> interface. I tried the getTBSCertificate
method with no luck, but later found that there's a method inherited from
Certificate called <a href="http://download.oracle.com/javase/6/docs/api/java/security/cert/Certificate.html#getEncoded()">getEncoded</a>, which does just what I needed.
There was only one task to do: since the MessageDigest object returns the
digest in raw bytes, I needed to convert them to hex digits in order to
display it in the dialog box. It turned out, that the project already had
a class for that, so I could avoid reinventing the wheel.</p>

<pre><code>import com.fsck.k9.mail.filter.Hex;
import java.security.cert.CertificateEncodingException;

...

if (sha1 != null) {
  sha1.reset();
  try {
    char[] sha1sum = Hex.encodeHex(sha1.digest(chain[i].getEncoded()));
    chainInfo.append("Fingerprint (SHA-1): " + new String(sha1sum) + "\n");
  } catch (CertificateEncodingException e) {
    Log.e(K9.LOG_TAG, "Error while encoding certificate", e);
  }
}
</code></pre>

<p>After development and building, there was only one task: testing. I installed
the modified version into an emulator and tried to configure an account on
my mail server. It worked, and as you can see on the screenshot below, the
checksum matches the one you can <a href="http://www.cacert.org/index.php?id=3">CAcert fingerprint page</a>.</p>

<p><img src="http://vsza.hu/k9mail-patch.png" alt="Patched version displaying CAcert certificate" title="" /></p>
]]></content>
	</entry>
</feed>
