<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Martin Holst Swende</title>
	<atom:link href="http://www.swende.se/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.swende.se</link>
	<description>av blandad karaktär</description>
	<lastBuildDate>Sun, 31 Jul 2011 18:22:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Defcon 19</title>
		<link>http://www.swende.se/index.php/2011/07/defcon-19/</link>
		<comments>http://www.swende.se/index.php/2011/07/defcon-19/#comments</comments>
		<pubDate>Sun, 31 Jul 2011 18:22:23 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=208</guid>
		<description><![CDATA[I will be speaking at Defcon 19 in Vegas next saturday, presenting OWASP Hatkit. I will do it jointly with Patrik Karlsson, who presented out of band channeling using sql injection at Defcon 15 a few years back. We have worked hard to implement *tons* of new stuff in the datafiddler, which has been kept [...]]]></description>
			<content:encoded><![CDATA[<p>I will be speaking at Defcon 19 in Vegas next saturday, presenting <a href="https://www.defcon.org/html/defcon-19/dc-19-speakers.html#Swende">OWASP Hatkit</a>. I will do it jointly with Patrik Karlsson, who presented out of band channeling using sql injection at Defcon 15 a few years back. We have worked hard to implement *tons* of new stuff in the datafiddler, which has been kept under wraps so far. It has been a lot of hard work, but we have made great progress! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2011/07/defcon-19/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hatkit now official Owasp project</title>
		<link>http://www.swende.se/index.php/2011/03/hatkit-now-official-owasp-project/</link>
		<comments>http://www.swende.se/index.php/2011/03/hatkit-now-official-owasp-project/#comments</comments>
		<pubDate>Thu, 31 Mar 2011 19:39:21 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=204</guid>
		<description><![CDATA[I just got two of my project approved as official Owasp projects. These are the Hatkit Proxy and the Hatkit Datafiddler. In case you don&#8217;t know what they are, there is some information on the Owasp wiki Hatkit Proxy,Datafiddler and also a presentation I put up on slideshare about the Datafiddler here. Currently, I am [...]]]></description>
			<content:encoded><![CDATA[<p>I just got two of my project approved as official Owasp projects. These are the Hatkit Proxy and the Hatkit Datafiddler. In case you don&#8217;t know what they are, there is some information on the Owasp wiki <a href="http://www.owasp.org/index.php/OWASP_Hatkit_Proxy_Project">Hatkit Proxy</a>,<a href="http://www.owasp.org/index.php/OWASP_Hatkit_Datafiddler_Project#tab=Project_About">Datafiddler</a> and also a presentation I put up on slideshare about the Datafiddler <a href="http://www.slideshare.net/holiman/hatkit-project-datafiddler">here</a>. </p>
<p>Currently, I am in the process of writing documentation on the Owasp wiki. There are two new mailing lists that you are welcome to join if these things sounds interesting to you:
<ul>
<li>
<a href="https://lists.owasp.org/mailman/listinfo/owasp-hatkit-proxy-project">Hatkit proxy mailing list</a></li>
<li>
<a href="https://lists.owasp.org/mailman/listinfo/owasp-hatkit-datafiddler-project">Hatkit Datafiddler mailing list</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2011/03/hatkit-now-official-owasp-project/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tampering with WebSockets</title>
		<link>http://www.swende.se/index.php/2011/01/tampering-with-websockets/</link>
		<comments>http://www.swende.se/index.php/2011/01/tampering-with-websockets/#comments</comments>
		<pubDate>Wed, 12 Jan 2011 15:06:47 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=194</guid>
		<description><![CDATA[I have been experimenting a bit with websockets, mostly to intercept and tamper with websocket traffic. In order to do so, I am using Jetty and the default chat-application which is bundled in the release ( > 7.0). I use google chrome as a browser. My goal was to be able to intercept WebSocket communications [...]]]></description>
			<content:encoded><![CDATA[<p>I have been experimenting a bit with websockets, mostly to intercept and tamper with websocket traffic. In order to do so, I am using Jetty and the default chat-application which is bundled in the release ( > 7.0). I use google chrome as a browser. </p>
<p>My goal was to be able to intercept WebSocket communications between the server and the client, that is</p>
<ul>
<li>Intercept messages that are sent to the server</li>
<li>Intercept messages from the server, before the client application receives them</li>
</ul>
<p>I also want my solution to <strong>not</strong> depend on how the application uses websockets, only dependant on the browser API for WebSockets. </p>
<p>To send anything over websockets, a websocket is constructed and the send()-mehtod is called. Therefore, a simple interceptor would look like this:<br />
<code lang="javascript">window.WebSocket.prototype.oldSend = window.WebSocket.prototype.send;<br />
window.WebSocket.prototype.send=function(data){<br />
	this.oldSend(prompt("Sending data",data));<br />
} </code></p>
<p>Simple overloading of the send-function. That was easy. </p>
<p>It turns out however, that there is no similar functionality for receiving. To receive, an application developer must construct a WebSocket and then &#8216;monkey-patch&#8217; onto it a function called &#8220;onmessage&#8221;. Llike so:</p>
<p><code lang="javascript">x=new WebSocket("ws://localhost:8080/ws/");<br />
x.onmessage=function(){alert(message.data);}</code></p>
<p>This means that the prototype object never really comes into play, since the function is defined only for the actual websocket instance. With some help from Gareth Heyes at <a href="http://sla.ckers.org/forum/read.php?6,35771,35787#msg-35787">sla.ckers.org</a> I instead used the __defineSetter__ property. </p>
<p>The __defineSetter__ is called whenever someone tries to set a property on an object. To get it called, however, I needed to create a wrapped WebSocket object which replaces window.WebSocket. By doing so, the websocket that is created by the application under review will be my &#8216;special&#8217; websocket, where I can deflect any setting of onmessage and retain my tamper-enabled onmessage function.<br />
<code lang="javascript">var oldWebSocket=window.WebSocket;<br />
function WrappedWebSocket(loc)<br />
{<br />
	this.prototype=new oldWebSocket(loc);<br />
	this.__proto__=this.prototype;<br />
	var wrapper=this;<br />
	this.onmessage=function(message)<br />
	{<br />
		var data = prompt("Receiving data",message.data);<br />
		wrapper.trueonmessage({data:data});<br />
	}<br />
	this.__defineSetter__('onmessage', function(val){<br />
					wrapper.trueonmessage=val;<br />
				});<br />
}<br />
window.WebSocket=WrappedWebSocket</code></p>
<p>To finish up, I can merge the two tamper-functions into the same definition, and also (thanks Gareth) put it all inside a closure. The final version became:<br />
<code lang="javascript">window.WebSocket = function(oldWebSocket) {<br />
	return function WrappedWebSocket(loc)<br />
	{<br />
		this.prototype=new oldWebSocket(loc);<br />
		this.__proto__=this.prototype;<br />
		var wrapper=this;<br />
		this.onmessage=function(message)<br />
		{<br />
			var data = prompt("Receiving data",message.data);<br />
			wrapper.trueonmessage({data: data});<br />
		};<br />
		this.__defineSetter__('onmessage', function(val){wrapper.trueonmessage=val;});<br />
		this.send=function(data){this.prototype.send(prompt("Sending data",data));};<br />
	};<br />
}(window.WebSocket);</code></p>
<p>And here is a bookmarklet that you can bookmark and execute the next time you want to tamper with a WebSocket-enabled app:<a href="javascript:window.WebSocket = function(oldWebSocket) {return function WrappedWebSocket(loc){this.prototype=new oldWebSocket(loc);this.__proto__=this.prototype;var wrapper=this;this.onmessage=function(message){var data = prompt("Receiving data",message.data);wrapper.trueonmessage({data: data});};this.__defineSetter__('onmessage', function(val){wrapper.trueonmessage=val;});this.send=function(data){this.prototype.send(prompt("Sending data",data));};};}(window.WebSocket);">TamperSocket</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2011/01/tampering-with-websockets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dumping the RMI Registry with NMAP</title>
		<link>http://www.swende.se/index.php/2010/12/dumping-the-rmi-registry-with-nmap/</link>
		<comments>http://www.swende.se/index.php/2010/12/dumping-the-rmi-registry-with-nmap/#comments</comments>
		<pubDate>Wed, 29 Dec 2010 22:13:37 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=162</guid>
		<description><![CDATA[A while ago, I wrote a NSE script to a Java RMI Registry and dump out information about the objects in the registry. This is a blog-post to shed some light on NSE-development in general and that script in particular. Nmap nowadays comes with a scripting engine, (Nmap Scripting Engine : NSE). When a particular [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago, I wrote a NSE script to a Java RMI Registry and dump out information about the objects in the registry. This is a blog-post to shed some light on NSE-development in general and that script in particular.</p>
<p>Nmap nowadays comes with a scripting engine, (Nmap Scripting Engine : NSE). When a particular service is encountered (say, &#8220;rmi&#8221;) in the service-scan, or a particular port is found open in the port-scan, a script which is &#8220;interested&#8221; in communicating with that particular port or service can be executed. NSE scripts are written in Lua, which I find very nice to work with. Nmap provides basic functionality for common tasks, such as socket communication, binary conversion, output control etc. </p>
<p>RMI is Java&#8217;s remote method invocation, i.e. Java&#8217;s native API for distributing application across different hosts. An object which implements the Remote interface can be called by anoher JVM. For example, say there is an object- let&#8217;s call it monitor &#8211; which resides inside your application and measures statistics for the application, or contains the runtime-configuration. Another application which monitors a cluster of servers may want to connect to each of these and provide real-time monitoring and administration of the services. In order for the cluster-monitor to locate the different monitors, the monitors would first have to make their presence known. They would typically do that by connecting to the RMI Registry. </p>
<p>The RMI Registry is typically found on port 1098 and 1099, often in pairs where one is primary and one is fall-over. It simply keeps tabs on where objects are located. So, the Registry is the natural starting point for anyone trying to gain information about the application which is running. </p>
<p>Over the wire, RMI is mostly java serialization protocol with a few additions (method call invocation, for example). Creating an RMI library for Lua may sound like an odd idea, but it has a few benefits:</p>
<ul>
<li> By reimplementing RMI instead of using java native RMI to perform these tests, I did not have to worry about problems arising when java tries to instantiate stubs of remote objects which belong to a class that is not on the current classpath.</li>
<li> It can be used by Nmap!</li>
</ul>
<p>Also: by using OpenJDK as a reference, I really just had to translate Java into Lua (and try to avoid the messy parts).</p>
<h2>The basics</h2>
<p>Nmap provides only the basics of socket programming, and the sockets do not perform any buffering on reads and writes. Therefore, I start off with creating my Lua-version of buffered reader and writer. I&#8217;ll just show the reader here: </p>
<p><code lang="lua[notools]"><br />
---<br />
-- BufferedReader reads data from the supplied socket and contains functionality<br />
-- to read all that is available and store all that is not currently needed, so the caller<br />
-- gets an exact number of bytes (which is not the case with the basic nmap socket implementation)<br />
-- If not enough data is available, it blocks until data is received, thereby handling the case<br />
-- if data is spread over several tcp packets (which is a pitfall for many scripts)<br />
--<br />
-- It wraps unpack from bin for the reading.<br />
-- OBS! You need to check before invoking skip or unpack that there is enough<br />
-- data to read. Since this class does not parse arguments to unpack, it does not<br />
-- know how much data to read ahead on those calls.<br />
--@usage:<br />
--	local bWriter = BufferedWriter:new(socket)<br />
-- 	local breader= BufferedReader:new(socket)<br />
--<br />
--	bWriter.pack('>i', integer)<br />
--	bWrier.flush() -- sends the data<br />
--<br />
-- 	if bsocket:canRead(4) then -- Waits until four bytes can be read<br />
-- 		local packetLength = bsocket:unpack('i') -- Read the four bytess<br />
-- 		if bsocket:canRead(packetLength) then<br />
-- 			-- ...continue reading packet values</p>
<p>BufferedReader = {<br />
	new = function(self, socket, readBuffer)<br />
		local o = {}<br />
		setmetatable(o, self)<br />
		self.__index = self<br />
		o.readBuffer = readBuffer -- May be nil<br />
		o.pos = 1<br />
		o.socket = socket -- May also be nil<br />
		return o<br />
	end,<br />
	---<br />
	-- This method blocks until the specified number of bytes<br />
	-- have been read from the socket and are avaiable for<br />
	-- the caller to read, e.g via the unpack function<br />
	canRead= function(self,count)<br />
		local status, data<br />
		self.readBuffer = self.readBuffer or ""<br />
		local missing = self.pos + count - #self.readBuffer -1<br />
		if ( missing > 0) then<br />
			if self.socket == nil then<br />
				return doh("Not enough data in static buffer")<br />
			end</p>
<p>			status, data = self.socket:receive_bytes( missing )<br />
			if ( not(status) ) then<br />
				return false, data<br />
			end<br />
			self.readBuffer = self.readBuffer .. data<br />
		end<br />
		-- Now and then, we flush the buffer<br />
		if ( self.pos > 1024) then<br />
			self.readBuffer = self.readBuffer:sub( self.pos )<br />
			self.pos = 1<br />
		end<br />
		return true<br />
	end,<br />
	---<br />
	--@return Returns the number of bytes already available for reading<br />
	bufferSize = function(self)<br />
		return #self.readBuffer +1 -self.pos<br />
	end,<br />
	---<br />
	-- This function works just like bin.unpack (in fact, it is<br />
	-- merely a wrapper around it.  However, it uses the data<br />
	-- already read into the buffer, and the internal position<br />
	--@param format - see bin<br />
	--@return the unpacked value (NOT the index)<br />
	unpack = function(self,format)<br />
		local ret = {bin.unpack(format, self.readBuffer, self.pos)}<br />
		self.pos = ret[1]<br />
		return unpack(ret,2)<br />
	end,<br />
	---<br />
	-- This function works just like bin.unpack (in fact, it is<br />
	-- merely a wrapper around it.  However, it uses the data<br />
	-- already read into the buffer, and the internal position.<br />
	-- This method does not update the current position, and the<br />
	-- data can be read again<br />
	--@param format - see bin<br />
	--@return the unpacked value (NOT the index)<br />
	peekUnpack = function(self,format)<br />
		local ret = {bin.unpack(format, self.readBuffer, self.pos)}<br />
		return unpack(ret,2)<br />
	end,<br />
	---<br />
	-- Tries to read a byte, without consuming it.<br />
	--@return status<br />
	--@return bytevalue<br />
	peekByte = function(self)<br />
		if self:canRead(1) then<br />
			return true, self:peekUnpack('C')<br />
		end<br />
		return false<br />
	end,<br />
	---<br />
	-- Skips a number of bytes<br />
	--@param len the number of bytes to skip<br />
	skip = function(self, len)<br />
		if(#self.readBuffer < len + self.pos) then<br />
			return doh("ERROR: reading too far ahead")<br />
		end<br />
		local skipped = self.readBuffer:sub(self.pos, self.pos+len-1)<br />
		self.pos = self.pos + len<br />
		return true, skipped<br />
	end,</p>
<p>}</code></p>
<p>A couple of comments: NSE does not provide a very good exception-handling system, so (almost) all functions return multiple return values, where the first is usually the status: true if all is well, false if something went wrong. The function doh(..) is just a wrapper for that :<br />
<code lang="lua">local function doh(str,...)<br />
	stdnse.print_debug("RMI-ERR:"..tostring(str), unpack(arg))<br />
	return false, str<br />
end</code></p>
<p>Once buffering sockets are up and running, I need something which resembles the DataWriter and DataReader from java. NSE provides a bin-library to do binary conversion between formats, and my library uses them. I'll just show the Lua-version of java DataInputStream here:</p>
<p><code lang="lua">---<br />
-- The JavaDIS class<br />
-- JavaDIS is close to java DataInputStream. It provides convenience functions<br />
-- for reading java types from an underlying BufferedReader<br />
--<br />
-- When used in conjunction with the BufferedX- classes, they handle the availability-<br />
-- checks transparently, i.e the caller does not have to check if enough data is available<br />
--<br />
-- @usage:<br />
-- 	local dos = JavaDOS:new(BufferedWriter:new(socket))<br />
-- 	local dos = JavaDIS:new(BufferedReader:new(socket))<br />
-- 	dos:writeUTF("Hello world")<br />
-- 	dos:writeInt(3)<br />
-- 	dos:writeLong(3)<br />
--	dos:flush() -- send data<br />
-- 	local answer = dis:readUTF()<br />
-- 	local int = dis:readInt()<br />
-- 	local long = dis:readLong()<br />
JavaDIS = {<br />
	new = function  (self,bReader)<br />
		local o = {}   -- create new object if user does not provide one<br />
		setmetatable(o, self)<br />
		self.__index = self -- DIY inheritance<br />
		o.bReader = bReader<br />
		return o<br />
	end,</p>
<p>	-- This closure method generates all reader methods (except unstandard ones) on the fly<br />
	-- according to the definitions in JavaTypes.<br />
	_generateReaderFunc = function(self, javatype)<br />
		local functionName = 'read'..javatype.name<br />
		local newFunc = function(_self)<br />
						--dbg(functionName .."() called" )<br />
						if not _self.bReader:canRead(javatype.len)  then<br />
							local err = ("Not enough data in buffer (%d required by %s)"):format(javatype.len, functionName)<br />
							return doh(err)<br />
						end<br />
						return true, _self.bReader:unpack(javatype.expr)<br />
					end<br />
		self[functionName] = newFunc<br />
	end,<br />
	-- This is a bit special, since we do not know beforehand how many bytes must be read. Therfore<br />
	-- this cannot be generated on the fly like the others.<br />
        readUTF = function(self, text)<br />
		-- First, we need to read the length, 2 bytes<br />
		if not self.bReader:canRead(2)  then-- Length of the string is two bytes<br />
			return doh("Not enough data in buffer [0]")<br />
		end<br />
		-- We do it as a 'peek', so bin can reuse the data to unpack with 'P'<br />
		local len = self.bReader:peekUnpack('>S')<br />
		-- Check that we have data<br />
		if not self.bReader:canRead(len) then<br />
			return doh("Not enough data in buffer [1]"=<br />
		end<br />
		-- For some reason, the 'P' switch does not work for me.<br />
		-- Probably some idiot thing. This is a hack:<br />
		local val = self.bReader.readBuffer:sub(self.bReader.pos+2, self.bReader.pos+len+2-1)<br />
		self.bReader.pos = self.bReader.pos+len+2<br />
		-- Someone smarter than me can maybe get this working instead:<br />
		--local val = self.bReader:unpack('P')<br />
		return true, val<br />
	end,<br />
	skip = function(self, len)<br />
		return self.bReader:skip(len)<br />
	end,<br />
	canRead = function(self, len)<br />
		return self.bReader:canRead(len)<br />
	end,<br />
}</code></p>
<p>It actually only defines readUTF, not the other types. In order to separate a bit between actual *code* and *format*, I define a set of translations between Java format for basic types and the format used by the bin-library:<br />
<code lang="lua">local JavaTypes = {<br />
	{name = 'Int', expr = '>i', len=  4},<br />
	{name = 'UnsignedInt', expr = '>I', len=  4},<br />
	{name = 'Short', expr = '>s', len=  2},<br />
	{name = 'UnsignedShort', expr = '>S', len=  2},<br />
	{name = 'Long', expr = '>l', len=  8},<br />
	{name = 'UnsignedLong', expr = '>L', len=  8},<br />
	{name = 'Byte', expr = '>C', len=  1},<br />
}<br />
</code></p>
<p>It basically specifies that a java short corresponds to the format string ">s" in the bin-library. Once that is done, I monkey-patch the javaDOS with the format definitions:<br />
<code lang="lua">-- Generate writer-functions on the JavaDOS/JavaDIS classes on the fly<br />
-- Generate writer-functions on the JavaDOS/JavaDIS classes on the fly<br />
for _,x in ipairs(JavaTypes) do<br />
	JavaDOS._generateWriterFunc(JavaDOS, x)<br />
	JavaDIS._generateReaderFunc(JavaDIS, x)<br />
end</code></p>
<p>The call to _generateWriterFunc() creates a new function named ("write"+"Short") in the library.  The only reason I had to implement UTF a bit 'special' is that the length of the UTF is not known in advance, so the reader cannot know if it can read the entire string until it has read the string length.  </p>
<h2>RMI</h2>
<p>I won't go into the details about RMI implementation details of the library. But to give a brief overview, in order to perform a remote method invocation, a few things are needed. </p>
<ul>
<li>Host and port, which Nmap provides. </li>
<li>Object id: a unique identifier for the object with which you are trying to communicate. The Registry-object has id 0</li>
<li>Hash code for the remote class of the object you are trying to invoke a method on. The hash for the Registry, (sun.rmi.registry.RegistryImpl_Stub) is 0x44154dc9d4e63bdf</li>
<li>Operation id: a numeric identifier of what method you are trying to invoke. The Registry has the following methods which will be used: list()=0, lookup(String)=2</li>
<li>Optional: any arguments which are needed by the method</li>
</ul>
<p>These values can be located inside the class-files for any Remote class. The RMIRegistry is implemented in OO-fashion inside my RMI library, and looks like this:<br />
<code lang="lua">---<br />
-- Registry<br />
-- Class to represent the RMI Registry.<br />
--@usage:<br />
-- 	registry = rmi.Registry:new()<br />
-- 	status, data = registry:list()<br />
Registry ={<br />
	new = function  (self,host, port)<br />
		local o ={}   -- create object<br />
		setmetatable(o, self)<br />
		self.__index = self -- DIY inheritance<br />
		-- Hash code for sun.rmi.registry.RegistryImpl_Stub, which we are invoking :<br />
		-- hex: 0x44154dc9d4e63bdf 	, 	dec: 4905912898345647071<br />
		self.hash = '44154dc9d4e63bdf'<br />
		-- RmiRegistry object id is 0<br />
		self.objId = 0<br />
		o.host = host<br />
		o.port = port<br />
		return o<br />
	end<br />
}<br />
-- Connect to the remote registry.<br />
--@return status<br />
--@return error message<br />
function Registry:_handshake()<br />
	local out = RmiDataStream:new()<br />
	local status, err = out:connect(self.host,self.port)</p>
<p>	if not status then<br />
		return doh("Registry connection failed: %s", tostring(err))<br />
	end<br />
	dbg("Registry connection OK "..tostring(out.bsocket) )<br />
	self.out = out<br />
	return true<br />
end<br />
---<br />
-- List the named objects in the remote RMI registry<br />
--@return status<br />
--@return a table of strings , or error message<br />
function Registry:list()<br />
	if not self:_handshake() then<br />
		return doh("Handshake failed")<br />
	end<br />
	-- Method list() is op number 1<br />
	return self.out:invoke(self.objId, self.hash,1)<br />
end<br />
---<br />
-- Perform a lookup on an object in the Registry,<br />
-- takes the name which is bound in the registry<br />
-- as argument<br />
--@return status<br />
--@return JavaClass-object<br />
function Registry:lookup(name)<br />
	self:_handshake()<br />
	-- Method lookup() is op number 2<br />
	-- Takes a string as arguments<br />
	local a = Arguments:new()<br />
	a:addString(name)<br />
	return self.out:invoke(self.objId, self.hash,2, a)<br />
end<br />
</code></p>
<p>The actual NSE-script uses the library like this:</p>
<p><code lang="lua">local registry= rmi.Registry:new( host.ip, port.number)<br />
local status, j_array = registry:list()</code></p>
<p>If all goes well, the variable j_array will contain a list of strings, where each string is the name of an object in the registry. It then loops over the names and queries additional info about each of them:<br />
<code lang="lua">	-- We expect an array of strings to be the return data<br />
	local data = j_array:getValues()<br />
	for i,name in ipairs( data ) do<br />
		--print(data)<br />
		table.insert(output, name)<br />
		dbg("Querying object %s", name)<br />
		local status, j_object= registry:lookup(name)<br />
		if status then<br />
			table.insert(output, j_object:toTable())<br />
		end<br />
	end</code></p>
<h2>Testing</h2>
<p>To write NSE scripts yourself, just place the scripts (or symlinks to them) into your nmap home scripts-dir, any libraries in the nselib/-dir, and run:<br />
<code lang="bash">nmap --script "rmi-dumpregistry.nse" -p 1098 <host></code></p>
<p>In order to perform some real live testing, you can use Nmap's built in functionality to randomly scan internet hosts with the -iR switch. The following command will randomly scan ten thousand addresses on port 1098 and port 1099, and if they are found to be open, the rmi-registry dumper will be executed:<br />
<code lang="bash">nmap --script rmi-dumpregistry.nse -p 1098,1099 -iR 10000</code></p>
<p>As I was testing this on the internet, I noticed two things. The first being that the probably most common usage for RMI is JMX. JMX is Java Management eXtensions, basically it is what I mentioned above: a java object which can be used to monitor and modify a java application. These objects are typically named "jmxconsole", and if you locate such an object it is possible to perform bruteforce password guessing against it. This is not implemented in Lua, but is very simple to write in native Java. Anyone with a valid username/password can then use jconsole to connect to a jmx service.  </p>
<p>The other thing I noticed was that ColdFusion/Flex disclosed the entire classpath of the application that I had encountered:<br />
<code lang="lua">-- PORT     STATE SERVICE REASON<br />
-- 1099/tcp open  rmi     syn-ack<br />
-- | rmi-dumpregistry:<br />
-- |   cfassembler/default<br />
-- |     coldfusion.flex.rmi.DataServicesCFProxyServer_Stub<br />
-- |     @192.168.0.3:1271<br />
-- |     extends<br />
-- |       java.rmi.server.RemoteStub<br />
-- |       extends<br />
-- |         java.rmi.server.RemoteObject<br />
-- |     Custom data<br />
-- |       Classpath<br />
-- |         file:/C:/CFusionMX7/runtime/../lib/ant-launcher.jar<br />
-- |         file:/C:/CFusionMX7/runtime/../lib/ant.jar<br />
-- |         file:/C:/CFusionMX7/runtime/../lib/axis.jar<br />
-- |         file:/C:/CFusionMX7/runtime/../lib/backport-util-concurrent.jar<br />
-- |         file:/C:/CFusionMX7/runtime/../lib/bcel.jar<br />
-- |         file:/C:/CFusionMX7/runtime/../lib/cdo.jar<br />
-- [.. the list goes on ...]</code></p>
<p>What is displayed above is, for each object in the registry:</p>
<ul>
<li>The name: cfassembler/default</li>
<li>The location of the remote object. In this case, the object resides on an internal address, 192.168.0.3. In other cases, it may reveal other publically accessible hosts which were not part of the original scan</li>
<li>The class hierarchy. In this case "extends RemoteStub which extends RemoteObject". In other cases, it may reveal information about what this application is used for and what the objects represent. It may also reveal the name of a class which is open source - if so, it is possible to download the class definitions and communicate directly with the object using java native RMI - and invoke methods on the objects. </li>
<li>Any so called 'Custom data', which is data that is encoded in a way which is privy to the class: Java RMI cannot parse custom data without first instantiating an object of said class first. It can contain data of any format that the programmer choose to put in the field. In this case, I noticed that it was a classpath and made a modification to parse that out and prettify for the end user.</li>
</ul>
<p>While this is far from a 0day, it is definitely not good to send out your internal driveletters, paths and source code details on the tubes.</p>
<h2>Conclusion</h2>
<p>Writing Nmap scripts is easy to do, if you think the steps above sounds complicated, blame Java (and me). The script itself was committed a while ago, and will be available in the next release (unless you update your nmap from subversion, in which case you already have it). </p>
<p>I can also recommend viewing the presentation from BlackHat 2010 (<a href="http://nmap.org/presentations/BHDC10/">http://nmap.org/presentations/BHDC10/</a>) given by Fyodor and David Fifield with the title "Mastering the Nmap Scripting Engine". It is an awesome presentation where Fyodor hacks Microsoft and David shows his skills by creating an nmap script from scratch (in front of a live audience - now THAT's hardcore!). </p>
<p>Also, the presentation briefly mentions me by name (blink and you'll miss it!) in the section about upcoming scripts, which is the closest I have come to the stage at BlackHat so far <img src='http://www.swende.se/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
<p>All source code is available either from nmap subversion repository or my <a href="http://www.swende.se/index.php/2010/12/customizing-mercurial/">swanky</a> mercurial <a href="http://martin.swende.se/hg">repositories</a>, the repository nsescripts contains this script and some other NSE-related things I have been working on. </p>
<h2>Disclaimer</h2>
<p>This tool is provided as a means for a system administrator or security consultant, such as myself, to be able to discover potentially vulnerable services in complex or large environments without having to be an expert at Java RMI. As with all tools of this type, it may just as well be used by attackers - but an attacker with basic knowledge of Java RMI could easily perform all of the above (and more) with a very simple Java program.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2010/12/dumping-the-rmi-registry-with-nmap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Customizing Mercurial</title>
		<link>http://www.swende.se/index.php/2010/12/customizing-mercurial/</link>
		<comments>http://www.swende.se/index.php/2010/12/customizing-mercurial/#comments</comments>
		<pubDate>Thu, 09 Dec 2010 13:29:42 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=148</guid>
		<description><![CDATA[I really like Mercurial (as in &#8220;distributed source control management tool&#8221; not as in a metallic element), but I am not that fond of the default look and feel of the web-publishing tool: hgwebdir. So, I am in the process of modifying and creating a custom template using a bit of jquery magic. Check it [...]]]></description>
			<content:encoded><![CDATA[<p>I really like Mercurial (as in &#8220;distributed source control management tool&#8221; not as in a metallic element), but I am not that fond of the default look and feel of the web-publishing tool: hgwebdir. So, I am in the process of modifying and creating a custom template using a bit of jquery magic. </p>
<p>Check it out at <a href="http://martin.swende.se/hg/">http://martin.swende.se/hg/</a> .<br />
<a href="http://www.swende.se/wp-content/uploads/2010/12/Screenshot-1.png"><img src="http://www.swende.se/wp-content/uploads/2010/12/Screenshot-1.png" alt="Theme is &quot;black-tie&quot; from jquery-ui" title="Screenshot-1" width="615" height="362" class="alignnone size-full wp-image-154" /></a></p>
<p>I added activity-tabs to all projects, which fetches the latest changelogs with xhr. Some more features that I am working on are support for displaying screenshots and content from README and INSTALL files. This requires some messing with commit-hooks, in order to get hg to extract the relevant files, generate thumbnails and create xml or json-descriptions of what content is available (aswell as publishing that info on the webserver). </p>
<p>The actual ui design comes from jquery-ui api, they have a lot of variants and it it easy to roll your own with the themeroller : <a href="http://jqueryui.com/themeroller/">http://jqueryui.com/themeroller/</a>. Once I have revamped the other pages aswell, I may submit it to the folks at Selenic and see if they like it. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2010/12/customizing-mercurial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finding Applications</title>
		<link>http://www.swende.se/index.php/2010/07/finding-applications/</link>
		<comments>http://www.swende.se/index.php/2010/07/finding-applications/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 21:47:46 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=133</guid>
		<description><![CDATA[The last of the batch of tools which uses search engines is called IPSearch. That one is useful if you have a large list of ip-addresses, and you want to find out whether e.g if there are any virtual hosts which shares the same ips, or just generally what applications are hosted on the ips. [...]]]></description>
			<content:encoded><![CDATA[<p>The last of the batch of tools which uses search engines is called IPSearch. That one is useful if you have a large list of ip-addresses, and you want to find out whether e.g if there are any virtual hosts which shares the same ips, or just generally what applications are hosted on the ips. Just pipe the ips into ipsearch, and it uses Bings search engine to find them. Unfortunately, requires an API-key <img src='http://www.swende.se/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  &#8211; but those are not hard to come by. </p>
<p>Example:</p>
<p><code lang="text">$ cat ip.txt | python ipsearch.py -b bingkey.txt<br />
208.201.239.101 :<br />
    craftzine.com: CRAFT: Dedicated to the renaissance in the world of ... : </p>
<p>http://craftzine.com/</p>
<p>    Web 2.0 Summit 2009 - Co-produced by TechWeb &#038; O'Reilly Conferences ... : </p>
<p>http://www.web2summit.com/web2009</p>
<p>    Perl.com Home Page : </p>
<p>http://www.perl.com/</p>
<p>    craftzine.com: CRAFT Projects : </p>
<p>http://craftzine.com/projects/</p>
<p>    tim.oreilly.com -- Various Thing I've Written: Tim O'Reilly's Archive : </p>
<p>http://tim.oreilly.com/</p>
<p>    Web 2.0 Expo San Francisco 2009 - Co-produced by TechWeb &#038; O'Reilly ... : </p>
<p>http://www.web2expo.com/webexsf2009</p>
<p>    Google free proxy! : </p>
<p>http://www.oreillynet.com/pub/h/4807</p>
<p>    makezine.com: MAKE: Magazine : </p>
<p>http://makezine.com/magazine/</p>
<p>    Web 2.0 Summit 2010 - Co-produced by UBM TechWeb &#038; O'Reilly ... : </p>
<p>http://www.web2summit.com/web2010</p>
<p>    O'Reilly Tools of Change for Publishing Conference 2010 - O'Reilly ... : </p>
<p>http://www.toccon.com/toc2010</p>
<p>    A total of 66200 results found, do manual test to find the rest : </p>
<p>67.222.96.148 :<br />
    O'Reilly Radar - Insight, analysis, and research about emerging ... : </p>
<p>http://radar.oreilly.com/</p>
<p>    Tools of Change for Publishing : </p>
<p>http://toc.oreilly.com/</p>
<p>    Best iPhone Apps - O'Reilly Media : </p>
<p>http://iphoneapps.oreilly.com/</p>
<p>    InsideRIA - Community for Rich Internet Application Developers and ... : </p>
<p>http://insideria.com/</p>
<p>    Google Wave: What Might Email Look Like If It Were Invented Today? - O ... : </p>
<p>http://radar.oreilly.com/2009/05/google-wave-what-might-email-l.html</p>
<p>    Best iPhone Apps: Best App Archives - O'Reilly Media : </p>
<p>http://iphoneapps.oreilly.com/archive.html</p>
<p>    Build a $21 Portable Vocal Booth - O'Reilly Digital Media Blog : </p>
<p>http://blogs.oreilly.com/digitalmedia/2008/02/build-a-portable-vocal-booth.html</p>
<p>    The Definition of Insanity is, perhaps, using that quote. - O'Reilly ... : </p>
<p>http://blogs.oreilly.com/digitalmedia/2006/10/the-definition-of-insanity-is.html</p>
<p>    Low End Linux Netbook Prices Continue To Drop - O'Reilly Broadcast : </p>
<p>http://broadcast.oreilly.com/2009/06/low-end-linux-netbook-prices-c.html</p>
<p>    David Pogue's Top 10 Tips for the iPhone 3GS and iPhone 3.0 Software ... : </p>
<p>http://broadcast.oreilly.com/2009/07/david-pogues-top-10-tips-for-t.html</p>
<p>    A total of 43800 results found, do manual test to find the rest : </p>
<p>72.34.60.160 :<br />
    Ignite : </p>
<p>http://ignite.oreilly.com/</p>
<p>    El primer Ignite Madrid tendrá lugar el 3 de Marzo del 2010, en el ... : </p>
<p>http://ignite.oreilly.com/2010/02/post-4.html</p>
<p></code></p>
<p><a href="http://martin.swende.se/hgwebdir.cgi/ipsearch/raw-file/tip/ipsearch.tar.gz">Download</a> or clone ( hg clone http://martin.swende.se/hgwebdir.cgi/ipsearch/ ) </p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2010/07/finding-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finding subdomains</title>
		<link>http://www.swende.se/index.php/2010/06/finding-subdomains/</link>
		<comments>http://www.swende.se/index.php/2010/06/finding-subdomains/#comments</comments>
		<pubDate>Mon, 28 Jun 2010 19:46:30 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=129</guid>
		<description><![CDATA[A while back, I wrote about Googlyhack. While I was at it, I made two other similar tools that use search engines for other purposes &#8211; but I noticed recently that I had not written anything about them. The first one is Subsearch, which is a replacement for the old tool &#8220;Subdomainer&#8221;. Subdomainer does not [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, I wrote about Googlyhack. While I was at it, I made two other similar tools that use search engines for other purposes &#8211; but I noticed recently that I had not written anything about them. The first one is <b>Subsearch</b>, which is a replacement for the old tool &#8220;Subdomainer&#8221;. Subdomainer does not seem to work anymore, so I made a replacement which uses Google, Yahoo and Bing to perform searches. The latter two requires an API-key.</p>
<p>It does this:</p>
<ul>
<li>Searches each search engine with exclusions for already found domains, such as &#8220;site:example.com -site:a.example.com -site:b.example.com&#8221; until all search results are exhausted and no more are found. </li>
<li>Except for google, which only allows 40 keywords. If the search is not exhausted by then, it tries to use google &#8216;slowsearch&#8217;, i.e it uses the last working query and clicks &#8220;next page&#8221; until it does not find any more results.</li>
</ul>
<p>Usage:</p>
<p><code lang="bash">$ ./subsearch.py -d oreilly.com -b bingkey.txt -y yahoo_app_id.txt<br />
Using domain oreilly.com<br />
Using yahoo search API as well<br />
Using bing search API as well<br />
--------------------------------------------<br />
Yahoo:<br />
www.oreilly.com<br />
radar.oreilly.com<br />
ignite.oreilly.com<br />
tim.oreilly.com<br />
wethemedia.oreilly.com<br />
oreilly.com<br />
en.oreilly.com<br />
--------------------------------------------<br />
Bing:<br />
oreilly.com<br />
radar.oreilly.com<br />
toc.oreilly.com<br />
answers.oreilly.com<br />
digitalmedia.oreilly.com<br />
iphoneapps.oreilly.com<br />
tim.oreilly.com<br />
en.oreilly.com<br />
--------------------------------------------<br />
Google:<br />
oreilly.com<br />
answers.oreilly.com<br />
microsoftpress.oreilly.com<br />
digitalmedia.oreilly.com<br />
iphoneapps.oreilly.com<br />
tim.oreilly.com<br />
radar.oreilly.com<br />
--------------------------------------------<br />
Performing google slow-search<br />
Done<br />
--------------------------------------------<br />
Done: 12 subdomains found:<br />
digitalmedia.oreilly.com<br />
en.oreilly.com<br />
www.oreilly.com<br />
tim.oreilly.com<br />
ignite.oreilly.com<br />
toc.oreilly.com<br />
oreilly.com<br />
microsoftpress.oreilly.com<br />
answers.oreilly.com<br />
iphoneapps.oreilly.com<br />
wethemedia.oreilly.com<br />
radar.oreilly.com<br />
</code></p>
<p><a href="http://martin.swende.se/hgwebdir.cgi/subsearch/raw-file/tip/subsearch.tar.gz">Download</a> or clone ( hg clone http://martin.swende.se/hgwebdir.cgi/subsearch/ ) </p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2010/06/finding-subdomains/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GooglyHacks (GHDB)</title>
		<link>http://www.swende.se/index.php/2010/04/googlyhacks-ghdb/</link>
		<comments>http://www.swende.se/index.php/2010/04/googlyhacks-ghdb/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 20:11:10 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=116</guid>
		<description><![CDATA[I noticed that the GHDB-plugin from w3af was a bit deprecated and not quite flexible enough for my purposes, so I wrote a little tool to use GHDB database to find vulnerabilites for a site. Google has deprecated the old Soap-api in favour for a new Ajax-api which was really nice to work with. To [...]]]></description>
			<content:encoded><![CDATA[<p>I noticed that the GHDB-plugin from w3af was a bit deprecated and not quite flexible enough for my purposes, so I wrote a little tool to use GHDB database to find vulnerabilites for a site. Google has deprecated the old Soap-api in favour for a new Ajax-api which was really nice to work with. </p>
<p>To use the tool it, you do this : </p>
<p><code lang="bash">python googlyhack.py -domain foobar.com</code></p>
<p>And then it goes through the entire GHDB (which is an XML-file, just drop in a new replacement if you find a newer one. Please also send it to me!). One feature which I missed in w3af and therefore implemented was that If google blocks you,  GooglyHack pause until you tell it to continue: </p>
<p><code lang="bash">Aborted after 1200 requests<br />
Stopped after 1200 requests (of 1466). Press any key to continue, or ctrl-c to quit</code></p>
<p>If you choose to abort, you can start it later (or on another computer) to continue again where it left off:<br />
<code lang="bash">python googlyhack.py -domain foobar.com -i 1200</code></p>
<p>Here is a snippet of an example run against domain microsoft.com :<br />
<code lang="bash">List loaded, length 1466<br />
Starting at index 0<br />
0:0 hits<br />
1:0 hits<br />
2:0 hits<br />
3:0 hits<br />
4:0 hits<br />
5:0 hits<br />
6:0 hits<br />
7:2 hits<br />
Example urls:<br />
-Title: http://social.msdn.microsoft.com/Forums/en-US/sqlexpress/thread/30d3b3c9-9bf8-4265-82bb-d192f232cf24<br />
-Url: Need to convert the following mysql to sql server<br />
-Title: http://social.msdn.microsoft.com/forums/pt-BR/520/thread/0e964ff4-0b2e-4a1b-80f6-1151e05aabb5/<br />
-Url: SQL Server Management Studio Express - Exportar com dados?<br />
Query used : site:microsoft.com "# Dumping data for table"<br />
GHDB Description: SQL database dumps. LOTS of data in these. So much data, infact, I'm pressed to think of what else an ev1l hax0r would like to know about a target database.. What's that? Usernames and passwords you say? Patience, grasshopper.....<br />
</code></p>
<p>I thought that google-blocking would be an issue, but using the ajax-api I had no such problems. So no additional steps are taken to bypass blocking, such as using alterating useragents or randomizing the ghdb-list. Apparantly the ajax-api is pretty nice against robotic behaviour. </p>
<p>Complete source can be found at <a href="http://martin.swende.se/hgwebdir.cgi/GooglyHack/">http://martin.swende.se/hgwebdir.cgi/GooglyHack/</a><br />
Get it either by :<br />
<code lang="bash">hg clone http://martin.swende.se/hgwebdir.cgi/GooglyHack/</code></p>
<p>-OR-<br />
<code lang="bash">wget http://martin.swende.se/hgwebdir.cgi/GooglyHack/raw-file/tip/src/googlyhack.py<br />
wget http://martin.swende.se/hgwebdir.cgi/GooglyHack/raw-file/tip/src/GHDB.xml<br />
</code></p>
<p>Enjoy! (and remember : don&#8217;t be evil!)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2010/04/googlyhacks-ghdb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Packet Play</title>
		<link>http://www.swende.se/index.php/2010/01/python-packet-play/</link>
		<comments>http://www.swende.se/index.php/2010/01/python-packet-play/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 22:17:24 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.swende.se/?p=94</guid>
		<description><![CDATA[As X-mas challenge for the Owasp Appsec Research 2010 conference, me and Mario Heiderich set up a Capture-the-flag at a computer. While .mario did all the tricky and brainteasing stuff with the actual challenge, I created a diversionary target which let me play a bit with low level packet shuffling in Python. The idea I [...]]]></description>
			<content:encoded><![CDATA[<p>As X-mas challenge for the Owasp Appsec Research 2010 conference, me and Mario Heiderich set up a Capture-the-flag at a computer. While .mario did all the tricky and brainteasing stuff with the actual challenge, I created a diversionary target which let me play a bit with low level packet shuffling in Python. </p>
<p>The idea I had in mind was that I wanted the computer to<br />
- Appear as having lots and lots of open ports<br />
- Each open port should appear to run some service<br />
- Each service should be recognised by nmap<br />
&#8230;<br />
- But actually, the incoming packets should be dropped</p>
<p>I got the inspiration for this when reading up on the Sockstress implementation. What we want to avoid is to have any state on the server side, since this is supposed to run on a low-end VPS-machine without affecting the other part of the system. So, how can this be achieved ?  This is the basic idea: </p>
<p>1. Using iptables, set up so that packets to the desired ports are put into a netfilter queue.<br />
2. Using python netfilter module, connect the netfilter queue to a python program.<br />
3. In the python program, create a suitable response packet, and send this over a raw socket.<br />
3a. On a SYN-packet, respond with a SYN-ACK. (This makes the port look open). The other part will finish the three-part handshake with an ACK packet.<br />
3b. On the ACK-packet, respond with two piggybacked packets. First, an ACK/PSH with some data that looks like some valid service, e.g &#8220;Windows FTP server&#8221; or &#8220;A-311 Death welcome&#8221;. Secondly, close the connection with a FIN/ACK packet.<br />
4. For extra credits, try to answer prudently to any other packets that may come in. Also, try to avoid endless repeating by e.g checking sequence numbers.<br />
5. Remember that the netfilter queue from iptables still waits for a judgement on what to do with this packet? Respond to the kernel with a &#8220;DROP&#8221; signal. The OS now drops the packet and forgets all about it.</p>
<h2>Iptables</h2>
<p>To set up so we can fiddle the packets in python, we do this :<br />
<code lang="bash"><br />
#Create a new iptable chain called fuzzywall<br />
iptables -N fuzzywall<br />
#<br />
# Fuzzywall<br />
# We only run it on port 1337 to start off<br />
# - Optionally : send to logging facilties (can be found in syslog)<br />
#iptables -A fuzzywall -p tcp --dport 1337 -j LOG --log-prefix "Sending to queue"<br />
#Add rule to 'fuzzywall', if dest port is 1337, send to netfilter queue<br />
iptables -A fuzzywall -p tcp --dport 1337 -j QUEUE</p>
<p>#Add our chain to INPUT<br />
iptables -A INPUT -j fuzzywall<br />
</code><br />
So, that puts fuzzywall in the INPUT chain. All incoming packets to port 1337 now goes to the netfilter queue. </p>
<h2>Python netfilter</h2>
<p>We need to get the kernel netfilter queue into our python program. To do this, I used nfqueue library from Pollux (<a href="http://www.wzdftpd.net/blog/index.php?2008/06/01/22-nfqueue-bindings">http://www.wzdftpd.net/blog/index.php?2008/06/01/22-nfqueue-bindings</a> ). It is very easy to set up :<br />
<code lang="python">    q = nfqueue.queue()<br />
    q.open()<br />
    q.bind(AF_INET)<br />
    q.set_callback(callback)<br />
    q.create_queue(0)<br />
    q.set_queue_maxlen(5000)<br />
    print "starting"<br />
    try:<br />
        q.try_run()<br />
    except KeyboardInterrupt, e:<br />
        print "interrupted"</p>
<p>    print "unbinding"<br />
    q.unbind(AF_INET)<br />
    print "closing"<br />
    q.close()</code></p>
<p>In addition, a handler needs to be specified which can return the verdict back to iptables : </p>
<p><code lang="python">def callback(dummy, payload):<br />
    data = payload.get_data()</p>
<p>    handler.handlePacket(data)</p>
<p>    payload.set_verdict(nfqueue.NF_DROP)<br />
    return</code></p>
<p>And, of course, it is in handler.handlePacket where the packetcrafting is peformed. </p>
<h2>Python Packetcrafting</h2>
<p>In order to play with packets, I found two libraries that could be used; impacket (<a href="http://pypi.python.org/pypi/Impacket/0.9.5">http://pypi.python.org/pypi/Impacket/0.9.5</a>) and dpkt (<a href="http://code.google.com/p/dpkt/">http://code.google.com/p/dpkt/</a>). They have a few differences, but both can be used to parse and create all kinds of packets. In the end, I used both of them (which maybe was a bit suboptimal &#8211; but worth it just to test how they worked). This example uses a dpkt-packet parsed from raw data and generates a default response packet using impacket:<br />
<code lang="python"><br />
def createReturnPacket(self,packet,seqOffset = 0):</p>
<p>        dst = inet_ntoa(packet.dst)<br />
        src = inet_ntoa(packet.src)<br />
        sport = packet.tcp.sport<br />
        dport = packet.tcp.dport</p>
<p>        #set the IPs<br />
        ip = ImpactPacket.IP()<br />
        ip.set_ip_src(dst)<br />
        ip.set_ip_dst(src)<br />
        #set the ports<br />
        tcp = ImpactPacket.TCP()<br />
        tcp.set_th_sport(dport)<br />
        tcp.set_th_dport(sport)<br />
        #Set a window size<br />
        tcp.set_th_win(10)<br />
        #Bundle the tcp packet inside the ip-packet<br />
        ip.contains(tcp)<br />
        return (ip,tcp,src)</code></p>
<p>I can now use this packet to create a SYN/ACK in response to a SYN :<br />
<code lang="python">        #Is this a SYN or an ACK?<br />
        if (in_packet.tcp.flags &#038; dpkt.tcp.TH_SYN) != 0:<br />
            out_tcp_packet.set_SYN()<br />
            out_tcp_packet.set_ACK()<br />
            out_tcp_packet.set_th_seq(0)<br />
            out_tcp_packet.set_th_ack(in_packet.tcp.seq+1);<br />
            self._send(dst, out_ip_packet)</code></p>
<p>Once an appropriate return packet is created, it can be sent raw on the socket :<br />
<code lang="python"><br />
    def _send(self, dst, ip):<br />
        s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)<br />
        s.setsockopt(IPPROTO_IP, IP_HDRINCL, 1)<br />
        s.sendto(ip.get_packet(), (dst, 0))<br />
        return<br />
</code></p>
<h2>Fooling nmap</h2>
<p>The desired functinality was that if an nmap service version scan was performed, such as:<br />
<code lang="bash">nmap -p 1337 -sV <host></code></p>
<p>Nmap should score a match. When a service version in nmap is performed, nmap sends so called &#8216;probes&#8217; to the port and checks what is returned. It has a list of fingerprints for known services. For example, one service probe called  &#8220;TCP GetRequest&#8221; sends &#8220;GET / HTTP/1.0\r\n\r\n&#8221;, and if the response matches &#8220;HTTP/1\.[01] \d\d\d.*\r\nDate: .*\r\nServer: Apache\r\n&#8221;, it is identified as an Apache server. If it does NOT match, nmap goes through the rest of the probes &#8211; which we definitely want to avoid, as we want as little overhead as possible. </p>
<p>First of all, nmap has the so called &#8216;Null probe&#8217;, which means that it connects to the port and waits for a few seconds to check if the service will volunteer some info without the client sending any data. It is in this segment I wanted to have my matches, since it is the first test. All service fingerprints are located in a file called nmap-service-probes, and look something like this :<br />
<code lang="bash"></p>
<p>match acap m|^\* ACAP \(IMPLEMENTATION \"CommuniGate Pro ACAP (\d[-.\w]+)\"\) | p/CommuniGate Pro ACAP server/ i/for mail client preference sharing/ v/$1/</p>
<p></code></p>
<p>To match &#8216;acap&#8217;, we must send some data that matches the expression after between the first pipes. It is trivial to write such a match : \* ACAP (IMPLEMENTATION &#8220;CommuniGate Pro ACAP 3.3&#8243;) would be identified as acap version 3.3. However, there are a couple of thousand fingerprints on the Null probe, and I want to randomly use them all. Therefore, I wrote a tool to reverse the regexps and put them into a python declaration. </p>
<h2>Regexp reverse engineering</h2>
<p>I was surprised to find that I could not locate any existing library to reverse regular expressions in the way I wanted : from a regexp, create ONE simple string that matches it. The closest I could find was a perl implementation which found as many matches it could given a regexp and a fixed length. Therefore, I wrote my own tool. </p>
<p>Maybe it is pretty simple to reverse a regexp, if you are a great programmer who knows what you are doing. It took me a while, though &#8211; and still I used the parts building the object-tree represention of the regexp from the built-in python regexp implementation. Basically, it does this :<br />
* Remove all optional groups (foo)* => gone<br />
* Insert 1 for digits, insert a for alpha, etc&#8230;<br />
* Insert the first char in any group-of-characters [abcd] => a<br />
* Insert the first in any OR (abc|def) => abc<br />
&#8230; the list goes on a bit. It gets tricky when it comes to group-references and stuff. The source is available at <a href="http://martin.swende.se/hgwebdir.cgi/pxeger/file/tip/Revexpy.py">http://martin.swende.se/hgwebdir.cgi/pxeger/file/tip/Revexpy.py</a></p>
<h2>Putting it together</h2>
<p>So, did it work? Well, yes :<br />
<code lang="bash">#: nmap -p 82 66.249.7.26 -sV</p>
<p>PORT   STATE SERVICE VERSION<br />
82/tcp open  ftp     Xitami ftpd</p>
<p>...again...</p>
<p>PORT   STATE SERVICE VERSION<br />
82/tcp open  smtp    (Wanadoo blocks smtp - NOT A REAL smtpd!)</p>
<p>...again...</p>
<p>PORT   STATE SERVICE VERSION<br />
82/tcp open  nngs    No Name Go Server<br />
</code></p>
<p>Alas, also no. After a while, the python process died &#8211;  probably because it was running on a machine with 128 MB of memory, which it had to share with Apache and Mysql&#8230; </p>
<h2>Disclaimer</h2>
<p>While this was a really fun project which touched on a lot of interesting fields, I did not do it as a security-tool to actually use in a real scenario.</p>
<p>All the codez are available at:<br />
<a href="http://martin.swende.se/hgwebdir.cgi/fuzzywall/">http://martin.swende.se/hgwebdir.cgi/fuzzywall/</a><br />
<a href="http://martin.swende.se/hgwebdir.cgi/pxeger/">http://martin.swende.se/hgwebdir.cgi/pxeger/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2010/01/python-packet-play/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Uppe igen</title>
		<link>http://www.swende.se/index.php/2009/11/hello-world/</link>
		<comments>http://www.swende.se/index.php/2009/11/hello-world/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 22:03:27 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wp.swende.se/wordpress/?p=1</guid>
		<description><![CDATA[Nu har jag återigen bytt CMS. Har gått igenom en del nu, körde på Serendipity (s9y) ett tag, sedan pluck, sedan lite django eftersom jag gärna ville köra Python. Har dock slutligen fastnat för WordPress. Hoppas jag inte behöver byta igen. Kommer inte uppdatera detta så ofta, detta är mest för att kunna publicera lite [...]]]></description>
			<content:encoded><![CDATA[<p>Nu har jag återigen bytt CMS. Har gått igenom en del nu, körde på Serendipity (s9y) ett tag, sedan pluck, sedan lite django eftersom jag gärna ville köra Python. Har dock slutligen fastnat för WordPress. Hoppas jag inte behöver byta igen. Kommer inte uppdatera detta så ofta, detta är mest för att kunna publicera lite verktyg och saker. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.swende.se/index.php/2009/11/hello-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

