In Active Directory environments, the objectSid
attribute stores security identifiers (SIDs) in a binary format that's typically base64-encoded when retrieved via LDAP. The human-readable SID format (like S-1-5-21-1270179133-2928470170-2248674342-4324
) is what administrators commonly work with.
Here's a complete solution to convert the base64-encoded objectSid
to human-readable format on Linux:
#!/bin/bash
# Extract and decode objectSid
OBJECT_SID="AQUAAAAAAAUVAAAAPWW1S5rojK4mDAiG5BAAAA=="
echo $OBJECT_SID | base64 -d | xxd -ps -u | sed -e 's/$..$/\\x\1/g' | xargs -0 printf "%s" | xxd -ps -u | sed -e 's/^00//' -e 's/$........$$....$$....$$.*$/S-1-\1-\2-\3-\4/' -e 's/$..$$..$$..$$..$/\4\3\2\1/g' -e 's/$..$$..$/\2\1/g' -e 's/^/S-1-/' -e 's/-$[0-9A-F]\{8\}$/-\1/g' -e 's/$[0-9A-F]\{4\}$$/0x\1/g' | awk -F '-' '{for (i=2;i<=NF;i++) {if ($i ~ /^0x/) printf "-%d",strtonum($i); else printf "-%d",strtonum("0x"$i);} printf "\n";}'
The conversion involves several steps:
- Base64 decoding the objectSid
- Converting to hexadecimal representation
- Parsing the SID structure components
- Formatting into the human-readable SID string
For more maintainable code, here's a Python solution:
import base64
import struct
def convert_object_sid(object_sid):
binary = base64.b64decode(object_sid)
revision = struct.unpack('B', binary[0:1])[0]
sub_authority_count = struct.unpack('B', binary[1:2])[0]
identifier_authority = struct.unpack('>Q', b'\x00\x00' + binary[2:8])[0]
sub_authorities = struct.unpack('<%dI' % sub_authority_count, binary[8:8+4*sub_authority_count])
sid = 'S-%d-%d' % (revision, identifier_authority)
for sub_authority in sub_authorities:
sid += '-%d' % (sub_authority)
return sid
# Example usage
print(convert_object_sid("AQUAAAAAAAUVAAAAPWW1S5rojK4mDAiG5BAAAA=="))
Here's how to combine this with your original ldapsearch command:
ldapsearch -LLL -H ldap://dc.example.com:389 -b dc=example,dc=lk -D example\\administrator -w adminPassword "(sAMAccountName=bob)" objectSid | awk '/objectSid::/ {print $2}' | base64 -d | xxd -ps -u | sed -e 's/$..$/\\x\1/g' | xargs -0 printf "%s" | xxd -ps -u | sed -e 's/^00//' -e 's/$........$$....$$....$$.*$/S-1-\1-\2-\3-\4/' -e 's/$..$$..$$..$$..$/\4\3\2\1/g' -e 's/$..$$..$/\2\1/g' -e 's/^/S-1-/' -e 's/-$[0-9A-F]\{8\}$/-\1/g' -e 's/$[0-9A-F]\{4\}$$/0x\1/g' | awk -F '-' '{for (i=2;i<=NF;i++) {if ($i ~ /^0x/) printf "-%d",strtonum($i); else printf "-%d",strtonum("0x"$i);} printf "\n";}'
When working with Active Directory through LDAP queries, you'll often encounter the objectSid
attribute, which represents security identifiers in binary format. The challenge is converting this Base64-encoded value into the standard SID format (e.g., S-1-5-21-...) that administrators recognize.
A typical LDAP query might return something like:
objectSid:: AQUAAAAAAAUVAAAAPWW1S5rojK4mDAiG5BAAAA==
You'll need these Linux packages:
sudo apt-get install ldap-utils python3
pip install pyasn1
Here's a reliable Python solution:
import base64
import struct
def convert_binary_sid_to_string(binary_sid):
version = struct.unpack('B', binary_sid[0:1])[0]
sub_authority_count = struct.unpack('B', binary_sid[1:2])[0]
identifier_authority = struct.unpack('>Q', b'\x00\x00' + binary_sid[2:8])[0]
sub_authorities = struct.unpack('<' + 'L' * sub_authority_count, binary_sid[8:8 + 4 * sub_authority_count])
sid = 'S-{0}-{1}'.format(version, identifier_authority)
for sub_auth in sub_authorities:
sid += '-{0}'.format(sub_auth)
return sid
# Usage:
base64_sid = "AQUAAAAAAAUVAAAAPWW1S5rojK4mDAiG5BAAAA=="
binary_sid = base64.b64decode(base64_sid)
print(convert_binary_sid_to_string(binary_sid))
For quick conversions in shell:
echo "AQUAAAAAAAUVAAAAPWW1S5rojK4mDAiG5BAAAA==" | base64 -d | xxd -ps | sed -e 's/$..$/\1 /g' -e 's/^ //' | awk '{
printf "S-%d", strtonum("0x" $1);
printf "-%d", strtonum("0x" sprintf("%02s%02s%02s%02s%02s", $7, $6, $5, $4, $3, $2));
for(i=8; i<=NF; i+=4) {
printf "-%d", strtonum("0x" sprintf("%02s%02s%02s%02s", $(i+3), $(i+2), $(i+1), $i));
}
print "";
}'
Combine the conversion with your original query:
ldapsearch -LLL -H ldap://dc.example.com:389 -b dc=example,dc=com -D example\\administrator -w password "(sAMAccountName=bob)" | \
awk '/objectSid::/ {print $2}' | \
base64 -d | \
xxd -ps | \
sed -e 's/$..$/\1 /g' -e 's/^ //' | \
awk '{
printf "S-%d", strtonum("0x" $1);
printf "-%d", strtonum("0x" sprintf("%02s%02s%02s%02s%02s", $7, $6, $5, $4, $3, $2));
for(i=8; i<=NF; i+=4) {
printf "-%d", strtonum("0x" sprintf("%02s%02s%02s%02s", $(i+3), $(i+2), $(i+1), $i));
}
print "";
}'
Error: "Invalid base64 input"
Fix: Ensure the objectSid is properly extracted. Some LDAP outputs include spaces or line breaks.
Error: Incorrect SID format
Fix: Verify the byte ordering in your conversion script matches the SID structure specification.