Tuesday, March 27, 2012

Checking client-side certificate verification with openssl

So you have some client software that claims it checks server SSL certs are issued by a valid CA, or better, by a specific CA? How do you check its claims? Set up a simple MITM attack (works for OS X and linux):

Create a self-signed cert:
openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem
Fire up the openssl server (man s_server for more options, including simple webserver functionality):
sudo openssl s_server -debug -cert cert.pem -accept 443
Edit your /etc/hosts file and add the domain you are attacking to resolve to localhost:
127.0.0.1 secure.company.com
Run your client.

Tuesday, March 13, 2012

ComputerName vs. LocalHostName vs. HostName on OS X

Hostnames on OS X are...complicated. Using scutil is probably the easiest way to get at them, although there are others. It looks like scutil just parses this plist:
/Library/Preferences/SystemConfiguration/preferences.plist

ComputerName


This is the computer name visible in the GUI in Preferences | Sharing | Computer Name and the scutil manpage describes it as 'The user-friendly name for the system.'
scutil --get ComputerName
Apple says:
The AppleTalk name and the default name used for SLP/DA. The Network browser in the Finder uses SMB/CIFS to find computers that provide Windows file sharing.

LocalHostName


This appears to be only used for Bonjour-aware services on the local network.
scutil --get LocalHostName
Apple says:
The name that designates a computer on a local subnet.
and as of 10.6:
Host names that contain only one label in addition to local, for example "My-Computer.local", are resolved using Multicast DNS (Bonjour) by default. Host names that contain two or more labels in addition to local, for example "server.domain.local", are resolved using a DNS server by default.

HostName


The name associated with hostname(1) and gethostname(3). Displayed in the default terminal command prompt (user@hostname).
scutil --get HostName
Apple says:
You can’t specify this name during server setup. Server Assistant sets the host name to AUTOMATIC in /etc/hostconfig. This setting causes the server’s host name to be the first name that’s true in this list:
- The name provided by the DHCP or BootP server for the primary IP address
- The first name returned by a reverse DNS (address-to-name) query for the primary IP address
- The local hostname
- The name “localhost”

Thursday, March 1, 2012

Using a dictionary to populate a format string in python for human and computer-friendly error reporting

Python 2.6 has brought some interesting string formatting options to the table. I recently needed an object that could pass back error information that could be consumed by humans and other code. The new string formatting came in handy.

class ValidationError(Exception):
  """Class for reporting validation errors."""

  BAD_RECORD = 1

  def __init__(self, error, msg, **kwargs):
    """Record Validation Error.

    Requires python 2.6

    Args:
      error: ValidationError code e.g. ValidationError.BAD_RECORD
      msg: format string for human readable version of the error
      **kwargs: kwargs to populate format string
    """
    super(ValidationError, self).__init__(self)
    self.message = msg.format(**kwargs)
    self.error = error
    self.kwargs = dict(kwargs)

  def __str__(self):
    return self.message

You can use it like this:

e = ValidationError(ValidationError.BAD_RECORD,
                    'Bad record detected in {records}',
                    records=records)

So to present the info to a human:
In [18]: print e
Bad record detected in {'a': 12, 'b': 123}
and other code can use:
In [19]: e.error
Out[19]: 1
and access the relevant varaibles like:
In [20]: e.kwargs
Out[20]: {'records': {'a': 12, 'b': 123}}