在Windows上为所有用户从凭据管理器中删除条目

12

我目前正在为Windows的卸载程序实现一个“删除设置”功能,并遇到了一个我甚至不确定是否可能解决的问题。

该应用程序使用CredentialManager(keymgr.dll)为当前用户存储凭据条目。让我们称凭据的目标为“X”。在卸载时,所有针对目标“X”的凭据都应从所有用户中删除。当然,卸载程序需要管理员权限,但我仍然发现这非常难以完成。

对于当前用户,该命令通常通过从命令提示符中输入 cmdkey /delete=:X 解决。据我所知,cmdkey.exe /list 仅帮助列出当前用户的条目,无法删除其他用户的本地条目。

我了解到,这些凭据是存储在C:\Users\_user_\AppData\Local\Microsoft\Credentials文件夹下的操作系统文件,但我无法知道要删除的条目是哪些文件,删除所有文件会对其他应用程序造成风险。此外,我假设删除操作系统文件也会很危险,可能会有限制(额外的UAC提示?)。

runas 命令是我找到的最接近的一个方案,但由于它需要用户密码,因此变得非常困难,也不是我想要在卸载程序中使用的东西。我还需要一种方法来获取每个用户的用户名和域并对它们进行迭代。

我更喜欢使用 cmdpowershell 来实现这个问题。


1
嗨,经过我自己的一些研究,我认为如果您不以拥有凭据的用户身份运行,则无法实现您想要的目标。最多,您只能删除所有存储的凭据... - sodawillow
4个回答

21

不想顶起一篇旧帖,但我需要自己完成这个任务,所以我想着如果有其他人也需要,我就把这个方法写下来:

cmdkey /list | ForEach-Object{if($_ -like "*Target:*" -and $_ -like "*microsoft*"){cmdkey /del:($_ -replace " ","" -replace "Target:","")}} 

一行Powershell命令,将删除任何包含"Microsoft"字符串的凭据。

参考: https://gist.github.com/janikvonrotz/7819990

我运行了它并在本地清除了它,不需要以管理员身份运行(但我是本地管理员)。


2

当从批处理文件或PowerShell命令运行cmdkey.exe实用程序时,可能会遇到两个与特殊字符相关的问题。 1.如果在批处理文件中运行,并且凭据具有没有双引号的“(”或“)”,即左括号和右括号,则该凭据将不会被删除。 2.如果凭据名称(也称为目标名称)由空格包围的连字符,则cmdkey将无法删除或创建具有该字符串“-”的凭据。

已编写一些PowerShell模块来尝试执行此操作,但我发现唯一处理这些例外情况的模块位于Github上 https://github.com/bamcisnetworks/BAMCIS.CredentialManager

BAMCIS.CredentialManager

使用此方法,我能够创建凭据以设置带有括号或连字符的测试环境,但更重要的是通过使用模块命令获取用户缓存凭据列表并将信息传递给删除命令来删除它们。

其中一个注意事项是,在删除命令之后,一段时间后会动态重新出现两个缓存凭据。

因此,为了解决频繁的用户锁定问题,我将尝试在用户上下文中使用SCCM在注销时部署此操作。否则,在删除凭据后可能需要重新启动系统。 以下是一个原型脚本,导入该模块并使用它来移除所有缓存凭据。像往常一样,请测试并自行承担风险!

Clear-host
import-Module "$PSScriptRoot\BAMCIS.CredentialManager\BAMCIS.CredentialManager.psd1"
$L = Get-CredManCredentialList -ErrorAction SilentlyContinue 

If($L -eq $null)
{

  Write-host "No Cached Credentials found to remove, no action taken"
  $LASTEXITCODE = 0
  Write-host "The last exit code is $LASTEXITCODE"


}
Else
{

  ForEach($cred in $L)
  {

    Write-host "`tProcessing...`n"
    Write-host "$($cred.TargetName.ToString())`n"
    Write-host "$($cred.Type.ToString())`n`n"

    $R = Remove-CredManCredential -TargetName  $($cred.TargetName.ToString()) -Type $($cred.Type.ToString()) -Force

  }
  $L = Get-CredManCredentialList -ErrorAction SilentlyContinue -ErrorVariable $Cred_Error

  If($L -eq $null)
  {

    Write-host "All Cached Credentials removed, program Complete"
    $LASTEXITCODE = 0
    Write-host "The last exit code is $LASTEXITCODE"

  }
  Else
  {

    Write-host "WARNING: One or more Cached Credentials were not removed, program Complete"
    $LASTEXITCODE = 1


  }
}

0

批处理,提升的 cmd 提示符:

要查找主要的内容,请列出任何带有 MS.O、Micro 和 teams 的内容:

for /f "tokens=1-4 Delims=:=" %A in ('cmdkey /list  ^| findstr Target: ^| findstr /i "MS.O Micro Teams"') do @echo %D

这会删除所有团队的条目:

for /f "tokens=1-4 Delims=:=" %A in ('cmdkey /list ^| findstr /i teams') do @cmdkey /delete:%D

如果您想将其作为脚本包含,语法会稍有不同。请将 %%A 和 %%D 变量加倍。


0
遇到了类似的问题,需要清除非域加入设备的旧凭据。创建登录任务以清除凭据。在我的情况下,我正在寻找特定的文件服务器,以免意外清除所有凭据。由于将字符串表达式管道传递到任务时存在语法问题,因此更容易创建引用.ps1然后在任务中引用。通过Intune推送了这个脚本....
# Full path of the file
$file = 'C:\script\clearcreds.ps1'
    
#If the file does not exist, create it.
if (-not(Test-Path -Path $file -PathType Leaf)) {
try {
$null = New-Item -Path "C:\ProgramData\CentraStage\Packages" -Name 
"clearcreds.ps1" -ItemType "file" -Value 'cmdkey /list | ForEach-Object{if($_ - 
         like "*Target:*" -and $_ -like "*fileserver*"){cmdkey /del:($_ -replace " ","" -replace "Target:","")}}'
Write-Host "The file [$file] has been created."
             }
         catch {
             throw $_.Exception.Message
         }
     }
#######################################
#Create ScheduledTask to Run at log on.
#######################################
$schtaskName = "Clear Cached Creds "
$schtaskDescription = "Clears Cached Creds for each user at logon."
$trigger = New-ScheduledTaskTrigger -AtLogOn
$class = cimclass MSFT_TaskEventTrigger root/Microsoft/Windows/TaskScheduler
#Execute task in users context
$principal = New-ScheduledTaskPrincipal -GroupId "S-1-5-32-545" -Id "Author"
$action3 = New-ScheduledTaskAction -Execute 'Powershell.exe' "-File C:\script\clearcreds.ps1"
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
$null=Register-ScheduledTask -TaskName $schtaskName -Trigger $trigger -Action   $action3  -Principal $principal -Settings $settings -Description 
$schtaskDescription -Force
Start-ScheduledTask -TaskName $schtaskName

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接