Stories tagged Security:RSS Feed

Thouhts on secure software archives; tags=Debian, Web, Linux, FOSS, Security

From the java point of view

Recently I had to get some Scala Tool working correctly. Unfortunately there are basically no packages in the Debian Archive at all so I had to use maven to install these (or download + install manually). Being a highly paranoid person downloading and executing code from the internet without any cryptographic verification at all one after the other practically drove me nuts. Looking a bit deeper I noticed that some of the software in maven's repository have some signatures next to them -- signed by the author or release manager of this specific project.

Why secure sources matters

With my experience in mind I got some Input from other people. One of the things I was told is that some scala tools just aren't security critical -- they're only installed and used as the current user. In my opinion this is, for my desktop system, totally wrong. The important things on my private Computers are my GPG and SSH keys as well as my private data. For messing with these no super user access is needed at all.

Comparing to the Common Lisp situation

Being a Common Lisp fan of course I noticed basically the same problem for installing Common Lisp libraries. Here the situation in Debian is quite a bit better -- and I'm working in the pkg-common-lisp Team to improve this even more. Common Lisp has some maven-alike tool for downloading and installing dependency trees called quicklisp -- without any cryptographic verification as well. However there's light at the end of this tunnel: There are plans to add GPG verification of the package lists really soon.

Comparing the maven and the quicklisp model

So there are basically two different approaches to be seen here. In maven the software author confirms with his signature the integrity of his software while in quicklisp the distributor confirms all users get the same software that he downloaded. Now the quicklisp author can't and won't check all the software that is downloadable using quicklisp. This won't be doable anyway as there's way to much software or a single person to check.

Now in some kind of perfect World the maven way would be vastly superior as there's a End-To-End verification and verification of the full way the software takes. However there's a big problem: I don't know any of these Authors personally and there's no reason I should just trust any of them.

Now comparing this to the Distribution / quicklisp model. Here I would just have to trust one person or group -- here the quicklisp team -- to benefit from the crypto which might be possible based on karma inside the using community. However here I don't gain the possibility that the software is integer.

However idealized if some of these pieces of software was forged between upstream and the quicklisp team and attacker would also intercept me downloading the software from the same address so I get the source from upstream matching the checksum from quicklisp -- assuming the quicklisp team does indeed know the correct website. Additionally I get the confirmation that all other quicklisp users get the same source (if the quicklisp guys are fine of course) so no-one inside the community complaining is a good indication the software is fine. For this to work there's of course a relevant user-base of the distributor (quicklisp) necessary.

Relevance for Debian

So how do conventional Linux Distributions like Debian fit in here. Ideally we would have maintainers understanding and checking the software and confirming the integrity using their private key or at least know their upstreams and having at least a secured way getting the software from upstream and a trust relationship with them. Of course that's just illusionary thinking of complex and important software (think libreoffice, gcc or firefox for example). Maintainers won't fully understand a lot simpler pieces of software. And loads of upstream projects don't provide a verified way of getting the correct source code though that's a bit better on the real high-impact projects where checksums signed by the Release Manager are more common than in small projects.

A misguided thought at the end

As I'm a heavy emacs user I like to have snapshots from current emacs development available. Fortunately binary packages with this are available from a Debian guy I tend to trust who is also involved upstream so adding the key from his repository to the keyring apt trusts. Now my first thoughts were along the lines "It would be really nice if I could pin that key to only the emacs snapshot packages" so this guy can't just put libc packages in his repository and my apt would trust them. Now thinking of it again a bogus upload of the emacs snapshot package could just as well put some binary or library on the system at some place in front of the real on in the system path which would be rather similar bad.

b

-- Christoph Egger <christoph@christoph-egger.org> Do, 12 Mai 2011 21:19:49 +0200

Generating .wot files now; tags=Web, Security, GnuPG

As you might have noticed, the original source of Web-Of-Trust Graph information went offline and probably won't come back. As a result also pathfinders like the one of Henk P. Penning are stuck in February 2012.

As I always found this kind of statistics interesting I've hacked the pks2wot python script that is part of the wotsap package to use normal hkp instead of the pks client and running it against my own sks keyserver which seems to work good enough to do a weekly dump of the current web-of-trust which can be found at http://wot.christoph-egger.org/download/. I'd be happy to hear if this is useful to anyone besides myself.


-- Christoph Egger <christoph@christoph-egger.org> Di, 04 Dez 2012 00:12:56 +0100

RuCTFe nsaless; tags=Uni, HowTo, Security

Greetings from the FAU Security Team (FAUST), the Uni Erlangen CTF group. We were participating in the RuCTFe competition and made it to 4th place. Following is my write-up on the nsaless service, the main crypto challenge in the competition. nsaless is a nodejs webservice providing a short message service. People can post messages and their followers receive the message encrypted to their individual RSA key.

About the gameserver protocol

The gameserver created groups of 8 users on the service 7 were just following the first user (and authorized by the first user to do so) while the first user sent a tweet containing the flag. The service used 512bit RSA with 7 as public exponent. While RSA512 is certainly weak, it's strong enough to make it unfeasible to break directly.

Attacking RSA

There are some known attacks against RSA with small exponents if no proper padding is done. The most straightforward version just takes the e-th root of the cipher-text and, if the clear message was small enough, outputs that root as plain-text. As the flag was long enough to make this attack impossible, we need a somewhat improved Attack.

Håstad's Broadcast Attack

Reminder:

  • In RSA, given a plain-text A, the sender computes Aᵉ mod N to build the cipher-text B.
  • Given simultaneous congruences we can efficiently compute a x ∈ ℤ such that x satisfies all congruences using the Chinese remainder theorem.

For NSAless we actually get several such B for different N (each belonging to different users receiving the tweet because they follow the poster). This effectively means we get Aᵉ in mod N for different N. Using the Chinese remainder theorem we can now compute a x ∈ ℤ ≡ Aᵉ mod Π Nᵢ. If we use at least e different B for this we are guaranteed that x actually equals Aᵉ (in ): A needs to be smaller than N for all N used (otherwise we lose information during encryption), therefore Aᵉ needs to be smaller than Nᵉ.

Computing now the e-th root of x we get the plain-text A – the flag.

Fix

Fixing your service is easy enough, just increase e to an suitable number > 8. At the end of the contest 5 Teams had fixed this vulnerability by either using 17 or 65537.

EXPLOIT

The basic exploit is shown below. Unfortunately it needs to retrieve all tweets for all users the compute the flags which just takes too long to be feasible (at least at the end of the competition where tons of users already existed) so you would need some caching to make it actually work. Would have been a great idea to have users expire after an hour or two in the service!

#!/usr/bin/python

import httplib
import urllib
import re
import json
import pprint
import gmpy
import sys

userparse_re = re.compile('<a [^>]*>([^<]*)</a></div>\s*<div>([^<]*)</div>')
tweetparse_re = re.compile("<div id='last_tweet'>([0-9]+)</div>")
followingparse_re = re.compile('<div><a href="/[0-9]+">([0-9]+)</a></div>')

def my_parse_number(number):
    string = "%x" % number
    if len(string) != 64:
        return ""
    erg = []
    while string != '':
        erg = erg + [chr(int(string[:2], 16))]
        string = string[2:]
    return ''.join(erg)

def extended_gcd(a, b):
    x,y = 0, 1
    lastx, lasty = 1, 0

    while b:
        a, (q, b) = b, divmod(a,b)
        x, lastx = lastx-q*x, x
        y, lasty = lasty-q*y, y

    return (lastx, lasty, a)

def chinese_remainder_theorem(items):
  N = 1
  for a, n in items:
    N *= n

  result = 0
  for a, n in items:
    m = N/n
    r, s, d = extended_gcd(n, m)
    if d != 1:
      raise "Input not pairwise co-prime"
    result += a*s*m

  return result % N, N

def get_tweet(uid):
    try:
        conn = httplib.HTTPConnection("%s:48879" % sys.argv[1], timeout=60)
        conn.request("GET", "/%s" % uid)
        r1 = conn.getresponse()
        data = r1.read()
        tweet = re.findall(tweetparse_re, data)
        if len(tweet) != 1:
            return None
        followers = re.findall(followingparse_re, data)
        return tweet[0], followers
    except:
        return None

def get_users():
    conn = httplib.HTTPConnection("%s:48879" % sys.argv[1], timeout=60)
    conn.request("GET", "/users")
    r1 = conn.getresponse()
    data1 = r1.read(1024 * 1024)
    data = dict()
    for i in re.findall(userparse_re, data1)[:100]:
        userinfo = get_tweet(i[0])
        if userinfo != None:
            data[i[0]] = (json.loads(i[1].replace('&quot;', '"'))['n'], userinfo)

    return data

users = get_users()
allusers = users.keys()
masters = [ user for user in allusers if len(users[user][1][1]) > 0 ]

for test in masters:
    try:
        followers = users[test][1][1]
        data = []

        for fol in followers:
            n = int(users[fol][0])
            tweet = int(users[fol][1][0])
            data = data + [(tweet, n)]

        x, n = chinese_remainder_theorem(data)

        realnum = gmpy.mpz(x).root(7)[0].digits()
        print my_parse_number(int(realnum))
    except:
        pass

-- Christoph Egger <christoph@christoph-egger.org> Fr, 20 Dez 2013 13:59:29 +0100


valid XHTML, CSS -- Django based -- ©2008 Christoph Egger