“sc” no Windows Server 2022 retorna “Access is denied” ao iniciar/parar serviços como não‑administrador (como corrigir com segurança)

Após migração para o Windows Server 2022, o sc \\servidor start|stop pode passar a retornar “Access is denied” para contas que não são administradoras. Este guia mostra a causa real e como habilitar o controle remoto de serviços com segurança e mínimo privilégio.

Índice

Visão geral do problema

Ambiente típico: em servidores Windows Server 2016, um grupo do AD (não‑administrador local) conseguia iniciar e parar um serviço remotamente, por exemplo:

sc \\SRV01 stop <ServiceName>
sc \\SRV01 start <ServiceName>

Após migrar esses hosts para Windows Server 2022:

  • sc \\SRV01 query <ServiceName> continua funcionando para o mesmo grupo (consulta de status).
  • sc \\SRV01 start|stop <ServiceName> falha com Access is denied, apesar de o DACL do serviço (definido por GPO) conceder Start/Stop.
CenárioComandoResultadoMotivo
Antes (WS 2016)sc \\SRV01 start SpoolerSucessoDACL do serviço concedia Start/Stop e era respeitada remotamente.
Depois (WS 2022)sc \\SRV01 start SpoolerAccess is deniedFortalecimento de segurança do SCM para chamadas remotas por não‑administradores.
Consulta no WS 2022sc \\SRV01 query SpoolerSucessoConsulta exige apenas ServiceQueryStatus, que segue permitido.

Causa raiz: mudança de segurança do SCM

Desde versões mais recentes do Windows (linha Windows 10/Server 2016 a partir de 1709 e posteriores, incluindo Server 2022), o Service Control Manager (SCM) passou a impor uma verificação adicional em chamadas remotas para operações sensíveis. Especificamente:

  • Chamadores remotos que não pertencem ao grupo de Administradores locais são bloqueados ao pedir direitos como SERVICESTART e SERVICESTOP, mesmo que o DACL do serviço conceda essas permissões.
  • Leituras como SERVICEQUERYSTATUS permanecem funcionais, por isso sc query segue funcionando.
  • A verificação adicional não afeta chamadas locais (por exemplo, dentro de uma sessão RDP ou PowerShell Remoting já no servidor), nas quais apenas o DACL do serviço é avaliado.

Em resumo: o DACL continua necessário, mas por si só não basta para permitir start/stop remotos feitos por não‑administradores no Windows Server 2022.

Solução recomendada (menor privilégio)

A correção segura segue dois pilares: (1) manter o DACL do serviço deliberadamente restrito e (2) isentar apenas os serviços necessários da nova verificação remota.

Passo 1 — Assegure o DACL correto no serviço

Garanta que o(s) grupo(s) de utilizadores que devem operar o serviço possuam Start e Stop no DACL do serviço. A forma mais consistente é via GPO:

  1. Abrir o Group Policy Management e editar um GPO vinculado às OU dos servidores de destino.
  2. Navegar até Computer Configuration > Policies > Windows Settings > Security Settings > System Services.
  3. Selecionar o serviço em questão (por exemplo, Print Spooler), marcar Define this policy setting e ajustar as permissões para o grupo (por exemplo, DOMÍNIO\OperadoresDeImpressão) permitindo Start e Stop.
  4. Aplicar o GPO e forçar atualização (gpupdate /force ou aguardar o ciclo normal).

Observações:

  • Você pode optar por SDDL se preferir aplicar via Security Templates ou automação; apenas certifique‑se de incluir os ACEs correspondentes a Start/Stop.
  • Valide localmente (RDP/console) com a conta não‑admin: se localmente for possível iniciar/parar, o DACL está correto e a falha remota se deve à verificação adicional do SCM.

Passo 2 — Isente os serviços necessários da verificação remota

No(s) servidor(es) de destino, inclua o ServiceName (não o Display Name) na lista de isenção de verificação remota do SCM. Essa lista é um valor REGMULTISZ onde cada entrada é um nome de serviço:

Chave:   HKLM\SYSTEM\CurrentControlSet\Control\SecurePipeServers\SCM
Valor:   RemoteAccessCheckExemptionList (REGMULTISZ)
Conteúdo: uma ou mais linhas com &lt;ServiceName&gt;
Exemplo: 
Spooler
Dhcp

Importante:

  • Use o ServiceName que aparece em Get-Service (coluna Name) ou sc getkeyname. Exemplos: Spooler (e não “Print Spooler”), Dnscache, W32Time.
  • Um reinício do servidor é necessário para que a isenção tenha efeito (o SCM é um componente fundamental do sistema).
  • A isenção não ignora o DACL. O controle de acesso do serviço continua sendo aplicado.

Exemplo em PowerShell (executar como Administrador no servidor)

New-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurePipeServers\SCM' -Force | Out-Null
New-ItemProperty `
  -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurePipeServers\SCM' `
  -Name 'RemoteAccessCheckExemptionList' `
  -PropertyType MultiString `
  -Value 'Spooler' `
  -Force | Out-Null

Restart-Computer 

Exemplo adicionando múltiplos serviços sem sobrescrever entradas existentes

$key  = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurePipeServers\SCM'
$name = 'RemoteAccessCheckExemptionList'
$add  = @('Spooler','Dhcp','W32Time')  # ServiceName(s) desejados

New-Item -Path \$key -Force | Out-Null
\$current = (Get-ItemProperty -Path \$key -Name \$name -ErrorAction SilentlyContinue).\$name
if (-not \$current) { \$current = @() }
\$merged = (\$current + \$add) | Where-Object { $\ -and ($\ -is \[string]) } | ForEach-Object { $\_.Trim() } | Select-Object -Unique

New-ItemProperty -Path \$key -Name \$name -PropertyType MultiString -Value \$merged -Force | Out-Null
Write-Host "Lista final de isenção:" -NoNewline; \$merged

Reiniciar depois que todas as alterações forem aplicadas

Passo 3 — Teste remoto após reinício

sc \\SRV01 stop Spooler
sc \\SRV01 start Spooler

Se as permissões do serviço estiverem corretas (Passo 1) e o ServiceName estiver na isenção (Passo 2), usuários não‑administradores listados no DACL poderão iniciar/parar o serviço remotamente via sc.

Alternativa somente para diagnóstico (não recomendado em produção)

Para confirmar rapidamente que a política de endurecimento é, de fato, a causa, você pode desabilitar globalmente a verificação remota. Crie o valor abaixo e reinicie o servidor:

Chave:   HKLM\System\CurrentControlSet\Control
Valor:   RemoteAccessExemption (DWORD)
Dados:   1  = desativa a verificação globalmente
         0  = mantém o comportamento seguro (padrão)

Se após essa mudança o sc start|stop passar a funcionar, volte o valor para 0 e aplique a solução aprovada (isenção por serviço + DACL). A isenção global amplia a superfície de ataque e não deve permanecer ativa em ambientes de produção.

Boas práticas e verificações complementares

Use o ServiceName correto

O sc e o registro exigem o ServiceName (nome interno). Para evitar erros:

# Em PowerShell:
Get-Service | Sort-Object Name | Select-Object Name, DisplayName, Status

No prompt:

sc getkeyname "Print Spooler" </code></pre>

<h3>Confirme o firewall do servidor</h3>
<p>As chamadas do <code>sc</code> usam RPC/RPC‑EPMAP. Habilite as regras de entrada do grupo <em>Remote Service Management</em> (pode ser por GPO):</p>
<pre><code>Enable-NetFirewallRule -DisplayGroup "Remote Service Management"
</code></pre>

<h3>Valide localmente (prova do DACL)</h3>
<p>Logue no servidor (RDP/console) com a conta não‑admin e tente:</p>
<pre><code>Start-Service Spooler
Stop-Service Spooler
</code></pre>
<p>Se localmente funciona e remotamente falha, o DACL foi aplicado; falta a isenção da verificação remota.</p>

<h3>Logs úteis para troubleshooting</h3>
<ul>
  <li><strong>System &gt; Service Control Manager</strong>: eventos como 7035/7036 (controles Enviar/Receber, estados Iniciado/Parado) e 7009/7011 (timeouts) ajudam a confirmar a execução do start/stop.</li>
  <li><strong>Security</strong>: com auditoria de <em>Object Access</em> habilitada (Outros eventos de acesso a objeto), você pode observar tentativas de acesso negadas ao SCM/serviço.</li>
</ul>

<h2>Como aplicar por GPO em larga escala</h2>
<h3>Permissões de serviço (System Services)</h3>
<ol>
  <li>GPO: <em>Computer Configuration &gt; Policies &gt; Windows Settings &gt; Security Settings &gt; System Services</em>.</li>
  <li>Defina o serviço e marque explicitamente <em>Start</em>/<em>Stop</em> para os grupos desejados.</li>
</ol>

<h3>Isenção por serviço (Registry Preferences)</h3>
<ol>
  <li>No mesmo GPO, em <em>Computer Configuration &gt; Preferences &gt; Windows Settings &gt; Registry</em>.</li>
  <li>Crie um item <strong>New &gt; Multi‑String Value</strong>:
    <ul>
      <li><em>Action</em>: <strong>Update</strong> (para mesclar com o que já existir).</li>
      <li><em>Hive</em>: <code>HKEYLOCALMACHINE</code></li>
      <li><em>Key Path</em>: <code>SYSTEM\CurrentControlSet\Control\SecurePipeServers\SCM</code></li>
      <li><em>Value name</em>: <code>RemoteAccessCheckExemptionList</code></li>
      <li><em>Value data</em>: uma linha por <em>ServiceName</em> (ex.: <code>Spooler</code>, <code>Dhcp</code>).</li>
    </ul>
  </li>
  <li>Considere usar <em>Item-level targeting</em> para aplicar a sub‑conjuntos (por OU, grupo de segurança, atributos do computador etc.).</li>
</ol>

<h3>Reinício controlado</h3>
<p>Combine a implementação com uma janela de manutenção e orquestração de reinício (ex.: ordem por criticidade, dependências entre serviços, comunicação aos usuários).</p>

<h2>Alternativas de operação remota e suas limitações</h2>
<ul>
  <li><strong>PowerShell Remoting</strong> (WinRM): ao abrir uma sessão no servidor e executar <code>Start‑Service</code> ou <code>Stop‑Service</code>, a chamada ao SCM passa a ser <em>local</em> dentro do host remoto. Nesse caso, a verificação “não‑admin remoto” não se aplica; ainda assim, o DACL do serviço precisa conceder a operação.</li>
  <li><strong>WMI/CIM</strong> com <code>Win32_Service</code>: a operação remota costuma trafegar via RPC e também é afetada pelas políticas de endurecimento; prefira a abordagem por isenção ou execute localmente via <em>Invoke-Command</em>.</li>
  <li><strong>Ferramentas de automação/monitoramento</strong>: ajuste para usar contas de serviço mínimas e explícitas, documentando quais serviços constam na isenção.</li>
</ul>

<h2>Checklist de verificação rápida</h2>
<table>
  <thead>
    <tr>
      <th>Pergunta</th>
      <th>Como verificar</th>
      <th>Esperado</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>O grupo tem <em>Start/Stop</em> no DACL do serviço?</td>
      <td>System Services (GPO) ou <code>sc sdshow &lt;ServiceName&gt;</code></td>
      <td>ACE do grupo presente com direitos de <em>Start</em>/<em>Stop</em>.</td>
    </tr>
    <tr>
      <td>O <em>ServiceName</em> está na isenção?</td>
      <td>Registro: <code>...SecurePipeServers\SCM\RemoteAccessCheckExemptionList</code></td>
      <td>Nome listado (uma linha por serviço).</td>
    </tr>
    <tr>
      <td>O firewall permite <em>Remote Service Management</em>?</td>
      <td><code>Get-NetFirewallRule -DisplayGroup "Remote Service Management"</code></td>
      <td>Regras de entrada <em>Enabled=True</em>.</td>
    </tr>
    <tr>
      <td>Foi feito reinício após mudanças?</td>
      <td>Janela de manutenção/Histórico de eventos</td>
      <td>Reinicialização concluída após edição do registro.</td>
    </tr>
    <tr>
      <td>Localmente (RDP/WinRM) funciona?</td>
      <td><code>Start-Service/Stop-Service</code> dentro do servidor</td>
      <td>Sucesso — comprova DACL correto.</td>
    </tr>
  </tbody>
</table>

<h2>Exemplos práticos</h2>

<h3>Exemplo A — Habilitar operação remota do Spooler para um grupo do AD</h3>
<ol>
  <li>GPO: em <em>System Services</em>, dê <em>Start</em>/<em>Stop</em> do <em>Print Spooler</em> ao grupo <code>DOMÍNIO\SuporteImpressão</code>.</li>
  <li>GPP: adicione <code>Spooler</code> ao <code>RemoteAccessCheckExemptionList</code> (Multi‑SZ).</li>
  <li>Reinicie o servidor de impressão.</li>
  <li>Teste do posto de suporte:
    <pre><code>sc \\PRINT01 stop Spooler
sc \\PRINT01 start Spooler

Exemplo B — Vários serviços críticos, rollout em larga escala

Para dezenas de servidores, liste os nomes em um arquivo e aplique por PowerShell Remoting:

$servers = Get-Content .\servidores.txt
$servicesToAllow = @('Spooler','Dhcp','W32Time','Dnscache')

\$script = {
param(\$servicesToAllow)
\$key  = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurePipeServers\SCM'
\$name = 'RemoteAccessCheckExemptionList'
New-Item -Path \$key -Force | Out-Null
\$cur = (Get-ItemProperty -Path \$key -Name \$name -ErrorAction SilentlyContinue).\$name
if (-not \$cur) { \$cur = @() }
\$merged = (\$cur + \$servicesToAllow) | ForEach-Object { \$.Trim() } | Where-Object { \$ } | Select-Object -Unique
New-ItemProperty -Path \$key -Name \$name -PropertyType MultiString -Value \$merged -Force | Out-Null
}

Invoke-Command -ComputerName \$servers -ScriptBlock \$script -ArgumentList (,\$servicesToAllow)

Programe um reinício conforme sua janela de manutenção

Comparativo: comportamento por versão

VersãoChamadas remotas Start/Stop por não‑adminsRequisitoNotas
Windows Server 2012 R2Normalmente permitidas se DACL concederDACL do serviçoSem verificação adicional do SCM para esse caso.
Windows Server 2016 (RTM)Permitidas se DACL concederDACL do serviçoComportamento semelhante ao 2012 R2 no RTM.
WS 2016 (1709+) / 2019 / 2022Bloqueadas por padrãoDACL + Isenção por serviço (RemoteAccessCheckExemptionList) ou desativação global (não recomendado)Consulta (sc query) segue permitida.

Erros comuns e como evitar

  • Usar o Display Name no lugar do ServiceName: “Print Spooler” não funciona em registro nem no sc. O nome certo é Spooler.
  • Esquecer do reinício: a lista de isenção só passa a valer após reinicializar o host.
  • Substituir o Multi‑SZ acidentalmente: em GPP, use Update para mesclar; Replace apaga os valores anteriores.
  • Pensar que a isenção ignora permissões: não ignora. Sem DACL correto, continuará falhando (local ou remotamente).
  • Confundir ferramentas: net stop pode funcionar localmente por caminhos diferentes, mas não soluciona a política do SCM para chamadas remotas.

Segurança: por que a solução é segura?

A abordagem proposta mantém o princípio do menor privilégio:

  1. Escopo mínimo: apenas serviços listados podem ser controlados remotamente por não‑admins.
  2. DACL ainda manda: somente quem consta no DACL do serviço com os direitos apropriados executa Start/Stop.
  3. Auditabilidade: os eventos de start/stop continuam registrados. É possível habilitar auditoria para acessos ao SCM e a serviços específicos.
  4. Reversibilidade: remover o serviço do Multi‑SZ (e reiniciar) revoga imediatamente a capacidade remota.

Diagnóstico rápido do “Access is denied”

  1. Execute whoami na estação que chama o sc e confira o grupo do AD esperado.
  2. Confirme o ServiceName exato: Get-Service Spooler ou sc getkeyname "Print Spooler".
  3. Valide o DACL via GPO ou sc sdshow <ServiceName>.
  4. Cheque a presença no Multi‑SZ RemoteAccessCheckExemptionList.
  5. Garanta que o firewall permita Remote Service Management.
  6. Revise os eventos 7035/7036 (System) e possíveis falhas no Security.

Como reverter

  • Remova o(s) nome(s) de serviço da lista RemoteAccessCheckExemptionList e reinicie o servidor.
  • Opcionalmente, ajuste o DACL no GPO para retirar Start/Stop do grupo se a operação não for mais necessária.

Perguntas frequentes

Por que query funciona e start/stop não?
Porque a consulta requer direito de leitura (ServiceQueryStatus), que a política não bloqueia. Iniciar/parar são operações elevadas e sofrem a verificação extra para chamadas remotas de não‑admins.

Posso contornar usando WMI/CIM?
Não de forma segura. As chamadas remotas para controlar serviços continuam sujeitas ao endurecimento. A solução correta é a isenção por serviço + DACL.

PowerShell 7 não tem -ComputerName em Start-Service. E agora?
Use Invoke-Command (WinRM) para executar Start-Service/Stop-Service dentro do servidor. Ainda assim, o DACL deve permitir a operação.

Preciso reiniciar mesmo?
Sim. O SCM aplica a lista de isenções na inicialização. Programe a alteração dentro de uma janela de manutenção.

É perigoso ativar a isenção global?
Sim, aumenta o risco. Use apenas para diagnóstico, por tempo limitado, e restaure o valor padrão em seguida.

Resumo executivo

  • No Windows Server 2022, o “Access is denied” ao usar sc para iniciar/parar serviços como não‑admin é consequência de um fortalecimento do SCM para chamadas remotas.
  • Mantenha o DACL do serviço via GPO e isente somente os serviços necessários no RemoteAccessCheckExemptionList.
  • Evite a desativação global; use‑a apenas para confirmar a causa.
  • Cheque firewall, garanta o ServiceName correto e valide pelos logs.

Apêndice: comandos úteis

# Ver o status remoto (ainda funciona sem isenção)
sc \\SRV01 query Spooler

Parar/Iniciar remoto (requer DACL + isenção por serviço)

sc \SRV01 stop Spooler
sc \SRV01 start Spooler

Ver/definir SDDL do serviço (cautela!)

sc sdshow Spooler
sc sdset Spooler \

Confirmar regras de firewall

Get-NetFirewallRule -DisplayGroup "Remote Service Management" | Format-Table -Auto

Listar ServiceName x DisplayName

Get-Service | Sort Name | Format-Table Name,DisplayName,Status -Auto

Ver o Multi‑SZ atual

Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurePipeServers\SCM' -Name RemoteAccessCheckExemptionList 

Com esse passo a passo, você devolve ao time de operações a capacidade de administrar serviços remotamente no Windows Server 2022 — de forma segura, auditável e alinhada ao princípio do menor privilégio.

Índice