cipherdyne.org

Security Researcher



Site Update - WordPress Theme without Running WordPress

WordPress site WordPress has a loyal following in the blogosphere and is used to power thousands of websites and blogs, and several books have been written about it. A compelling measure of WordPress popularity is the number of downloadable themes that can provide an easily deployed and consistent look and feel to WordPress sites. So, when I was looking to update the presentation of the cipherdyne.org site, it seemed a natural step to consider a WordPress theme.
I've updated cipherdyne.org to use a slightly modified version of the Daleri Selection (v1.0) Theme by Andreas Viklund, but with a twist: I don't run actually Word Press. All of that PHP code and MySQL database backend is throwing a lot of complex code (and associated potential security vulnerabilities) at a problem that (in my case) can be solved in a simpler way. That is, I just want to provide an outlet for my software and publications, and maintain a blog for my corner of the security technology landscape. For this, I just need a themed website in plain HTML and CSS along with RSS and Atom feeds, and I need an effective way to manage all of the pages and create new blog posts. This is where perl, rsync, and subversion comes in.
The cipherdyne.org website and blog is managed by a set of custom perl scripts that perform each the following tasks:
  • Provide a way to create new blog posts and link them into the cipherdyne.org blog hierarchy. For example, the forward and backward links at the end of each post (such as this one) are auto-generated based on the posting date, and the permanent blog links are created from each post by the blog post title. The number of blog posts is summarized by date and organized into categories that can be browsed via the blog archives, and updates to the RSS and Atom feeds are automatically generated.
  • Validate HTML and XML page structure. This is exceeding easy through the use of the perl XML::Simple module. But, using the W3C HTML validator is more thorough, so I periodically use it as well to spot check various pages on cipherdyne.org.
  • Validate software release MD5 digests and GnuPG signatures (see the fwknop download page for example), and automatically correct if any digest is invalid.
  • Search through the entire cipherdyne.org website and flag any broken links (parsing the output of a recursive wget against the cipherdyne.org staging server make this easy).
  • Send blog pings out via the XMLRPC::Lite module to various blog aggregation services such as FeedBurner and Technorati.
  • Drive the entire cipherdyne.org site via Subversion for source control, and deploy with rsync to separate staging and production servers. When it comes to deploying a more complex piece of software for visualizing changes to the source code for any of the cipherdyne.org projects, my first choice is Trac, but when it comes to the main cipherdyne.org site, a set of HTML pages maintained by a consistent WordPress theme is sufficient.

Hakin9 March 2008 Issue

Hakin9 March 2008 Issue The March issue of Hakin9 Magazine contains some noteworthy articles and interviews. First is an article written by Ryan Maple entitled "Best Practices for Secure Shell" which discusses various security measures that an administrator can use to heighten the security of SSH. These measures include (among others) forcing the usage of SSH protocol version 2, restricting the address (via the ListenAddress variable) that SSHD binds to from the default of 0.0.0.0, using tcpwrappers, and configuring SSHD to listen on a port other than tcp/22. Covering Single Packet Authorization would have been difficult to include in the same article, but a reference is made to another online article Knock, Knock, Knockin' on EnGarde's Door (with FWKNOP) that does discuss protecting SSH with SPA. Next, is Matt Jonkman's fifth part in his series "Writing IPS Rules". This article covers the byte_test keyword in the Snort rules language and how to use it to write signatures against length encoded protocols. In particular, Matt illustrates using byte_test to look for specific byte values at particular offsets derived from data within the DHCP protocol. The offsets themselves are determined by the data on the wire and therefore cannot simply be hard coded within a signature beforehand. For those who are interested in the latest IDS signatures from Matt, he has updated the online home of the Bleeding Edge Snort ruleset to Emerging Threats. Finally, both Marcus Ranum and Richard Bejtlich were interviewed for the March issue. I would like to see Hakin9 do a more in-depth interview of Bejtlich though since he always has an insightful perspective on computer security - particularly as demonstrated in his book The Tao of Network Security Monitoring.

fwknop Windows UI Update

Sean Greven has released the next version of his fwknop UI for Windows systems. This release is compatible with all fwknop daemons that are configured to accept SPA packets that have been encrypted with the Rijndael symmetric cipher. The executable can be downloaded here, and the source code is also available here. Finally, here is a screenshot to illustrate generating an SPA packet from Windows 2000 running under VMware on an Ubuntu 7.10 system. The fwknopd daemon is running in --debug mode in the terminal on the right, and you can see the addition of an iptables ACCEPT rule to allow access to SSHD:

fwknop Window UI update

Port Forwarding via Single Packet Authorization

Digg How to Safely Connect to Your Closed Internal Systems via SPA and NAT Port Forwarding via Single Packet Authorization Most port knocking or Single Packet Authorization implementations offer the ability to passively authenticate clients for access only to a locally running server (such as SSHD). That is, the daemon that monitors a firewall log or that sniffs the wire for port knock sequences or SPA packets can only reconfigure a local firewall to allow the client to access a local socket. This is usually accomplished by allowing the client to connect to the server port by putting an ACCEPT rule in the INPUT chain for iptables firewalls, or adding a pass rule for ipfw firewalls for the client source IP address. For local servers, this works well enough, but suppose that you ultimately want to access an SSH daemon that is running on an internal system? If the SPA software is deployed on a Linux gateway that is protecting a non-routable internal network and has a routable external IP address, it is inconvenient to first have to login to the gateway and then login to the internal system.
       Since the 1.9.2 release, fwknop has supported the creation of inbound port forwarding rules for iptables firewalls via the DNAT target in the PREROUTING chain after receiving a valid SPA packet. This allows direct access to internal systems on non-routable address space from the open Internet. Here is an example - suppose that you are running fwknop on Linux gateway system that is protecting an internal network 192.168.10.0/24 and has an external routable address of 11.1.1.1. Now, suppose that you are on travel somewhere (so your source IP address is not predictable), and you would like to access an SSH server that is running on the internal system 192.168.10.23. Finally, because fwknop is deployed, iptables is configured in a default-DROP stance against all attempts to connect with any SSH daemon; nmap cannot even tell that there is any SSH server listening. Access is granted only after a valid SPA packet is passively sniffed by the fwknopd daemon.

With inbound NAT support configured in fwknop (the config is mentioned below), here is an illustration of fwknop usage in order to gain direct access to SSHD on the 192.168.10.23 from an external network (note that the -R argument instructs the fwknop client to automatically resolve the current IP address - 12.2.2.2 in this case):
[externalhost]$ fwknop -A tcp/22 --Forward-access 192.168.10.23,5001 \
-R -D 11.1.1.1

[+] Starting fwknop client (SPA mode)...
    Resolving external IP via: http://www.whatismyip.org/
    Got external address: 12.2.2.2

[+] Enter an encryption key. This key must match a key in the file
    /etc/fwknop/access.conf on the remote system.

Encryption Key:

[+] Building encrypted Single Packet Authorization (SPA) message...
[+] Packet fields:

        Random data:    6862733471944039
        Username:       root
        Timestamp:      1207404612
        Version:        1.9.3
        Type:           2 (FORWARD access mode)
        Access:         12.2.2.2,tcp/22
        Forward access: 192.168.10.23,5001
        SHA256 digest:  hE4zGafLtQiQiFrep+cSq/wVO7SQhwh65hmLr+ehtrw

[+] Sending 206 byte message to 11.1.1.1 over udp/62201...
Now, port 5001 on the external IP address is forwarded through to the SSH server on the internal 192.168.10.23 system, but only for the client IP 12.2.2.2:
[externalhost]$ ssh -p 5001 mbr@11.1.1.1
Password:
[internalhost]$
Graphically, this scenario is illustrated by the following picture. The dotted lines represent the SPA packet from the fwknop client (which only needs to be sniffed by the fwknopd daemon running on the Linux gateway), and the solid arrows represent the SSH connection from the external client through to the internal SSH server.

DNAT SPA access to internal SPA server
On the Linux gateway system that is running the fwknop daemon, executing the following command illustrates the additions to the iptables policy to allow the SSH connection to be forwarded to the internal system. These firewall rules are automatically deleted after a 30 second timeout (this is tunable), but any existing SSH connection remains open through the use of the iptables connection tracking capability.
[gateway]# fwknopd --fw-list
[+] Listing rules in fwknop chains...
Chain FWKNOP_INPUT (1 references)
 pkts bytes target prot opt in out source   destination

Chain FWKNOP_FORWARD (1 references)
 pkts bytes target prot opt in out source     destination
   19  2740 ACCEPT tcp  --  *  *   12.2.2.2   0.0.0.0/0    tcp dpt:22

Chain FWKNOP_PREROUTING (1 references)
 pkts bytes target prot opt in out source     destination
    1    60 DNAT   tcp  --  *  *   12.2.2.2   0.0.0.0/0    tcp \
dpt:5001 to:192.168.10.23:22
Finally, the /etc/fwknop/access.conf is configured like so to facilitate this example, and the ENABLE_IPT_FORWARDING variable is also enabled in the /etc/fwknop/fwknop.conf file:
SOURCE: ANY;
OPEN_PORTS: tcp/22;
PERMIT_CLIENT_PORTS: N;
ENABLE_FORWARD_ACCESS: Y;
FW_ACCESS_TIMEOUT: 30;
KEY: aesdemokey;
In addition to explaining the inbound NAT support offered by fwknop, this blog post also announces the 1.9.3 release of fwknop. Here is the complete ChangeLog:
  • Added MASQUERADE and SNAT support to complement inbound DNAT connections for SPA packets that request --Forward-access to internal systems. This functionality is only enabled when both ENABLE_IPT_FORWARDING and ENABLE_IPT_SNAT are set, and is configured by two new variables IPT_MASQUERADE_ACCESS and IPT_SNAT_ACCESS which define the iptables interface to creating SNAT rules. The SNAT supplements of DNAT rules are not usually necessary because internal systems usually have a route back out to the Internet, but this feature accommodates those systems that do not have such a route. By default, the MASQUERADE target is used if ENABLE_IPT_SNAT is enabled because this means that the external IP does not have to be manually defined. However, the external IP can be defined by the SNAT_TRANSLATE_IP variable.
  • Added hex_dump() feature for fwknop client so that raw encrypted SPA packet data can be displayed in --verbose mode.
  • When ENABLE_IPT_FORWARDING is set, added a check for the value of the /proc/sys/net/ipv4/ip_forward file to ensure that the local system allows packets to be forwarded. Unless ENABLE_PROC_IP_FORWARD is disabled, then fwknopd will automatically set the ip_forward file to "1" if it is set to "0" (again, only if ENABLE_IPT_FORWARDING is enabled).
  • Minor bugfix to remove sys_log() call in legacy port knocking mode.
  • Minor bugfix to expand both the Id and Revision tags via the svn:keywords directive.

Software Release - gpgdir-1.8

Software Release - gpgdir-1.8 The 1.8 release of gpgdir is ready for download. This is a minor feature enhancement release, and here is the Here is the complete ChangeLog:
  • Updated the test suite to validate the gpgdir --Obfuscate-filenames mode to ensure that files are encrypted as "gpgdir_<pid>_<num>.gpg".
  • Minor bug fix to remove the .gpgdir_map_file in --Obfuscate-filenames mode after a successful decryption cycle.
  • Updated to version 0.36 of CPAN GnuPG::Interface module.

Software Release - psad-2.1.2

Software Release - psad-2.1.2 The 2.1.2 release of psad is ready for download. This is a minor bugfix release to improve support for Linux distributions that report a timestamp in syslog messages just before any iptables log prefix. Here is an example of such syslog messages reported in "psad --Status output (sent to the psad mailing list by Erik Heidt):
[+] iptables log prefix counters:
      "[ 5370.901768] Default_Drop________": 1
      "[ 9411.899552] Default_Drop________": 1
      "[ 7560.529042] Default_Drop________": 1
      "[ 6454.263813] Default_Drop________": 1
      "[ 7038.635371] Default_Drop________": 1
      "[ 5648.026038] Default_Drop________": 1
      "[ 1207.663709] Default_Drop________": 1
      "[  394.423573] Default_Drop________": 1
      "[  186.740237] Default_Drop________": 1
      "[ 9405.138521] Default_Drop________": 1
      "[ 5364.208693] Default_Drop________": 1
      "[ 7297.121141] Default_Drop________": 1
The bug caused the timestamp portion of the syslog messages to be included within the iptables log prefix strings, and because timestamps are nearly unique, this forced even the same iptables log prefix to also be treated as unique.
Here is the complete ChangeLog:
  • Bugfix to not include kernel timestamps in iptables log prefixes that contain spaces like "[ 65.026008] DROP" (bug reported by Erik Heidt).
  • Bugfix to skip non-resolved IP addresses (bug reported by Albert Whale)
  • Better p0f output in --debug mode to display when a passive OS fingerprint cannot be calculated based on iptables log messages that include tcp options (i.e., with --log-tcp-options when building a LOG rule on the iptables command line).

IDS signature matching with iptables, psad, and fwsnort

IDS signature matching with iptables, psad, and fwsnort The UK's Unix & Open Systems User Group has re-printed an article I wrote originally for the December, 2007 security issue of USENIX ;login: Magazine The article is entitled "IDS signature matching with iptables, psad, and fwsnort" and concentrates on how to use the iptables infrastructure in the Linux kernel as a source of intrusion detection data. That is, iptables offers many features (such as application layer string matching) that allow a significant fraction of Snort rules to be converted into iptables rules, and fwsnort automates the conversion process. The end result is an iptables policy that is looking for evidence of malicious traffic. Also covered in the article is the concept of log analysis with an emphasis on passive OS fingerprinting. The completeness of the iptables logging format - which even includes the options portion of the TCP header when the --log-tcp-options argument is given on the iptables command line when building a LOG rule - allows psad to run the same algorithm that p0f uses to passively fingerprint remote operating systems.

In other news, Carla Schroder has written an article on psad for Enterprise Networking Planet. She recommends running psad alongside Snort, which falls nicely within the principle of defense-in-depth in order to maintain a strong defensive stance. Also, Noah Schiffman has written an article on port knocking for Network World. He mentions the usage of port knocking within some malware applications as an authentication mechanism, and he also touches on Single Packet Authorization.

SOURCE Boston Advanced Linux Firewalls Talk Slides

SOURCE Boston Advanced Linux Firewalls Talk Slides At the SOURCE Boston conference in Boston last week I gave talk entitled "Advanced Linux Firewalls" (slides). The conference attendance was good considering that this is the first year the conference was offered, and I look forward to next year. I managed to see a few talks, and two that stood out from the crowd were Roger Dingledine's talk "How To Make Tor Play Well With The Rest Of The Internet", and Andrew Jaquith's talk "Not Dead But Twitching: Anti-Virus Succumbs to the Scourge of Modern Malware". Roger highlighted several technology research and development areas for the Tor project, including the ability to use UDP instead of TCP for Tor virtual circuits. This is of particular interest to me, since it would mean that SPA packets could be routed over the Tor network without having to resort to the establishment of full TCP connections (which breaks the "single packet" part of "SPA"). Andrew gave some interesting perspectives on malware trends, including the fact that malware over time is becoming more targeted while at the same time exhibiting high variability. The end result is that malware authors are able to attack the weakest link in the creation of signatures for malware detection - the people that reverse engineer malware. Because human resources are scarce and slow when it comes to reverse engineering (there is no fully automated mechanism for this yet), malware authors are able to essentially perpetrate a DoS against vendors that offer malware detection.

fwknop-1.9.2 Release at SOURCE Boston

fwknop-1.9.2 Release at SOURCE Boston Today at the SOURCE Boston computer security conference I will give a talk entitled "Advanced Linux Firewalls" in which I will present many of the themes I discuss in my book published late last year by No Starch Press. This talk will also launch the 1.9.2 release of fwknop, and present several new features such as client-derived access timeouts, the ability to select any of several digest algorithms (SHA-256, SHA-1, or MD5) for replay attack detection, the removal of the Salted__ prefix in SPA packets encrypted with Rijndael, and blacklist IP exclusions for incoming SPA packets. Many of these features were implemented by the SPAPICT team as well as several other contributors, and I wish to thank all who participated in the fwknop development process.

      You can download fwknop-1.9.2 here, and for those interested in the changes in the fwknop-1.9.2 release, here is the complete ChangeLog:
  • Crypt::CBC adds the string "Salted__" to the beginning of the encrypted text (at least for how fwknop interfaces with Crypt::CBC), so the fwknop client was updated to delete the encoded version of this string "U2FsdGVkX1" before sending a Rijndael-encrypted SPA packet on the wire. The fwknopd server will add this string back in before decrypting. This makes it harder to write an IDS signature that looks for fwknop traffic; e.g. look for the default prefix string "U2FsdGVkX1" over UDP port 62201, which would work for fwknop clients < 1.9.2 (as long as the port number is not changed with --Server-port).
  • Added more granular source IP and allowed IP tests so that access to particular internal IP addresses can be excluded in --Forward-access mode. A new keyword "INTERNAL_NET_ACCESS" is now parsed from the access.conf file in order to implemented these restrictions.
  • (SPAPICT Group) Added BLACKLIST functionality to allow source IP addresses to easily be excluded from the authentication process.
  • (Grant Ferley) Submitted patch to handle SIGCHLD in IPTables::ChainMgr.
  • (Grant Ferley) Submitted patch to handle Linux "cooked" interfaces for packet capture (e.g. PPPoE interfaces).
  • (SPAPICT Group) Applied modified version of the client-defined access timeout patches submitted by the PICT SPA Group. There are two new message types to facilitate client timeouts; one for normal access mode, and the other for the FORWARD access mode. In the access.conf file, there is also a new variable "PERMIT_CLIENT_TIMEOUT" to allow each SOURCE stanza to allow client-defined timeouts or not.
  • (SPAPICT Group) Submitted patches to include support for the SHA1 digest algorithm for SPA packet replay attack detection. I modified these patches for maximum configurability (see the --digest-alg argument on the fwknop command line), and the ability to use the SHA256 algorithm as well. The default path to the /var/log/fwknop/md5sums file has been changed to /var/log/fwknop/digest.cache, and the default digest algorithm is now SHA256 (but this is tunable via the DIGEST_TYPE variable in the fwknop.conf file).
  • Added the Digest::SHA perl module in support of the SHA1 and SHA256 digest algorithms for replay attack detection and SPA message integrity.
  • Added full packet hex dumps (including packet headers) to fwknopd in --debug --verbose mode. This is to help diagnose packet sniffing issues over the loopback interface on Mac OS X (first reported by Sebastien Jeanquier).
  • (Test suite) Bugfix to ensure that the FWKNOP_DIR variable is set to the local output/ directory in several of the test config files in the test/conf/ directory.
  • (Test suite) Added several tests for configurable digest algorithms in support for the SHA256, SHA1, and MD5 digest changes made by the SPAPICT Group.
  • Updated the fwknop client to always call encode_base64() with the string to encode along with a second null-string argument to force all encoded data to not include line breaks.
  • Bugfix in install.pl to not test for the iptable command on non-Linux systems, and to not test for the ipfw command on systems that are Linux.
  • (Test suite) Updated to include the /proc/config.gz file so that the kernel config can be reviewed (not all Netfilter hooks are necessarily compiled in).

Thwarting Distributed SSH Brute Force Attempts

Thwarting Distributed SSH Brute Force Attempts The SANS Internet Storm Center has an interesting diary entry that discusses a set of distributed brute force attempts against SSHD originating from a specific Class C subnet 58.147.10.0/24. According to the diary entry, a random selection of IP addresses within this subnet (which is owned by an organization in Thailand) are probing for listening SSH daemons on the open Internet, but each IP address is limiting the number of probes to two. Presumably this is to fly beneath the radar of any threshold-based detection mechanisms that might automatically block the attempts to communicate with SSHD.
     After rummaging around in my iptables logfiles, I noticed the following two log entries that show exactly two SYN packets from the IP 58.147.10.209 and destined for one of my systems:
Jun  3 14:55:06 minastirith kernel: DROP IN=eth0 OUT= \
MAC=00:13:d3:38:b6:e4:00:90:1a:a0:1c:ec:08:00 SRC=58.147.10.209 DST=71.N.N.N LEN=60 \
TOS=0x00 PREC=0x00 TTL=44 ID=11651 DF PROTO=TCP SPT=57473 DPT=22 WINDOW=5840 RES=0x00 \
SYN URGP=0 OPT (020405780402080A7CCF5BC50000000001030302)
Jun  3 14:55:09 minastirith kernel: DROP IN=eth0 OUT= \
MAC=00:13:d3:38:b6:e4:00:90:1a:a0:1c:ec:08:00 SRC=58.147.10.209 DST=71.N.N.N LEN=60 \
TOS=0x00 PREC=0x00 TTL=44 ID=11653 DF PROTO=TCP SPT=57473 DPT=22 WINDOW=5840 RES=0x00 \
SYN URGP=0 OPT (020405780402080A7CCF677D0000000001030302)
These two packets date back to June of last year, so the 58.147.10.0/24 network has apparently been active for quite some time. So, beyond the whois information mentioned in the ISC diary entry, can we tell anything more about our friend at 58.147.10.209? Because I always use the --log-tcp-options command line argument when building my iptables LOG rules, we have nice hex dumps included in the log messages above that represent the options portion of the TCP header. Having this information is necessary in order to passively fingerprint the remote TCP stack with p0f. The psad project re-implements the p0f algorithm over iptables log messages - p0f requires raw packet data acquired via libpcap - so what does psad have to say about the remote TCP stack?
[minastirith]# psad -A -m /var/log/messages --restrict-ip 58.147.10.209
[+] p0f(): 58.147.10.209 len: 60, frag_bit: 1, ttl: 44, win: 5840
[+] MSS: 1400, SACK, Timestamp: 2093964229, NOP, Win Scale: 2,
    Could not match 58.147.10.209 against any p0f signature.
Oh well, that is unfortunate. So, p0f does not seem to have a fingerprint that can characterize the remote TCP stack. I also looked through the passive OS fingerprinting database included with the ettercap project, but no luck there either. This was a manual process though because psad does not yet support the format of the fingerprints in ettercap, but this will be supported in the next release.
     In the meantime, the discussion in the diary entry advocates limiting the set of IP addresses that are allowed to talk to the SSH daemon, but ends with a comment stating that this is not always possible. I agree with this comment, and this is highlighted whenever you administer a system and you need access to SSHD from unpredictable source addresses (such as when travel is involved). A robust solution is to deploy Single Packet Authorization with a default-drop packet filter. Why let arbitrary source IP addresses communicate with your SSH daemon?

Software Release - gpgdir-1.7

gpgdir-1.7 released The 1.7 release of gpgdir is ready for download. This release fixes a bug that was introduced in gpgdir-1.6 that caused previously encrypted directories to not be decrypted in --decrypt mode. This bug was reported by Per Ronny Westin, and the result is the addition of a new test suite so that bugs of this type don't creep back into the gpgdir development process. Here is some sample output of the new test suite in action:

[+] ==> Running gpgdir test suite <==

(Setup) gpgdir program compilation..................................pass (0)
(Setup) Command line argument processing............................pass (1)
(Test mode) gpgdir basic test mode..................................pass (2)
(Encrypt dir) gpgdir directory encryption...........................pass (3)
(Encrypt dir) Files recursively encrypted...........................pass (4)
(Encrypt dir) Excluded hidden files/dirs............................pass (5)
(Decrypt dir) gpgdir directory decryption...........................pass (6)
(Decrypt dir) Files recursively decrypted...........................pass (7)
(MD5 digest) match across encrypt/decrypt cycle.....................pass (8)
(Ascii-armor dir) gpgdir directory encryption.......................pass (9)
(Ascii-armor dir) Files recursively encrypted.......................pass (10)
(Ascii-armor dir) Excluded hidden files/dirs........................pass (11)
(Decrypt dir) gpgdir directory decryption...........................pass (12)
(Decrypt dir) Files recursively decrypted...........................pass (13)
(MD5 digest) match across encrypt/decrypt cycle.....................pass (14)

[+] ==> Passed 15/15 tests against gpgdir. <==
[+] This console output has been stored in: test.log

Here is the complete ChangeLog: for the 1.7 release:
  • Bugfix to ensure that encrypted directories can actually be decrypted. This bug was reported by Per Ronny Westin.
  • Updated to use the ".asc" extension for encrypted files in --Plain-ascii mode.
  • Added gpgdir test suite. All future gpgdir releases (and including this 1.7 release) require that all gpgdir tests pass on the systems where gpgdir is developed.

Interfacing VIM with GnuPG Encrypted Files

Digg VIM + GnuPG Interfacing VIM with GnuPG Encrypted Files Over the years the editor I have become the most familiar with is vim. It provides features that allow the software development process to go smoothly, such as split screens, syntax highlighting, integration with cscope tags, function folding, and more. By applying configuration directives to your ~/.vimrc file, you can instruct vim to perform some nice preprocessing functions against files. This blog post illustrates a ~/.vimrc tweak (originally from Wouter Hanegraaff) that allows vim to leverage GnuPG to decrypt a previously encrypted file, allow edits to be made, and then re-encrypted before it is written back to disk. Here is the section of the .vimrc file to allow such transparent encryption and editing:
" Transparent editing of gpg encrypted files.
" By Wouter Hanegraaff <wouter@blub.net>
augroup encrypted
au!
" First make sure nothing is written to ~/.viminfo while editing
" an encrypted file.
autocmd BufReadPre,FileReadPre *.gpg set viminfo=
" We don't want a swap file, as it writes unencrypted data to disk
autocmd BufReadPre,FileReadPre *.gpg set noswapfile
" Switch to binary mode to read the encrypted file
autocmd BufReadPre,FileReadPre *.gpg set bin
autocmd BufReadPre,FileReadPre *.gpg let ch_save = &ch|set ch=2
autocmd BufReadPost,FileReadPost *.gpg '[,']!gpg --decrypt 2> /dev/null
" Switch to normal mode for editing
autocmd BufReadPost,FileReadPost *.gpg set nobin
autocmd BufReadPost,FileReadPost *.gpg let &ch = ch_save|unlet ch_save
autocmd BufReadPost,FileReadPost *.gpg execute ":doautocmd BufReadPost " . expand("%:r")
" Convert all text to encrypted text before writing
autocmd BufWritePre,FileWritePre *.gpg '[,']!gpg --default-recipient-self -ae 2>/dev/null
" Undo the encryption so we are back in the normal text, directly
" after the file has been written.
autocmd BufWritePost,FileWritePost *.gpg u
You can combine this vim tweak with gpgdir to maintain recursively encrypted directories, and just edit the files directly. For example, the following sequence of commands shows the creation of an encrypted file and how vim then interfaces with GnuPG to allow transparent editing:
$ cat > somefile
private data
more private data
$ gpg -e somefile
$ wipe somefile
Okay to WIPE 1 regular file ? (Yes/No) yes
Operation finished.
1 file wiped and 0 special files ignored in 0 directories, 0 symlinks removed \
but not followed, 0 errors occured.
$ ls -l somefile.gpg
-rw-r--r-- 1 mbr mbr 618 2008-02-17 01:52 somefile.gpg
$ vim somefile.gpg
"somefile.gpg" [noeol] 3L, 618C

You need a passphrase to unlock the secret key for
user: "Michael Rash <mbr@cipherdyne.org>"
2048-bit ELG-E key, ID 1234ABCD, created 2007-05-01 (main key ID ABCD1234)

Enter passphrase:

<apply edits now, and hit :wq >

$ ls -l somefile.gpg
-rw-r--r-- 1 mbr mbr 932 2008-02-17 01:55 somefile.gpg
As you can see from the output above, the file was modified (and the original file somefile was deleted using wipe).

Finally, the 1.6 (UPDATE: actually, the 1.7 release is available as of 02/18/2008) release of gpgdir is ready for download. This is a bugfix release that restores the exclusion of previously encrypted files from the file selection process, and includes a few minor install.pl enhancements as well. Here is the ChangeLog:
  • Bugfix to not include previously encrypted files (i.e. those with a .gpg extension) in the encryption/decryption file list. This bug was introduced in gpgdir-1.5 when a change was made to ignore ascii-armored files.
  • Added added LC_ALL=C locale setting for the install.pl script (this should help to ensure gpgdir is properly installed on most systems). Two new command line arguments --LC_ALL and --no-LC_ALL also allow the locale setting to be changed or not used at all.
  • Added --Exclude-mod-regex option to the install.pl script so that it is possible to force the exclusion of perl modules that gpgdir would normally install. This is useful for ensuring that gpgdir references perl modules that are already installed in the system perl library tree instead of using those that are installed in /usr/lib/gpgdir.
  • Updated to display command line usage warnings without automatically displaying the entire usage() page (which is quite long).

Deploying the Trac Timeline and Browse Source Features

Deploying the Trac Timeline and Browse Source Features The Trac Project provides an excellent web interface for project documentation, ticket-based project management, and visualization of source code (from a Subversion repository). All of the Cipherdyne open source projects use Trac as the code display mechanism, and allow users to readily see how the projects are developed over time. However, the Cipherdyne projects are not large software engineering efforts with many dedicated developers, and I prefer not to allow my webserver to accept user registrations and tickets even if it is through Trac. The project mailing lists as well as personal email correspondence has been (so far) completely sufficient for bug reporting, and development tasks are tracked within TODO files in each of the top level source directories for each project. Trac also offers a Wiki, but I write all of my own documentation for my projects and I accept enhancements via email as well.

So, why the blog post? Well, it is not immediately obvious how to enable just the Timeline, Browse Source, and Search features in Trac, and disable the remaining features such as the Roadmap, Tickets, and the Wiki. (All of these features can be seen in the Trac site in the navigation bar off to the right.) It turns out that Trac is database driven, and disabling these features can be accomplished from the command line as follows with the trac-admin command:
$ trac-admin /path/to/trac_directory permission remove anonymous TICKET_CREATE \
TICKET_MODIFY TICKET_VIEW ROADMAP_VIEW REPORT_VIEW MILESTONE_VIEW REPORT_SQL_VIEW \
WIKI_CREATE WIKI_MODIFY WIKI_VIEW
Also, you will need to set the default_handler variable in the conf/trac.ini file to BrowserModule instead of WikiModule. Using the above command, the Trac navigation bar only includes the Timeline, Browse Source, and Search features as seen here, and this is a valuable configuration for small open source projects. However, if you would like additional functionality in Trac to be enabled for the Cipherdyne projects please email me; perhaps there are benefits here that would justify the change.

Software Release - fwknop-1.9.1

fwknop-1.9.1 release The 1.9.1 release of fwknop is ready for download. This release focuses on better installation support for platforms such as Ubuntu 7.10 and Fedora 8, and also includes many enhancements to the fwknop test suite. The test suite is up to over 80 tests on Linux systems now, and includes verbose output that can help to troubleshoot any fwknop installation. Here is an excerpt from one of the symmetric key tests against the loopback interface which uses the fwknop packet hex dump feature:
Sat Jan 26 14:33:03 2008     Raw packet data (hex dump, minus packet headers):
        0x0000:  5532 4673 6447 566b 5831 2f46 7867 764e  U2FsdGVkX1/FxgvN
        0x0010:  2f7a 516e 626b 6e74 6943 7638 464b 3543  /zQnbkntiCv8FK5C
        0x0020:  6f6c 7a48 7268 3835 6f77 5a71 5075 4444  olzHrh85owZqPuDD
        0x0030:  4133 512f 6133 6b75 392b 6f58 7177 7748  A3Q/a3ku9+oXqwwH
        0x0040:  6450 7250 6933 4d2f 5278 556d 4e70 7833  dPrPi3M/RxUmNpx3
        0x0050:  6477 3942 6f36 5345 7542 4a50 306d 4630  dw9Bo6SEuBJP0mF0
        0x0060:  476a 5a49 5267 736f 6a37 4769 582b 7344  GjZIRgsoj7GiX+sD
        0x0070:  306a 6446 6d7a 7744 7154 3951 7976 4f65  0jdFmzwDqT9QyvOe
        0x0080:  3765 736d 7855 6a69 7049 5a42 5765 6f67  7esmxUjipIZBWeog
        0x0090:  6f45 6a4d 3744 6f50 5338 7469 7874 4f78  oEjM7DoPS8tixtOx
        0x00a0:  4c33 6457 7275 4f6f 6448 55              L3dWruOodHU
Sat Jan 26 14:33:03 2008 [+] Packet from 127.0.0.1 matched SOURCE: ANY (line 15)
Sat Jan 26 14:33:03 2008 SOURCE block: 0
REQUIRE_SOURCE_ADDRESS: 1
PERMIT_CLIENT_PORTS: 0
OPEN_PORTS:
$VAR1 = {
          'tcp' => {
                     '22' => ''
                   }
        };
REQUIRE_USERNAME: root
CMD_REGEX: (?-xism:echo)
KEY: (removed)
ENABLE_CMD_EXEC: 1
TYPE: any
DATA_COLLECT_MODE: 0
FW_ACCESS_TIMEOUT: 5
SOURCE: ANY
Sat Jan 26 14:33:03 2008 [+] Attempting Rijndael decrypt...
Sat Jan 26 14:33:03 2008     Decrypting raw data (hex dump):
        0x0000:  5361 6c74 6564 5f5f c5c6 0bcd ff34 276e  Salted__.....4'n
        0x0010:  49ed 882b fc14 ae42 a25c c7ae 1f39 a306  I..+...B.\...9..
        0x0020:  6a3e e0c3 0374 3f6b 792e f7ea 17ab 0c07  j>...t?ky.......
        0x0030:  74fa cf8b 733f 4715 2636 9c77 770f 41a3  t...s?G.&6.ww.A.
        0x0040:  a484 b812 4fd2 6174 1a36 4846 0b28 8fb1  ....O.at.6HF.(..
        0x0050:  a25f eb03 d237 459b 3c03 a93f 50ca f39e  ._...7E.<..?P...
        0x0060:  edeb 26c5 48e2 a486 4159 ea20 a048 ccec  ..&.H...AY. .H..
        0x0070:  3a0f 4bcb 62c6 d3b1 2f77 56ae e3a8 7475  :.K.b.../wV...tu
    Salt:
        0x0000:  c5c6 0bcd ff34 276e                      .....4'n
    Key:
        0x0000:  9087 692c 0d84 a24b a802 9b30 550e 6031  ..i,...K...0U.`1
        0x0010:  3121 f532 7404 b2af a863 653f 6d6b 7dab  1!.2t....ce?mk}.
    IV:
        0x0000:  3ba9 7bda d3ac 0ae3 2a75 288e a791 6f0d  ;.{.....*u(...o.
    PassPhrase:
        0x0000:  6677 6b6e 6f70 7465 7374 3030 3030 3030  fwknoptest000000
    Block Size: 16
    Key Size:   32

Sat Jan 26 14:33:03 2008 [+] Decrypted message: 2729686373650157:cm9vdA== \
:1201375981:1.9.1:1:MTI3LjAuMC4yLHRjcC8yMg==:5v0x5MwZ8I9AUyvriRQ7Ug
For those interested in the changes in the fwknop-1.9.1 release, here is the complete ChangeLog:
  • Added ENABLE_OUTPUT_ACCESS keyword to access.conf file parsing. This provides a similar configuration gate for the iptables OUTPUT chain to the ENABLE_FORWARD_ACCESS keyword, and adds the abiliy to control which access.conf SOURCE blocks interface to the OUTPUT chain.
  • Better installation support for various Linux distributions including Fedora 8 and Ubuntu. The current runlevel is now acquired via the "runlevel" command instead of attempting to read /etc/inittab (which does not even exist on Ubuntu 7.10), and there are new command line arguments --init-dir, --init-name, and --runlevel to allow the init directory, init script name, and the runlevel to be manually specified on the install.pl command line.
  • Added command line argument display to fwknop client --verbose mode.
  • Updated the test suite to include OUTPUT chain tests, reference access.conf files in the test/conf/ directory, and perform SPA packet format validation tests by parsing fwknopd output.
  • Updated fwknopd to use always use the -c argument on the knoptm command line (this makes sure that the test suite usage of fwknopd causes knoptm to reference the correct configuration).
  • Updated IPTables::ChainMgr to print iptables command output to stdout or stderr if running in debug or verbose mode.
  • Added --Exclude-mod-regex to install.pl so that the installation of particular perl modules that match the supplied regex can be skipped.
  • Added SIGALRM wrapper to the test suite since some libpcap and system combinations break the ability of fwknopd to sniff packets.
  • Added srand() call to the fwknop client (this is useful for older versions of perl which do not automatically call srand() at the first rand() call if srand() was not already called).
  • Added a test to the test suite for sniffing packets over the loopback interface.
  • Added SPA packet aging test to the test suite to ensure that packet expirations work properly (this feature protects against MITM attacks where a valid SPA packet is stopped by an inline attacker and retransmitted at a later time to acquire access).
  • Added a file (test.log) to collect test suite console output.
  • Added --Prepare-results argument to test suite to anonymize test results and create a tarball that can be emailed to a third party to assist in debugging.
  • Added full firewall policy dumps and the collection of system specifics to the test suite. This makes it easy to send the output directory and the test.log file to developers to assist in debugging (no information is sent anywhere except as part of a manual process of course, and addresses can be anonymized with --Prepare-results - loopback addresses are not modified).
  • Added --fw-del-ip <IP> argument to fwknopd so that a specific IP address can be removed from the local firewall policy (this is used by the test suite to ensure that if a test for removed firewall rules fails then subsequent tests will not also fail because they are no longer tracked by a running knoptm instance).
  • Added a test to the test suite to collect fwknopd syslog output. This is useful to see if a mechanism such as SELinux is deployed in a manner that prevents normal fwknop communications.
  • Bugfix to track MD5 digest for SPA command mode packets.
  • Bugfix in fwknopd to not open ports listed in OPEN_PORTS in the absence of the PERMIT_CLIENT_PORTS directive when an SPA packet contains a request for access to a port not listed in OPEN_PORTS. debugging fwknop if there are any issues.
  • Added --verbose flag to fwknopd commands issued by the test suite so that more data is collected for debugging analysis.
  • Added GnuPG tests to the test suite with dedicated keys (for use only with the test suite) in the test/conf/client-gpg and test/conf/server-gpg directories.
  • Added digest file validation to test suite to make sure that fwknopd correctly tracks SPA packet MD5 digests.
  • Updated to search state tracking rule in any iptables chain (many iptables policies have user-defined chains that can be a bit complicated to parse).
  • Updated install.pl to be more strict in stopping any running fwknopd processes.

RPM and a perl.req Heredoc Bug

RPM and a perl.req Heredoc Bug It looks like the Redhat Package Manager has a bug that in some corner cases where the dependencies of a perl program are not properly resolved. This happens whenever the perl program contains a particularly formatted embedded heredoc where a line within the heredoc text section begins with either the word use or require and is followed by any other word. Both "use" and "require" happen to be perl import statements, and the /usr/lib/rpm/perl.req script bundled with the RPM software does not make an exception for usages of these words within heredoc text. The end result is that whatever word follows either "use" or "require" is interpreted as a module dependency.

Here is an example of a heredoc section within a perl program that exposes the RPM dependency bug with line numbers included (this is derived from a modified version of the usage() text in the psad project, but please note that this has been fixed in psad; the example is just to show how to reproduce the bug):
1    print <<_HELP_;
2
3 psad: the Port Scan Attack Detector
4
5 Usage: psad [options]
6
7   --packets <number>      - Specify number of packets to
8                                   use in benchmark test (default is
9                                   10,000).
10  -U,  --USR1                   - Send a running psad process a USR1
11                                  signal (generates a dump of psad
12                                  data structures on STDOUT).
13
14 _HELP_
Note on line 8 above, the line begins with "use in benchmark" (ignoring the line number and the whitespace). The word after "use" is "in", and this is interpreted as a dependency by perl.req as illustrated below when trying to install an RPM out of psad with the heredoc text section above:
[/usr/src/redhat/RPMS/i386]# rpm -ivvh psad-2.1.1-1.i386.rpm
D: package psad-2.1.1-1.i386 has unsatisfied Requires: perl(in)
D:  Requires: perl(strict)                                  YES (db provides)
D:  Requires: perl(vars)                                    YES (db provides)
D:  Requires: perl(warnings)                                YES (db provides)
D:  Requires: rpmlib(CompressedFileNames) <= 3.0.4-1        YES (rpmlib provides)
D:  Requires: rpmlib(PayloadFilesHavePrefix) <= 4.0-1       YES (rpmlib provides)
D:  Requires: rpmlib(VersionedDependencies) <= 3.0.3-1      YES (rpmlib provides)
D:  Requires: rtld(GNU_HASH)                                YES (db provides)
D: opening  db index       /var/lib/rpm/Conflictname rdonly mode=0x0
D: closed   db index       /var/lib/rpm/Pubkeys
D: closed   db index       /var/lib/rpm/Depends
D: closed   db index       /var/lib/rpm/Conflictname
D: closed   db index       /var/lib/rpm/Providename
D: closed   db index       /var/lib/rpm/Basenames
D: closed   db index       /var/lib/rpm/Packages
D: closed   db environment /var/lib/rpm/Packages
error: Failed dependencies:
        perl(in) is needed by psad-2.1.1-1.i386
There is no "in" module, so it's no wonder the RPM installation fails. Unfortunately, this problem does not manifest itself when an RPM is built - only when it is installed.

The heredoc functionality is handy in perl, and allows a multi-line block of text to be faithfully reproduced without having to specify syntactic details such as newline characters in normal print statements. With a bug such as illustrated above, it can be hard to track down why certain RPM's do not install properly since heredoc text can be complex and verbose. It is usually easy to restructure the text so that neither "use" nor "require" begin a line, but only if you know that is the fundamental source of the problem.

Chances are that the RPM maintainers are already aware of this bug, but I will submit it to be sure that it hasn't slipped through the cracks.