Remoting with PyAMF - the easy way
Aahh, Remote Procedure Calls. Gotta love ‘em. They make programmers forget all we have taught them about being careful with user input, sanitising everything and double checking that there’s nothing malicious in it, treating all user input as a potential threat against their system. Ok, frankly, most of the times developers tend to forget about this in all other scenarios too, or we wouldn’t still be plagued with XSS and the like.
But RPC, in whatever shape it comes, makes it a lot easier to forget about user input because it is more or less transparent to the developer. I mean, that’s the whole point of RPC, isn’t it? Letting you work with remote functions/methods/objects like they’re local. No worries about network protocols etc. And this is exactly what makes it so dangerous, because developers forget that all the pretty function calls and objects they send over the wire are not necessarily what they receive on the other end. Attackers can, if the data is not encrypted and signed, read and manipulate the data. Or send their own. The receiving end has to make sure that whatever it gets is checked first.
Where was I going with this again? Ah, yes, AMF. Adobe’s Action Message Format. It’s a binary format primarily used to serialise ActionScript objects (think RPC for Flash). I had to test a remote installation of an AMF gateway and searched for a decent way of pentesting that stuff. First thing I found was Jon Rose’s Deblaze, a command line tool to interact with Flash remoting end points. It’s a nice tool, but it only allows you to send Ints, Floats or Strings as method parameters. That wasn’t enough for me, as I needed to send more complicated objects to the remote server.
I continued searching and found a blog post about pentesting Adobe Flex Applications with a custom AMF client. They use pyAMF, a Python implementation of AMF. Perfect. The only thing that bothered me was that the way they build their client in the blog post seemed overly complicated. Do I really need to build my AMF object by hand and use an HTTP library to send the POST request to the server? That’s inconvenient for just a little testing.
I looked at the pyAMF homepage myself and found that you don’t have to do all this stuff manually. pyAMF provides a perfectly capable client library, with HTTPS support and authentication. It’s really easy to use. First, import the RemotingService:
from pyamf.remoting.client import RemotingService
Then, all you have to do is create a new RemotingService with the AMF gateway’s URL, get the service you want to use and invoke the method with whatever parameters it takes. Taken straight from pyAMF’s website for a service called “service” with the method “getLanguages()”:
client = RemotingService('http://demo.pyamf.org/gateway/recordset') service = client.getService('service') print service.getLanguages()
And that’s it. Much easier, isn’t it? You can also set custom headers etc. Of course, the approach taken in the abovementioned blog post might be better if you really want to dig more into the AMF internals when testing. But if you primarily want to check if you can invoke methods you shouldn’t be able to access, or call the methods with parameters they might choke on, then the pyAMF client is the way to go.