I have been struggling with this for a while, I am trying to find the BitLocker Recovery Keys from AD using PHP, this is part of a tracking tool.
I can access the computer element, and I have access to the keys but when I check for objectClass=msFVE-RecoveryInformation I dont get any data back.
I am accessing the computer element like this:
$adServer = "ADSERVER";
$ldap = ldap_connect( $adServer );
$usernamead = "user";
$password = "pass";
$ldaprdn = 'domina' . "\\" . $usernamead;
ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
ldap_set_option( $ldap, LDAP_OPT_REFERRALS, 0 );
$bind = @ldap_bind( $ldap, $ldaprdn, $password );
$username = $_COOKIE['deviceusername'];
if ( $bind ) {
$filter="(&(Name=computername)(objectClass=computer))";
$result = ldap_search( $ldap, "dc=domain,dc=ads", $filter );
ldap_sort( $ldap, $result, "sn" );
$info = ldap_get_entries( $ldap, $result );
for ( $i=0; $i<$info["count"]; $i++ ) {
if ( $info['count'] > 1 )
break;
print_r($info);
};
}
This is the code part I used in our internal IT support web page. May not be beautiful but it works.
function listKeys($querie_string){
//Allow either the first 8 chars like in the AD Users and Computers or the whole KeyID
$KeyID_regex = "/^(?:[A-F0-9]{8})(?:-(?:[A-F0-9]{4}-){3}[A-F0-9]{12})?$/";
$querie_key = FALSE;
if (preg_match($KeyID_regex,$querie_string,$rgx_result)){
$querie_key = TRUE;
}
//dont forget to define them somewhere!!!
global $host_search_ldap_base_dn, $ldap_host, $ldap_usr_dom, $ldap_search_user, $ldap_search_user_password;
$ldap = ldap_connect($ldap_host);
if($bind = @ldap_bind($ldap, $ldap_search_user.$ldap_usr_dom, $ldap_search_user_password)) {
if ($querie_key == FALSE){
$filter = sprintf("(&(cn=%s)(objectClass=computer))",$querie_string);
$attr = array("dn");
$result = ldap_search($ldap, $host_search_ldap_base_dn, $filter, $attr) or exit("Unable to search host dn on LDAP server");
$entries = ldap_get_entries($ldap, $result);
if ($entries["count"] != 1){
ldap_unbind($ldap);
return sprintf("invalid amount of results %d for querie %s",$entries["count"],$querie_string);
}
}
if ($querie_key == TRUE){
$filter = sprintf("(&(name=*{%s*})(objectClass=msFVE-RecoveryInformation))",$querie_string);
$ldap_dn = $host_search_ldap_base_dn;
} else {
$filter = sprintf("(objectClass=msFVE-RecoveryInformation)",$querie_string);
$ldap_dn = $entries[0]["dn"];
}
$attr = array("msFVE-RecoveryPassword", "name", "distinguishedName");
$result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search for keys on LDAP server");
$entries = ldap_get_entries($ldap, $result);
ldap_unbind($ldap);
$key_list = array();
for ($i = 0;$i<$entries["count"];$i++){
//extract date, time and keyID
$regex = "/(?<date>[0-9]{4}-[0-9]{2}-[0-9]{2})T(?<time>[0-9]{2}:[0-9]{2}:[0-9]{2})(.+)\{(?<keyID>[A-Z0-9\-]+)\}/";
preg_match($regex,$entries[$i]["name"][0],$matches);
//extract computername
$hostname_regex = "/\},CN=(?<computer>.+?),/";
preg_match($hostname_regex,$entries[$i]["distinguishedname"][0],$hostname_matches);
//Create array
$tmp = array();
$tmp["computer"] = $hostname_matches["computer"];
$tmp["date"] = date("Y-m-d H:i:s",strtotime($matches["date"]." ".$matches["time"]));
$tmp["keyID"] = $matches["keyID"];
$tmp["dn"] = $entries[$i]["distinguishedname"][0];
$tmp["name"] = $entries[$i]["name"][0];
$tmp["recoverypassword"] = $entries[$i]["msfve-recoverypassword"][0];
array_push($key_list,$tmp);
}
//TODO Sort by date!!!
return $key_list;
}
}
In the end just iterate over the result if its an array:
$keys = listKeys("myhostname");
if (is_array($keys)){
foreach ($keys as $keyentrie) {
//code goes here
}
}
Hope that helps someone. Downside of this approach is that if you search for a KeyID search takes about 2-5 Seconds to get results. (Our environment hast about 10000 computer objects below the defined LDAP search base)
PS don't forget input sanitation!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With