Herzlich Willkommen!

12 | 08 | 2017

PowerShell Quirks: New-PSDrive und der Speicherplatz

Geschrieben von um 11:26 Uhr

Wenn man in einer PowerShell-Sitzung mit

New-PSDrive -Name Z -Root "\\SERVER\SHARE" -PSProvider FileSystem

ein Netzlaufwerk mappt, stellt man fest, dass die Spalten „Used Space“ und „Free Space“ leer sind:

Möchte man die Werte haben, funktioniert es mit dem Argument -Persist:

Ich hätte sogar eine theoretische Erklärung dafür, aber Gernot Meyer hat im TechNet-Forum eine Beobachtung zitiert, die diese Erklärung widerlegt, daher halte ich mich mal zurück und recherchiere weiter.

Happy drive mapping!

Tags » , , , , «

+

19 | 07 | 2017

PowerShell Quirks: Move-ADDirectoryServerOperationMasterRole und der Schema Master

Geschrieben von um 20:54 Uhr

Heute mal ein Quickie, nur als Merker für den Hinterkopf:

Auch wenn es im Internet von Anleitungen nur so wimmelt, die den Befehl

Move-ADDirectoryServerOperationMasterRole <DomainController> -OperationMasterRole SchemaMaster

zeigen, gibt es dazu ein Wort zu sagen: Das funktioniert nur, wenn man

  • entweder den Befehl auf dem DC aufruft, zu dem die Rolle transferiert werden soll
  • oder den Parameter -Force mit angibt.

Alle anderen Rollen lassen sich auch ohne -Force beliebig hin und her transferieren.

Happy FSMOing!

Tags » , , «

+

29 | 06 | 2017

CipherSuites in Windows Server vorgeben und überwachen – Teil 1

Geschrieben von um 20:13 Uhr

Wir haben die Aufgabe bekommen, eine ganz bestimmte Auswahl an Cipher Suites für einige Applikationsserver zuzulassen. Gesagt, getan. Nach Prüfung der Kompatibilität zu anderen Applikationen und einem Test in der Testumgebung haben wir das Gewünschte umgesetzt…

…nur um festzustellen, dass anscheinend bei jedem Patchday irgendetwas dabei ist, das die Liste wieder auf den vorgegebenen Zustand zurück stellt. Eine Automatisierungs- und nach Möglichkeit Überwachungslösung musste also her.

Die benötigte Einstellung kann man ganz einfach mit einem PowerShell-Einzeiler

Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002" -Name "Functions" -Value "TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_RC4_128_SHA"

oder visuell durch IISCrypto erledigen. Beide Verfahren tun das gleiche: Den String für den Wert „Functions“ als kommagetrennte Liste der Cipher Suites zusammenbasteln und in die Registry schreiben. Der Haken an der Sache: damit das Ganze auch in Kraft tritt, wird ein Reboot der Maschine benötigt.

Die Erzwingung der korrekten Werte in der Registry erreicht man einfach per Group Policy Preference:

Somit ist erst einmal der Automatisierungsteil erledigt. Nun könnte aber jemand Böses (OK, Böses mit Adminrechten) die Cipher Suites verstellen, die Kiste rebooten, und die veränderte Einstellung würde bis zum nächsten Reboot in Kraft bleiben. Zur Überwachung ist es also nicht ausreichend, den Wert in der Registry abzufragen, man muss schauen, was wirklich aktiv ist.

Der erste Wurf war die Nutzung der Windows-API. Nach einigem Googlen fand ich zwar immer noch kein PowerShell-Modul dafür, aber immerhin den folgenden vielversprechenden Thread auf StackOverflow: https://stackoverflow.com/questions/19695623/how-to-call-schannel-functions-from-net-c

Leicht modifiziert, wird daraus ein binäres Modul:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Management.Automation;

namespace CipherSuites
{
    [Cmdlet(VerbsCommon.Get, "CipherSuites")]
    public class GetCipherSuitesCmdlet: Cmdlet
    {
        [DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
        static extern uint BCryptEnumContextFunctions(uint dwTable, string pszContext, uint dwInterface, ref uint pcbBuffer, ref IntPtr ppBuffer);
        [DllImport("Bcrypt.dll")]
        static extern void BCryptFreeBuffer(IntPtr pvBuffer);
        [StructLayout(LayoutKind.Sequential)]
        public struct CRYPT_CONTEXT_FUNCTIONS
        {
            public uint cFunctions;
            public IntPtr rgpszFunctions;
        }
        public const uint CRYPT_LOCAL = 0x00000001;
        public const uint NCRYPT_SCHANNEL_INTERFACE = 0x00010002;
        public const uint CRYPT_PRIORITY_TOP = 0x00000000;
        public const uint CRYPT_PRIORITY_BOTTOM = 0xFFFFFFFF;
        static uint cbBuffer = 0;
        static IntPtr ppBuffer = IntPtr.Zero;
        string so;
        uint Status;

        protected override void BeginProcessing()
        {
             cbBuffer = 0;
             ppBuffer = IntPtr.Zero;
        }
        protected override void ProcessRecord()
        {
        }
        protected override void EndProcessing()
        {
            Status = BCryptEnumContextFunctions(
                         CRYPT_LOCAL,
                         "SSL",
                         NCRYPT_SCHANNEL_INTERFACE,
                         ref cbBuffer,
                         ref ppBuffer);
            if (Status == 0)
            {
                CRYPT_CONTEXT_FUNCTIONS functions = (CRYPT_CONTEXT_FUNCTIONS)Marshal.PtrToStructure(ppBuffer, typeof(CRYPT_CONTEXT_FUNCTIONS));
                IntPtr pStr = functions.rgpszFunctions;
                for (int i = 0; i < functions.cFunctions; i++)
                {
                    so = Marshal.PtrToStringUni(Marshal.ReadIntPtr(pStr));
                    WriteObject(so);
                    pStr = new System.IntPtr((pStr.ToInt64() + (IntPtr.Size)));
                }
                BCryptFreeBuffer(ppBuffer);
            }
            GC.Collect();
            GC.WaitForFullGCComplete();
        }
    }
}

Das Ergebnis könnt ihr ohne jede Gewähr hier herunterladen: CipherSuites.dll. Ich werde das nicht offiziell auf Gallery veröffentlichen – warum, erkläre ich unten. Für das Monitoring wird das noch NAGIOS-konform in PowerShell verpackt:

$root = (get-item $PSScriptRoot).parent.FullName.ToString()
if (!(Get-Command "Get-CipherSuites" -EA SilentlyContinue)) { Import-Module ($root + "\modules\CipherSuites.dll") }
$additional_cs_is_critical = $true
$missing_cs_is_critical = $false
$cs_list = "TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_RC4_128_SHA"
$exitCodes = @{
"UNKNOWN" = 3;
"CRITICAL" = 2;
"WARNING" = 1;
"OK" = 0
}
if (Get-Command "Get-CipherSuites" -EA SilentlyContinue) { $cs = Get-CipherSuites } else { $cs = @() }
$cs_string = $cs -join ","
if ($cs_list-like $cs_string) {
    $state = "OK"
    $status_msg = "CipherSuites are in order"
    $perfdata_msg = "ciphersuites=$($cs.count);0;0"
} elseif (!($cs)) {
    $state = "UNKNOWN"
    $status_msg = "Could not retrieve CipherSuites"
    $perfdata_msg = "ciphersuites=-1;-1;-1"
} else {
    $nadd = 0
    $nmiss = 0
    $csl = $cs_list -split ","
    foreach ($cx in $cs) {
        if ($csl -notcontains $cx) {
            $nadd++
        }
    }
    foreach ($cx in $csl) {
        if ($cs -notcontains $cx) {
            $nmiss++
        }
    }
    if (($nadd -eq 0) -and ($nmiss -eq 0)) {
        $status_msg = "CipherSuites reordered!"
        $perfdata_msg = "ciphersuites=$($cs.count);0;0"
        if ($reordered_cs_is_critical) {
            $state = "CRITICAL"
        } else {
            $state = "WARNING"
        }
    } else {
        $status_msg = "CipherSuites mismatched: $nmiss missing, $nadd additional"
        $perfdata_msg = "ciphersuites=$($cs.count);$nmiss;$nadd"
        if (($additional_cs_is_critical -and ($nadd -gt 0)) -or ($missing_cs_is_critical -and ($nmiss -gt 0))) {
            $state = "CRITICAL"
        } else {
            $state = "WARNING"
        }
    }
}
Write-Host $state": $status_msg|$perfdata_msg"
exit $exitCodes[$state]

Funktioniert soweit, bereits die ersten Tests ließen aber den dringenden Verdacht aufkommen, dass die Windows-API lediglich die konfigurierten, nicht jedoch die ausgeführten Cipher Suites zurückgeben. Ich wollte es genau wissen und habe schnell den Process Monitor angeworfen. Und siehe da…
Hat sich ja wirklich gelohnt, dafür noch eine API zu schreiben. Dann müssen wir also für die Überwachung etwas bemühen, das agiert wie https://testssl.sh. Wie das ausgeht, berichte ich im nächsten Teil.

Happy decrypting!

Tags » , , , , , , «

+

22 | 06 | 2017

Tschüß, old friend & mentor… Gespannt auf Mark Minasi 2.0!

Geschrieben von um 22:59 Uhr

Vor einigen Tagen hat Mark Minasi in seinem Newsletter (und ein paar Tage zuvor in seinem Forum) angekündigt, dass er beschlossen hat, sich in seinem neuen Heim in Florida zu Ruhe zu setzen. Das hat erwartungsgemäß eine Welle der verklärten Traurigkeit in der Szene ausgelöst. Manche Beiträge lesen sich fast wie Nachrufe, so z.B. von Jeremy Moskowitz und Don Jones. An Fakten wurde das meiste, was es zu sagen gibt, glaube ich, von den Beiden gesagt.

Dabei ist der Typ quietschlebendig und hat schon seit Jahrzehnten bewiesen, dass er nicht still sitzen kann. Insofern versuche ich nun, auch meine stille Trauer mit der freudigen Erwartung dessen zu übertönen, was in den kommenden Jahren aus Marks Feder noch kommen mag. Nun, wo er nicht mehr darauf angewiesen ist, mit Windows 10-Adminkursen und AD-Workshops durch die USA zu tingeln.

Marks Abschied aus dem Berufsleben hinterläßt eine Lücke. Wenn er’s denn schafft, sich herauszuhalten. Das wird die Zeit zeigen.

Tags » , , «

+

21 | 06 | 2017

PowerShell: Ein schneller Versuch, ADMX zu parsen

Geschrieben von um 19:45 Uhr

Hier ein bißchen Code, um alle Einstellungen aus ADMXen inklusive Registry-Pfad und -Typ zu exportieren. Ein paar Typen könnten noch fehlen …

Achtung! In Zeilen 10 und 11 frißt der Syntax Highlighter den Typ (quadratische Klammer auf)xml(quadratische Klammer zu) unmittelbar vor der runden Klammer. Noch weiß ich nicht, wie ich ihn überredet bekomme, das anzuzeigen. Bis dahin hier der Quelltext zum Download: admx_parser

$language = "de-DE"
$root = "C:\Windows\PolicyDefinitions"
$output = @()

$admx_files = Get-ChildItem $root -Filter "*.admx"
foreach ($admx in $admx_files) {
    $admx_file = Split-Path $admx -Leaf
    $adml = "C:\Windows\PolicyDefinitions\$($language)\$($admx_file.TrimEnd('x'))l"
    if (Test-Path $adml) {
        $admx_data = (Get-Content $admx.FullName)
        $adml_data = (Get-Content $adml -Encoding UTF8)
        $adml_strings = $adml_data.policyDefinitionResources.resources.stringTable.GetEnumerator()
        $policies = $admx_data.policyDefinitions.policies
        foreach ($pol in $policies.policy) {
            $dn_string = $pol.displayName.Substring(9, ($pol.displayName.Length - 10))
            $et_string = $pol.explainText.Substring(9, ($pol.explainText.Length - 10))
            $policy_name = ($adml_strings.Where({$_.id -eq $dn_string})).'#text'
            $adml_strings.Reset()
            $policy_desc = ($adml_strings.Where({$_.id -eq $et_string})).'#text'
            $adml_strings.Reset()
            if ($pol.elements.HasChildNodes) {
                $els = $pol.elements.GetEnumerator()
                foreach ($el in $els) {
                    $reg_value = "$($pol.Key)\$($el.valueName)"
                    switch ($el.Name) {
                        'boolean' { $reg_type = 'REG_DWORD (1)' }
                        'decimal' { $reg_type = 'REG_DWORD' }
                        'text' {
                            if ($el.expandable) {
                                $reg_type = 'REG_EXPAND_SZ'
                            } else {
                                $reg_type = 'REG_SZ'
                            }
                        }
                        'enum' {
                            $ex = $el.FirstChild.FirstChild.FirstChild.Name
                            switch ($ex) {
                                'decimal' { $reg_type = 'REG_DWORD' }
                                'text' {
                                    if ($el.expandable) {
                                        $reg_type = 'REG_EXPAND_SZ'
                                    } else {
                                        $reg_type = 'REG_SZ'
                                    }
                                }
                            }
                        }
                        'list' {
                            $reg_type = 'REG_SZ (list)'
                            $reg_value = $el.Key
                        }
                        default { 
                            Write-Host $el.Name -ForegroundColor Cyan
                            $reg_type = $el.Name
                            $reg_value = $el.Key
                        }
                    }
                    $out_item = New-Object PSObject -Property @{'RegPath' = $reg_value; 'RegType' = $reg_type; 'PolicyTitle' = $policy_name; 'PolicyDescription' = $policy_desc; 'ADMXFile' = $admx_file}
                    $output += $out_item
                }
            } else {
                $reg_value = "$($pol.Key)\$($pol.valueName)"
                $reg_type = 'REG_DWORD (1)'
                $out_item = New-Object PSObject -Property @{'RegPath' = $reg_value; 'RegType' = $reg_type; 'PolicyTitle' = $policy_name; 'PolicyDescription' = $policy_desc; 'ADMXFile' = $admx_file }
                $output += $out_item
            }
        }
    } else {
        Write-Host "ADML in $language not found: $adml" -ForegroundColor Yellow
    }
}
$output | Export-CSV c:\temp\admx.csv -Encoding UTF8

Enjoy!

Tags » , , «

2

07 | 05 | 2017

PSConfEU 2017: Das war schön

Geschrieben von um 23:08 Uhr

Drei unvergessliche Tage in Hannover, Inspiration für das ganze Jahr, tolle Gespräche, neue und alte Freunde:

Danke an @TobiasPSP, das Orga-Team, die Speaker!

Tags » , , , «

+

06 | 05 | 2017

Das neue Buch von Daniel Suarez ist erschienen!

Geschrieben von um 14:55 Uhr

Change Agent

Der Meister beschäftigt sich weiter mit Veränderung der Gesellschaft durch Technologie, diesmal geht es aber nicht primär um Computer und künstliche Intelligenz, sondern um Genetik und ihre Bedeutung für die Identität des einzelnen.

Mein Urteil: Unbedingt lesenswert!

Tags » , , «

+

21 | 04 | 2017

Ein unschöner, aber wohl unvermeidlicher Schlussstrich unter einem Jahr TechNet-Forum

Geschrieben von um 19:14 Uhr

Seit ziemlich genau einem Jahr bin ich nun wieder im TechNet-Forum aktiv gewesen. Der Ton ist erfreulicherweise viel kollegialer und produktiver geworden, das war früher anders. Allerdings kommt wohl bei jedem der Tag, da gerät man an den Falschen.

Und so bin ich heute quasi doppelt zum Ritter geschlagen worden: Eine Beleidigung und Meldung als Missbrauch:

Mark Minasi sagte mal vor knapp 10 Jahren, die schlimmsten Hasskommentare kämen immer von anonymen Usern. Der Mann hat’s damals schon durchschaut. Hoffentlich folgen die Mods auf TechNet dem Aufruf und bannen mich für immer, dann habe ich wieder mehr Zeit, mein dümmliches Gesülze dort zu verbreiten, wo es keinem weh tut, nämlich hier in meinem eigenen Blog…

Tags » , «

+

17 | 03 | 2017

„Verbindung verweigert“ zwischen SEP sesam und XenServer: Fake News

Geschrieben von um 8:09 Uhr

Wieder was gelernt: Wenn der Versuch, einen XenServer-Sicherungsclient zur SEP sesam-Topologie hinzuzufügen, mit der Fehlermeldung

E002-HOSTS   Kein Zugang auf Rechner <XENPOOLMASTER>: 2017-03-16 16:41:49: sxs-1500: Error:    Could not login to XEN Server: <class ’socket.error‘>: [[Errno 10061] Es konnte keine Verbindung hergestellt werden, da der Zielcomputer die Verbindung verweigerte]

quittiert wird, muss es noch lange nicht heißen, dass man etwas falsch gemacht hat oder dass ein Netzwerkproblem vorliegt. Einfach ignorieren und versuchen, einen Sicherungsauftrag anzulegen – die Chancen stehen gut, dass es klappen wird. Sehr gut sogar.

Es geht nämlich bei der Verbindungsprüfung nicht ein einziges Paket Richtung XenServer – ich habe es sogar mit WireShark überwacht, so sehr hat diese Meldung uns aus der Spur gebracht.

Aber so ist es halt mit allen Fake News…

Tags » , , , «

+

07 | 03 | 2017

Leider kein April-Scherz – neue VMware-Zertifizierungspreise

Geschrieben von um 22:46 Uhr

Ab dem 01. April wird VMware die Zertifizierungspreise „anpassen„. Und während man vielleicht die Erhöhung von $400 auf $450 (12,5%) für Advanced-Zertifizierungen noch verschmerzen kann, tun mir die besten der besten armen Schweine leid, die vorhatten, ihre VMware-Recognition mit einem VCDX-Titel zu krönen. Statt $1200 (300 Registrierung + 900 Verteidigung) müssen sie nun $3900 löhnen (900 Registrierung + 3000 Verteidigung). Das ist eine Erhöhung um 225%. Und dass man dafür von Duncan Epping persönlich zerlegt wird, lindert den Schmerz vermutlich nur marginal.

Einmal ausnahmsweise ist es ein gutes Gefühl, nicht zu den besten auf einem Gebiet zu gehören…

*seufz*

Tags » , , «

+