2 posts categorized "ruby"

06/09/2009

Tomcat Management: Use the JMXProxy to Change Configuration

After a short break to cover some interesting news over the past couple weeks and to switch templates in Blogger, this series returns with setting configuration values using the JMXProxy. Also, breaking with tradition in this series using Groovy and HTTPBuilder for the 'getting' script examples, the 'setting' portion of this series will use Ruby with the HTTParty gem. There is a fairly good reason why I'm not using Groovy and HTTPBuilder for this next batch of posts--it doesn't work! However, I do not believe that this is the fault of Groovy, HTTPBuilder, or Tomcat. Blame can solidly be placed on my limited programming skills.

One important thing to keep in mind when setting configuration values with the JMXProxy: It ain't permanent! Like the JMX-Console in JBoss, the JMXProxy allows you to Get or Set configuration details at run-time and if one were to restart tomcat, any changes that were made would be reverted back to values stored in your web.xml, server.xml, or other configuration files. So what good is it? Well, you can set logging levels at run-time to better debug a production issue or you could, in theory, create a run-time configuration that is built dynamically after startup without ever having to modify a configuration file outside of tomcat-users.xml.

The example below provides (hopefully!) a useful example meant to illustrate some basic changes that can be made to tomcat. It prints the current configuration of the http connector, then it enables HTTP compression and raises MaxThreads to 400, then reverts everything back pausing after each step so that you can witness the changes. For simplicity, I've set a basic tomcat manager UID and Password to "tomcat".

#!/usr/bin/env ruby

require 'rubygems'
require 'httparty'

class JMXProxy
 include HTTParty
 format :html
 basic_auth 'tomcat', 'tomcat'
end

puts JMXProxy.get('http://localhost:8080/manager/jmxproxy/?qry=Catalina:type=Connector,port=8080')
puts
puts 'Pausing 10 seconds - Changing Settings'
sleep(10)

puts JMXProxy.get('http://localhost:8080/manager/jmxproxy/?set=Catalina:type=Connector,port=8080&att=compression&val=on')
puts JMXProxy.get('http://localhost:8080/manager/jmxproxy/?set=Catalina:type=Connector,port=8080&att=maxThreads&val=400')
puts JMXProxy.get('http://localhost:8080/manager/jmxproxy/?qry=Catalina:type=Connector,port=8080')
puts
puts "Check it out! Resetting changes in 10 seconds..."
sleep(10)

puts JMXProxy.get('http://localhost:8080/manager/jmxproxy/?set=Catalina:type=Connector,port=8080&att=compression&val=off')
puts JMXProxy.get('http://localhost:8080/manager/jmxproxy/?set=Catalina:type=Connector,port=8080&att=maxThreads&val=40')
puts JMXProxy.get('http://localhost:8080/manager/jmxproxy/?qry=Catalina:type=Connector,port=8080')

05/24/2009

Ruby: IIS WebDAV Checker

Sometimes, the frustrating thing about being a systems administrator is that often one's attention gets distracted easily by current events. The IIS WebDAV vulnerability and exploit making the rounds recently made me wonder just how many sites that I am responsible for supporting are utilizing WebDAV. So, the latest batch of Tomcat Management articles will have to wait a little bit longer.

Administering a large number of sites, it actually isn't all that unusual to come across a site built by someone else that might not have the required controls in place that Disables WebDAV on an IIS server, so a discovery tool like this I thought might be useful to more folks than just myself.

So, during this long, rainy, first unofficial start of Summer weekend, I've written the following script that will scan a site and report back whether or not WebDAV is enabled on it. I've tested it on all platforms except for SharePoint Portal, and I'd appreciate it if anyone out there with access to a SharePoint portal server could run it and report back whether the script reports correctly. I'd also appreciate any feedback from readers who are more experienced with Ruby as to whether this script could be fixed or made better.

The script uses the logic from a recent Technet blog article regarding the most recent WebDAV vulnerability. It doesn't work with SSL encrypted sites yet.

#!/usr/bin/env ruby

# Original Written by Chris @ Blogging Techstacks
# Updates by $Your_Name_Could_Go_Here!

# This script tests for the existence of an IIS server running WebDAV. It
# is based upon the following article:
# http://blogs.technet.com/srd/archive/2009/05/20/answers-to-the-iis-webdav-authentication-bypass-questions.aspx
#
# This script DOES NOT attempt any kind of exploit against WebDAV servers.
# All it does is test for the existence of WebDAV.
#
# Usage: ./iisWebDAVTest.rb <site> where <site> must use
# the following syntax: http://fully-qualifed-hostname/
# Trailing slash is required.
# Works with https as well!

require 'net/http'

# Text Colorization Class--not needed but looks fancy
class String
 def red; colorize(self, "\e[1m\e[31m"); end
 def green; colorize(self, "\e[1m\e[32m"); end
 def dark_green; colorize(self, "\e[32m"); end
 def yellow; colorize(self, "\e[1m\e[33m"); end
 def blue; colorize(self, "\e[1m\e[34m"); end
 def dark_blue; colorize(self, "\e[34m"); end
 def purple; colorize(self, "\e[1m\e[35m"); end
 def colorize(text, color_code) "#{color_code}#{text}\e[0m" end
end

puts "\nEnter the URL for the site (example: http://www.some-site.com/)"
name = gets 

url = URI.parse(name)
begin
req = Net::HTTP::Options.new(url.path)
resp = Net::HTTP.start(url.host, url.port) {|http|
 http.request(req) 
}
rescue Errno::ECONNRESET, Errno::ECONNABORTED
 puts "Connection Dropped! - Site could be dropping OPTIONS requests."
 exit
end
# Case statement - delivers response based on status code returned from site
statuscode = resp.code
result = case statuscode
 when "200" 
 then
 if resp.header['DAV'] == '1, 2' && resp.header['MS-Author-Via'] == 'DAV'
 then
  puts "Site has WebDAV enabled. Could be at risk. Get current on patches.".yellow
  puts "Allowable Methods: " + resp.header['Allow']
 elsif resp.header['DAV'] == '1,2' && resp.header['MS-Author-Via'] == 'DAV' && resp.header['X-MSDAVEXT'].exists
 then
  puts "Site uses Sharepoint's DAV".dark_green
  puts "Allowable Methods: " + resp.header['Allow']
 else
 puts "Server is not running WebDAV"
 puts "Allowable Methods: " + resp.header['Allow']
 end
 when "301" 
 then 
 puts "\nSite responded with a 301 - Permanent Redirect".yellow
 puts "\nAn OPTIONS request to redirect target: " 
 puts resp.header['Location'].dark_green 
 puts "may not work and RFC 2616 states that an OPTIONS"
 puts "request MUST NOT automatically follow a redirect."
 puts
 puts "Retry the request to: " + resp.header['Location'].dark_green
 puts "but you might get no response or an error."
 puts
 when "302" 
 then
 puts "\nSite responded with a 302 - Found".yellow
 puts "\nAn OPTIONS request to redirect target: " 
 puts resp.header['Location'].dark_green 
 puts "may not work and RFC 2616 states that an OPTIONS"
 puts "request MUST NOT automatically follow a redirect."
 puts
 puts "Retry the request to: " + resp.header['Location'].dark_green
 puts "but you might get no response or an error."
 puts
 when "403" 
 then 
 puts "OPTIONS is disabled. 403 Forbidden".red
 when "404" 
 then 
 puts "OPTIONS is probably disabled. 404 Not Found".red
 when "405" 
 then 
 puts "OPTIONS is disabled. 405 Method Not Allowed Response".red
 when "501" 
 then 
 puts "OPTIONS is disabled. 501 Not Implemented Response.".red
 else 
 puts "Unexpected Response."
end