Thursday, 5 November 2009

introducing htrosbif

htrosbif - Active HTTP server fingerprinting and recon tool

What does it do?

knan@viconia:~/ak-git/htrosbif.git$ ./htrosbif http://localhost:8525/
Match (1200/1200): pound-2.4.5.sig => jetty-4.2.19.sig
Match (1193/1200): pound-2.4.5.sig => jetty-4.2.24.sig
Match (1076/1200): pound-2.4.5.sig => jetty-4.0.6.sig
Match (1042/1200): pound-2.4.5.sig => jetty-4.1.4.sig
Match (1039/1200): pound-2.4.5.sig => apache-1.2.6-php3-used.sig
Match (1033/1200): pound-2.4.5.sig => jetty-3.1.8.sig
Match (1010/1200): pound-2.4.5.sig => jetty-3.0.6.sig
Match (1000/1200): pound-2.4.5.sig => tomcat-4.1.40-oldconnector.sig
Match (1000/1200): pound-2.4.5.sig => tomcat-5.0.30.sig
Match (1000/1200): pound-2.4.5.sig => apache-2.2.13-php-5.3.0-used.sig

Does a bit of Recon by Fire, if you will. Prods the web server in all sorts of old, new, basic, fancy, spec-compliant and spec-breaking ways. Tries to characterise both the well-spoken educated responses and the seriously deviant babble it receives in return. Signatures contain no user data, only header names and http-level quirks. A few dozen sacrifical test installs of servers ancient (cern, 1993) and new have survived its tentacles.

As a (very) useful side effect, might detect reverse proxies, http load balancers, intrusion prevention systems and web application firewalls.

Cool! Download?


$ git clone


GPL v3.

Alpha, huh?

Yup. Signature format(s) are still in flux, and sections of the code are just stubs. But it basically works. Sending me signatures isn't very useful yet. Sending me patches, ideas and comments, however... are extremely welcome @ knan-rosbif at


Because I wanted to see what could be inferred from behaviour alone.

HTTP load balancers like Pound and HAProxy usually are invisible, ghostly presences, subtly directing traffic and shaping conversations - these touches are detectable, if you think to look.

Replacing a Server: header is trivial effort, mimicking protocol handling quirks much less so.

Monday, 2 November 2009

Bad karma

The 9.10 upgrade losing track of /boot and swap (What, uuid? never seen those uuids anywhere, honest! Wanna buy some slightly used /dev/sda* references? Fell off a truck!) and thus failing to boot was a bit painful.

A bunch of games suddenly growing scratchy/stuttery sound problems not evident in jaunty was more painful. Much debugging ensued.

Wondercure: apt-get remove --purge pulseaudio

... if only all social disorders were as easy to correct.

Tuesday, 6 October 2009

Befuddling web servers for fun

sub test_get_11trailingcrap_knowngood()
# So, does trailing crap after the HTTP/1.1 cause a panic?
# Lots of fun stuff ... some ignore the crap,
# some think "stupid client, must be 1.0, here you go",
# some get confused about the url and return a 404,
# some reject with 400, some spew an error page
# with no headers at all ("stupid 0.9 client, go away")...
# ...and some are just endearingly confused about it all.
# UNKNOWN 400 Bad Request

Wednesday, 23 September 2009

Fingerprinting fun

knan@viconia:~/ak-git/htrosbif.git$ ./htrosbif
Fuzzy match (932/1000): lighttpd-1.5-svn2621.sig
Fuzzy match (797/1000): lighttpd-1.4.23.sig
Fuzzy match (797/1000): lighttpd-1.4.21.sig
Fuzzy match (797/1000): lighttpd-1.4.22.sig
Fuzzy match (683/1000): lighttpd-1.4.17.sig
Fuzzy match (683/1000): lighttpd-1.4.18.sig
Fuzzy match (683/1000): lighttpd-1.4.13.sig
Fuzzy match (683/1000): lighttpd-1.4.19.sig

Monday, 6 July 2009

Hairy stunt #1: firmware update via wine

My shiny new LG GGW-H20L blu-ray/alphabet soup reader/writer happened to need a firmware update. For some reason, many hardware vendors think win32 executables are handy for this sort of thing. I really... don't.

But I got intrigued when several people reported success updating the firmware through wine. Copious amounts of wine can of course make almost anything seem like a good idea, so I bravely give it a try - it will probably brick something in an amusing way, at least.

winetricks mfc42 grabs the usual missing dlls for us. Yet, the firmware updater fails with something on the order of ERROR_SUCCESS in informativeness.

Oh well. Last try: running wine as root.
... and it works. Quickly and perfectly. I don't _think_ I'm hallucinating. More voluptuous hallucinations would be expected in that case.

I suspect the kernel's blk_verify_command kicked in when running as a normal user. Fair enough, you don't necessarily want the backup job user to be able to overwrite the tape drive firmware with zeroes. Or a more-evil-than-usual ransomware virus.

Still, I boggle. And salute fellow Wine contributors. Well done.

Monday, 15 June 2009

ip6tables fun

Note to self. IPv6 connection tracking is a bit eccentric.

Seems that neighbour solicitations are "INVALID" according to conntrack. I.e. IPv6's equivalent of arp requests are invalid ... and dropped if you have a "-m state --state INVALID -j DROP" rule before your accept-various-icmpv6 rules.

This does great things for my host security, obviously.

workaround: put --state INVALID drops after the icmpv6 rules.

Friday, 27 March 2009

OpenVMS cuteness

220 MultiNet FTP Server Process V5.2(16) at Thu 26-Mar-2009 8:19PM-EDT

ftp> site window-size 1073741824
200 TCP window size now 1073741824 bytes

Strangest ftp command competition, anyone?

Tuesday, 10 March 2009

OpenVPN: LDAP and ipset says you may.

Our ad-hoc authorization scheme proceeds. Adding custom schemas to OpenLDAP is pretty easy. (vpnaccess.schema)

ipset lets us define netfilter rules against named, dynamic sets of ips, like:
ipset -N bofhirc iphash
iptables -m set --set bofhirc src -d -p tcp \
-m tcp --dport 22 -j ACCEPT
adds a rule giving only ips added to the bofhirc set access to port 22. How ips are added to that set is up to you (Port knocking, messenger pigeon, ocr on a piece of paper held up in front of a webcam...) but involves ipset -A bofhirc <ip> at some point. And hopefully ipset -D bofhirc <ip> at some other point to revoke that access again. All without disturbing your carefully-tuned iptables config on every login.

A touch of the swiss army chainsaw with Net::LDAP to OpenVPN --client-connect ( and --client-disconnect ( Et voila. Adding accesses is now as easy as adding a named set of firewall rules, and adding:
objectClass: vpnAccessPerson
vpnAccess: bofhirc
to the relevant user in ldap. The ips involved are private and assigned by OpenVPN, so there's no risk of aliasing for multiple users behind a NAT.

Thursday, 5 March 2009

OpenVPN: Hooked!


OpenVPN 2.x provides a bunch of script hooks. Which ones are most useful for authorization?

--up, --down ... mostly used on the client side. Restoring network settings on vpn disconnect with a --down hook, for example. Not suitable.

--route-up ... we don't have the user common_name at this point. Not suitable.

--ipchange ... discouraged in server mode.

--auth-user-pass-verify ... authentication. Too early. The client is untrusted and doesn't have an assigned ip yet.

--tls-verify ... pre-authentication. Too early.

--client-connect, --client-disconnect... straight after authentication, before client-specific config is read. Good enough, if we're a bit careful (i.e. don't change ip address assignments in client-specific config files), and easy to understand triggering conditions. Has all the parameters we need.

--learn-address ... perhaps the architecturally correct place to put it. Somewhat harder to understand the triggering condition. Documented as "Run script or shell command cmd to validate client virtual addresses or routes."

I know, I know, I promised perl hacking here... next time.

Wednesday, 4 March 2009

OpenVPN: May I?

I was recently asked to look at an existing road-warrior OpenVPN implementation, and see how it could be improved to differentiate network access levels per-user. Some users should have basic access, some should have access to their department's privileged systems, some should have usual department accesses plus temporary specific access to a customer system for setup and upgrades. Fun!

In computer security parlance, this is an authorization issue. Authentication is working, we know who you are, we don't know yet what you should have access to.

Users on this network is stored in LDAP, and the third-party OpenVPN Auth-LDAP plugin is used for authentication. RADIUS is not used anywhere, and adding it to the mix would add complexity and, strangely, not seem to gain us much - the third-party OpenVPN Radiusplugin only does authentication and accounting, and not really the "third A".

The Auth-LDAP plugin has some *BSD-specific code for interacting with PF. I considered rewriting that code to match requirements, but it's written in a pretty unfamiliar language (Objective-C) and has a number of limitations. A user can only be a member of one group (first-match) and group membership can only give access to one set of resources.

Thankfully, OpenVPN has lots of hooks for scripting. Perl hacking will ensue in next installment. Until then.

Tuesday, 24 February 2009


200 OK
Server: nc -l -p 80
X-AspNet-Version: 1.1.4322

...riiight. I believe you.

Monday, 5 January 2009

Sunset spookiness

Now why is the sun sneaking rightwards along the hilltop? Can't see anything tasty in that direction...