728x90

Update 2021-12-18 – This looks like a much more competent script for detecting this vulnerability and there is a python version for Linux: https://github.com/CERTCC/CVE-2021-44228_scanner

Updated 2021-12-17 – Script is v1.4 and looks for .war files now too

Original post below

Inspired by the one-liner here: https://gist.github.com/Neo23x0/e4c8b03ff8cdf1fa63b7d15db6e3860b#find-vulnerable-software-windows

gci 'C:\' -rec -force -include *.jar -ea 0 | foreach {select-string "JndiLookup.class" $_} | select -exp Path

I wrote a script to expand on the command, support Windows Server 2008 onward and to be more automated.

This script is basically the one liner with a bit of logic to get all the local fixed disks on a server and iterate through them all looking for Log4j jar file:

<#
.Synopsis
Checks the local system for Log4Shell Vulnerability [CVE-2021-44228]
.DESCRIPTION
Gets a list of all volumes on the server, loops through searching each disk for Log4j stuff
 
Version History
1.0 - Initial release
1.1 - Changed ErrorAction to "Continue" instead of stopping the script
1.2 - Went back to SilentlyContinue, so much noise
Replace attribute -Include by -Filter (prevent unauthorized access exception stopping scan)
Remove duplicate path with Get-Unique cmdlet
.EXAMPLE
.\check_CVE-2021-44228.ps1
.NOTES
Created by Eric Schewe 2021-12-13
Modified by Cedric BARBOTIN 2021-12-14
#>
 
# Get Windows Version string
$windowsVersion = (Get-WmiObject -class Win32_OperatingSystem).Caption
 
# Server 2008 (R2)
if ($windowsVersion -like "*2008*") {
 
$disks = [System.IO.DriveInfo]::getdrives() | Where-Object {$_.DriveType -eq "Fixed"}
 
}
# Everything else
else {
 
$disks = Get-Volume | Where-Object {$_.DriveType -eq "Fixed"}
 
}
 
# I have no idea why I had to write it this way and why .Count didn't just work
$diskCount = $disks | Measure-Object | Select-Object Count -ExpandProperty Count
 
Write-Host -ForegroundColor Green "$(Get-Date -Format "yyyy-MM-dd H:mm:ss") - Starting the search of $($diskCount) disks"
 
foreach ($disk in $disks) {
 
# gci 'C:\' -rec -force -include *.jar -ea 0 | foreach {select-string "JndiLookup.class" $_} | select -exp Path
 
# Server 2008 (R2)
if ($windowsVersion -like "*2008*") {
 
Write-Host -ForegroundColor Yellow " $(Get-Date -Format "yyyy-MM-dd H:mm:ss") - Checking $($disk.Name): - $($disk.VolumeLabel)"
Get-ChildItem "$($disk.Name)" -Recurse -Force -Include @("*.jar","*.war") -ErrorAction SilentlyContinue | ForEach-Object { Select-String "JndiLookup.class" $_ } | Select-Object -ExpandProperty Path | Get-Unique
 
}
# Everything else
else {
 
Write-Host -ForegroundColor Yellow " $(Get-Date -Format "yyyy-MM-dd H:mm:ss") - Checking $($disk.DriveLetter): - $($disk.VolumeLabel)"
Get-ChildItem "$($disk.DriveLetter):\" -Recurse -Force -Include @("*.jar","*.war") -ErrorAction SilentlyContinue | ForEach-Object { Select-String "JndiLookup.class" $_ } | Select-Object -ExpandProperty Path | Get-Unique
 
}
 
}
 
Write-Host -ForegroundColor Green "$(Get-Date -Format "yyyy-MM-dd H:mm:ss") - Done checking all drives"

Sample output with nothing found:

Sample output with something found:

Good luck everyone.

728x90
728x90

We’ve run into a strange problem with our Windows Server 2019 VMs where sometimes when we clone a new VM from our template it works perfectly fine and sometimes it won’t let you install any new Roles and throws a 0x80073701 error. Better still, sometimes it lets you install a new Role and then months later when you go to add something else it fails also with a 0x80073701.

For the longest time the only solution I was able to find online was nuke it and start over which is typically what we did. That or to manually dig through registry keys for packages installed in Windows with a different language than that of your operating system. I never was able to get that suggestion to work because I couldn’t gain the permissions I needed to delete the registry keys. We also had zero luck running DISM with it’s variety of flags.

At some point a co-worker of mine stumbled across a PowerShell script that solved the problem for us and saved us having to rebuild a few more complicated VMs.

I had to use that script tonight on a VM but this time it didn’t work. I tried to see if I could find a new version but I couldn’t even find the original script. With some fiddling I eventually got the script to work but it dawned on me that lots of people might have having this problem and the script to fix it with out wiping/reloading might not be easily found anymore.

Full Disclosure. I did not write this script, I’ve only used it a few times with success. I searched for the authors name to see if they had a Github repo or something out there and found nothing other than a LinkedIn.

Near as I can tell this script does the following:

  1. Elevates its privileges in a very specific looking way. I did not dig much into it since the rest of the script does not appear to do anything malicious and you should run this “As an administrator” anyway I just went with it
  2. It then asks you for the location of your CBS log file, if none is provided it uses the default location
  3. It then parses the CBS log file for any instances of ERROR_SXS_ASSEMBLY_MISSING and then parses those lines to pull out the specific package names that are causing problems
  4. Using it’s elevated privileges it takes ownership of that packages registry keys and changes the ‘Currentstate’ key to ‘0’ which I assume means not installed or ignored
  5. It does some checks to make sure the ‘Currentstate’ was successfully changed and then completes

Once the script has run you do not need to reboot. You should be able to start adding Roles to the server right away.

I have found that running the script against “C:\Windows\Logs\CBS\CBS.log” does not always solve the problem. Tonight I went into “C:\Windows\Logs\CBS\” and had to run it against the second newest log “CbsPersist_20230310065917.log”. After doing that the issue was resolved for me.

In our case it appears the issue is with KB4598230 which has been pulled from the Microsoft Update Catalogue and can no longer be downloaded. I have seen plenty of form posts involving other KBs causing the exact same error though.

Sorry, that was a lot of reading. Here is what you are after:

 
 
 
 
<#
.SYNOPSIS
 
This script will fix the SXS assmbly missing issue while installing feature
 
.DESCRIPTION
 
The script mark the resolved packages absent which are missing manifest.
 
.PARAMETER
 
Provide CBS file path
 
.OUTPUTS
<Outputs if any, otherwise state None - example: Log file stored in current working directory "AssemblyMissingScript-" + [datetime]::Now.ToString("yyyyMMdd-HHmm-ss") + ".log")>
.NOTES
Version: 1.0
Author: Abhinav Joshi
Creation Date: 14/11/2020
Purpose/Change: Initial script development
 
.EXAMPLE
 
Run the script ERROR_SXS_ASSEMBLY_MISSING.ps1
 
Please enter CBS file path (Default Path: c:\windows\logs\cbs\cbs.log): C:\windows\Logs\cbs\cbs2.log
#>
 
 
function enable-privilege {
param(
## The privilege to adjust. This set is taken from
[ValidateSet(
"SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
"SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
"SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
"SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
"SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
"SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
"SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
"SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
"SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
"SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
"SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
$Privilege,
## The process on which to adjust the privilege. Defaults to the current process.
$ProcessId = $pid,
## Switch to disable the privilege, rather than enable it.
[Switch] $Disable
)
 
## Taken from P/Invoke.NET with minor adjustments.
$definition = @'
using System;
using System.Runtime.InteropServices;
 
public class AdjPriv
{
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
 
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}
 
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool EnablePrivilege(long processHandle, string privilege, bool disable)
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = new IntPtr(processHandle);
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
if(disable)
{
tp.Attr = SE_PRIVILEGE_DISABLED;
}
else
{
tp.Attr = SE_PRIVILEGE_ENABLED;
}
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
}
'@
 
$processHandle = (Get-Process -id $ProcessId).Handle
$type = Add-Type $definition -PassThru
$type[0]::EnablePrivilege($processHandle, $Privilege, $Disable)
}
 
$logfile = [System.IO.Path]::Combine($rootDir, "AssemblyMissingScript-" + [datetime]::Now.ToString("yyyyMMdd-HHmm-ss") + ".log")
if (-not (Test-Path "$PWD\logs")) {
New-Item -Path "$PWD\logs" -ItemType Directory -Verbose
}
Start-Transcript -Path "$PWD\logs\$logfile"
 
$cbspathTEMP = Read-Host -Prompt "Please enter CBS file path (Default Path: c:\windows\logs\cbs\cbs.log)"
 
$cbspath = $cbspathTEMP.Replace('"','')
 
write-host ""
 
write-host -ForegroundColor Yellow $cbspath
 
 
if ($cbspath -eq $null -or $cbspath.Length -eq "0"){
 
Write-Host -ForegroundColor Yellow "No path was entered"
 
Write-Host "Setting up default CBS path"
 
$cbspath = "c:\Windows\Logs\CBS\CBS.log"
 
Write-Host -ForegroundColor Cyan $cbspath
}
 
 
$CheckingpackagesResolving = "Resolving Package:"
 
$checkingFailure = Get-Content $CBSpath | Select-String "ERROR_SXS_ASSEMBLY_MISSING"
 
if ($checkingFailure -ne $null -and $CheckWhichFeature -ne 0) {
 
Write-Host "Checking resolving packages"
 
$CBSlines = Get-Content $CBSpath | Select-String $CheckingpackagesResolving
 
$Result = @()
 
if ($CBSlines) {
 
foreach ($CBSline in $CBSlines) {
 
$packageLine = $CBSline | Out-String
 
$package = $packageLine.Split(":").Trim().Split(',').Trim() | Select-String "Package_"
 
$Result += $package
}
 
Write-host "Found following resolving packages"
 
$Results = $Result | Select-Object -Unique
 
foreach ($regpackage in $Results) {
 
$bb = "SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\$regpackage"
 
$uname = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
 
enable-privilege SeTakeOwnershipPrivilege
 
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($bb, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::takeownership)
# You must get a blank acl for the key b/c you do not currently have access
$acl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None)
$me = [System.Security.Principal.NTAccount]$uname
$acl.SetOwner($me)
$key.SetAccessControl($acl)
 
# After you have set owner you need to get the acl with the perms so you can modify it.
$acl = $key.GetAccessControl()
$rule = New-Object System.Security.AccessControl.RegistryAccessRule ($uname, "FullControl", "Allow")
$acl.SetAccessRule($rule)
$key.SetAccessControl($acl)
 
$key.Close()
 
Write-Host "Mark this package absent $regpackage"
 
Set-ItemProperty -Path "HKLM:\$bb" -Name Currentstate -Value 0 -Type DWord -Force
}
 
Write-host "Verifying package state"
 
$Verifcationcheckvalue = "1"
 
foreach ($Regpackagecheck in $Results) {
 
$CurrentstateOfpackage = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\$Regpackagecheck").CurrentState
 
if ($CurrentstateOfpackage -eq "0") {
 
Write-host -ForegroundColor Green $CurrentstateOfpackage of $Regpackagecheck
 
$Verifcationcheckvalue += "1"
 
 
}
else {
 
Write-host -ForegroundColor red $CurrentstateOfpackage of $Regpackagecheck
 
$Verifcationcheckvalue += "0"
}
}
 
if ($Verifcationcheckvalue -notmatch "0") {
 
write-host "========================================================================="
 
write-host ""
 
Write-host -f white -BackgroundColor green "Verification passed, Retry Enabled"
 
write-host ""
 
write-host "========================================================================="
 
$Global:try = $true
 
}
else {
 
write-host "========================================================================="
 
write-host ""
 
write-host -f white -BackgroundColor Red "Verification Failed, Can't contiune. Collect $logfile and CBS.log"
 
write-host ""
 
write-host "========================================================================="
 
$Global:try = $false
}
 
}
else {
 
Write-Error "Error while finding resolving packages"
}
}
 
else {
 
Write-Host "Looks like $CBSpath is not right CBS File, check manually. "
 
}
 
 
 
stop-Transcript
 
pause

Abhinav Joshi, whoever you are. Thank you very much for this script. It’s saved us a ton of time and headache.

728x90
728x90

Windows Server 평가판 다운로드 Url

https://www.microsoft.com/ko-kr/evalcenter/evaluate-windows-server-2019?filetype=ISO

728x90
728x90

 

1. 역할(Role)과 기능(Feature) 설치
서버관리자를 열어 몇가지 추가 기능들을 설치만 하면 윈도우8과 같은 UI를 얻게 됩니다. 권장 설치 목록은 Hyper-V, 닷넷프레임워크, 데스크톱경험(Desktop Experience) 정도이고, 필요시에 텔넷클라이언트와 무선랜서비스를 추가하면 됩니다.
설치를 진행하면 두번 이상 자동으로 재부팅되며 Metro 타일화면까지 진행됩니다. 바탕화면을 우클릭해보면 개인설정(Personalize)가 생겨 있습니다.

2. ping 허용, ipv6 제거
C:\> netsh advfirewall firewall add rule name="ICMP Allow incoming V4 echo request" protocol=icmpv4:8,any dir=in action=allow

C:\> services.msc 명령어를 통해 서비스관리자를 호출하여 "IP Helper" 서비스를 중단(disable)시키고, 랜카드 속성에서 TCP/IPv6 부분을 체크해제

 

3. IE 보안 강화 구성 해제

Server 를 설치하고 난뒤 몇몇 어플리케이션을 다운로드 받아서 설치해야하는데 기본적으로 IE를 실행하게 되면 보안 강화 구성 때문에 사이트 연결때마다 알림창이 떠서 귀찮게 하죠

 

서버 관리자 창 -> 로컬 서버 선택 -> 속성 창의 오른쪽 중앙 -> IE 보안 강화 구성 선택 -> 관리자/사용자 모두 사용안함으로 선택

 

4. 계정 암호 복잡성 규칙 및 유효기간 해제하기

Windows Server는 암호를 정할때 대문자 소문자 특수문자 숫자가 꼭 포함이 되어야만 복잡성을 통과해서 암호 설정이 됩니다.

 

서버 관리자 창 -> 우측 상단의 도구 -> 로컬 보안 정책 -> 계정 정책 -> 암호 정책

암호는 복잡성을 만족해야함 : 해제
최대 암호 사용기간 : 0 으로 설정


5. 사용자 계정 추가 및 Administrator 계정 이름 변경

Admin 권한을 가진 계정을 새로이 생성하고 Adminitrator 계정은 그 이름을 바꿔주는 것이 보안 측면이 좋다고 하기에 새로운 계정을 생성하고 Admin계정 권한을 부여한뒤 Administrator 이름을 변경하였습니다.

계정 추가 방법은 제어판 -> 사용자 계정 -> 다른 계정 관리 -> 사용자 계정 추가 를 선택 하시면 됩니다.

 

    Admin 계정 변경 방법 : 서버 관리자 창 -> 우측 상단의 도구 -> 로컬 보안 정책 -> 로컬 정책 -> 보안 옵션

     -> Administrator 계정 이름 바꾸기 -> 변경하고자 하는 이름으로 변경

 

6. 원격 데스크톱 활성화

홈서버에는 모니터와 키보드, 마우스를 연결하지 않고 본체만 항상 켜두기때문에 서버 관리를 위해서 RDP를 활성화 해줘야만 Windows Server 2012에 접속해서 이것저것 관리를 할 수가 있습니다.

서버 관리자 창 -> 로컬 서버 선택 -> 속성창 왼쪽 중앙 -> 원격 데스크톱 선택 -> 이 컴퓨터에 대한 원격 연결 허용 선택 -> 네트워크 수준 인증을 사용하여 원격 데스크탑을 실행하는 컴퓨터에서만 연결 허용(권장) 해제

 

 

끝.

728x90

+ Recent posts