AndrewNohawk
General

Facebook GraphAPI and Maltego

So a while back facebook released their graph API a way for websites and other to integrate with facebook, things like:

  • Searching
  • Profile enumeration ( status / feed / info )
  • Friend enumeration

You can read the entirety of the functions at the Graph API documentation section on facebook.

So the first thing you notice is that certain functions are immediately limited ( call it the juicy section if you want ) such as viewing friends or getting full profile information, for these you need to auth , which immediately limits them from use in the public space ( unless of course we ask for username and password everytime – perhaps in the future ).

So we are left with search, and after a bit of messing with it, it turns out its a *super* method for searching public data on facebook, eg: if you want to search for something like ‘Maltego’ you can simply go to: https://graph.facebook.com/search?q=%22Maltego%22

Then you get a basic JSON reply and from there its game over, what IS interesting however is that if you look at the JSON you notice that it shows the user information as well:

"data": [
      {
         "id": "<ID>",
         "from": {
            "name": "<name>",
            "id": "<ID>"
         },
         "message": "I learned about this program in a security class
I took yesterday...It's amazing what you can find out there on the
internet. I suggest you keep your personal info as safe as
possible :)",
         "picture": "http://external.ak.fbcdn.net/safe_image.php?
d=35edd425da4428331e33664fc02a9544&w=90&h=90&url=
http%3A%2F%2Fwww.paterva.com%2Fweb5%2Fimg%2Fchicken.png",
         "link": "http://www.paterva.com/web5/",
         "name": "Maltego 3",
         "caption": "www.paterva.com",
         "icon": "http://static.ak.fbcdn.net/rsrc.php/zD/r/
aS8ecmYRys0.gif",
         "type": "link",
         "created_time": "2010-10-08T15:37:50+0000",
         "updated_time": "2010-10-08T16:21:50+0000"
      }

So now not only can you view what was said about term <x> on facebook, but you can ALSO see who said it, so why is this interesting for use with Maltego? Well imagine you had a few phrases you were searching for, resulting in say 255 ‘facebookObjects’ ( like the one above ) for each phrase. Well then using a spreadsheet or some other non graphical form would take forever, however with Maltego you would very quickly be able to identify people who are talking about all of your phrases.

So how do we take these results to a Maltego transform? To be honest, in php it is about 30 minutes of work! ( also, please note i actually commented stuff :P ). NOTE: I know it breaks on some things and i’ll look into it if people find this useful, for now i just want to show how easy it is to integrate practically anything with Maltego :)

<?php
//include our MaltegoTDS class(es) – available from http://www.paterva.com/web5/TDS/
include_once(“Maltego.php”);
//set return content-type to be XML
header (“content-type: text/xml”);
$maltegoInput = new MaltegoTransformInput();
$maltegoTransform = new MaltegoTransformResponse();
$resultsFound = 0;
$foundEnts = array();

/*
Get Page – fetch the facebook Graph API search page and create facebookObjects with the results
-url: URL to browse to
-maltegoTransform: maltego transform object ( to add entities )
-sliderValue: the slider value sent from Maltego to let us know how many results
-resultsFound: the number of results (yes yes, i know this should be a global with the maltegoTransform too – but i am lazy )
*/
function getPage($url,$maltegoTransform,$sliderVal,$resultsFound)
{
//Standard CURL stuff to get the Page
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_FAILONERROR, 0);
curl_setopt($ch, CURLOPT_URL, $url);
$returned = curl_exec($ch);
curl_close ($ch);

//Convert the response from JSON into an associative array
$returned = json_decode($returned,TRUE);

//Just the posts section
$posts = $returned[“data”];

if(is_array($posts))
{
foreach($posts as $p)
{
$resultsFound++; // I know right :P
if($resultsFound <= $sliderVal)
{
$userDetails = $p[“from”]; // User stuff <id> and <name>
$ent = $maltegoTransform->addEntity(“facebook.Object”,”change”); // add our facebook.Object entity
$ent->setIconURL(“http://graph.facebook.com/” . $userDetails[“id”] . “/picture”); // cool way to get the profile picture!
$ent->setDisplayInformation(“<a href=’http://www.facebook.com/profile.php?id=” . $userDetails[“id”] . “‘>http://www.facebook.com/profile.php?id=” . $userDetails[“id”]); // Add a link so you can go view the profile in your web browser
foreach($p as $key=>$value)
{
//Just add the stuff we get back – this might change, so lets take it all, it also means transforms can extend from here
if(!is_array($value))
{
$value = trim(htmlspecialchars($value));
$ent->addAdditionalFields($key,$key,”false”,$value);
}
else
{
//Wow i realise this code sucks, and should be function to do the array stuff, but meh.
foreach($value as $k=>$v)
{
if(!is_array($v))
{
$v = htmlspecialchars($v);
$ent->addAdditionalFields($key . “.” . $k,$key . “.” .$k,”false”,$v);
}
else
{
foreach($v as $kk=>$vv)
{
if(!is_array($vv))
{
$vv = htmlspecialchars($vv);
$ent->addAdditionalFields($k . “.” . $kk,$k . “.” .$kk,”false”,$vv);
}
}
}
}
}
}
//Add it to our list of found ents
$foundEnts[] = $ent;
//So for each ‘type’ of object found, set the
switch ($p[“type”])
{
case “link”:
case “status”:
case “photo”:
@$ent->setValue(($p[“message”]));
break;

//Sometimes u get the name / description — SOMETIMES.
case “video”:
if(isset($p[“name”]))
{
@$ent->setValue(($p[“name”]));
}
elseif(isset($p[“description”]))
{
@$ent->setValue(($p[“description”]));
}
else
{
@$ent->setValue((“No Character”));
}
break;

}

}

if(count($foundEnts) == 0)
{
$maltegoTransform->addException(“No search results found!”);
$maltegoTransform->throwExceptions();
}
else
{
//just strip the values so our graph doesn’t look messy – dont worry its added as an additional field anyway :)
$maxLen = 20;
foreach($foundEnts as $f)
{

if(strlen($f->value) > $maxLen)
{
$f->setValue(substr($f->value,0,$maxLen) . “…”);
}
$f->setValue(htmlspecialchars(str_replace(“\n”,””,$f->value)));
}

}

}
}
//If we haven’t got enough results and we can go to the next page, do that.
if($resultsFound < $sliderVal)
{
if(isset($returned[“paging”]))
{
$pages=$returned[“paging”];
if($pages[“next”])
{
getPage($pages[“next”],$maltegoTransform,$sliderVal,$resultsFound);
}
}
}

}

//Get our term, url encode it and call the above function, once it returns, display output
if ($maltegoInput->getEntity() )
{
$sliderVal = $maltegoInput->slider;
$term = urlencode($maltegoInput->value);
getPage(“https://graph.facebook.com/search?q=” . $term . “&type=post”,$maltegoTransform,$sliderVal,$resultsFound);
$maltegoTransform->returnOutput();
}
else
{
$maltegoTransform->addException(“No input entity found”);
$maltegoTransform->throwExceptions();
}

?>

So there we have it, a TDS transform up and running… well almost, all thats required is that you load up a graph with the facebook.Object entity type and import it, its a 5 second thing, and you can grab the graph here.

Next you can simply discover the facebook transforms via the seed on the TDS- “https://cetas.paterva.com/TDS/runner/showseed/facebookGraphAPI”:

  1. Click Manage in the ribbon at the top
  2. Click Discover transforms
  3. Add the seed with the name “FacebookGraphAPI” and the URL “https://cetas.paterva.com/TDS/runner/showseed/facebookGraphAPI”
  4. next->next->next->next->finish
  5. Use it!

Heres an example i did with the Phrases “Julius Malema” (ANC youth league president) and “Jacob Zuma” (ANC president):

facebookGraphAPI-example1

facebookGraphAPI-example1

Grab this graph

Let me know what you think!

Comments

  1. Thanks mate .

Leave a Reply

Your email address will not be published. Required fields are marked *