Archiv für die Kategorie » Allgemein «

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 » , , «

+

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 » , , , «

+

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 » , «

+

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 » , , «

+

24 | 02 | 2017

Das war mal wieder soweit…

Geschrieben von um 15:14 Uhr

… und ich musste meinen VCP erneuern. Diesmal beschloss ich, dies im Wege eines Delta Exams zu tun. Das ging gut, aber ich denke, nächstes Mal mache ich mal wieder eine volle Prüfung. Der Aufwand ist derselbe und der Stressfaktr etwas weniger 😉

Tags » , , «

+

16 | 12 | 2016

Erstes Treffen der EXUSG Berlin – das war schön :-)

Geschrieben von um 19:25 Uhr

Gestern haben wir uns bei der dama.go am Spittelmarkt zum ersten Mal getroffen. Der Abend war ein voller erfolg – geballtes Know-How in einem Raum, inspirierende Vorträge, tolle Gespräche und auch ein bißchen Nostalgie 🙂

Mein Vorschlag, Termine für die Treffen in 2017 bereits jetzt festzulegen, wurde zumindest nicht abgelehnt. Die Termine stehen unter http://exusg.de/veranstaltungen/terminplanung-2017/ zur Abstimmung nach dem Motto „wer was dagegen hat, möge sich jetzt äußern oder für immer schweigen“.

Ich freue mich schon auf das nächste Treffen, voraussichtlich im Februar.

Tags » , , , , , , «

+

06 | 11 | 2016

Exchange User Group Berlin geht an den Start!

Geschrieben von um 22:40 Uhr

http://exusg.de : Die Exchange User Group Berlin ist nun offiziell gegründet und als Microsoft Technical Community anerkannt. Das erste Treffen ist für den 15.12.2016 geplant. Der genaue Ort und das Programm werden in den nächsten Tagen veröffentlicht.

Wir wollen über konkrete Herausforderungen im Betrieb von Exchange, Lync, OOS usw. – aber auch um die Zukunft der Kommunikation im Unternehmen sprechen.

Alle Neuigkeiten der neuen Gruppe findet ihr auf http://exusg.de.

Also: Bitte mitmachen und fleißig weitersagen!

Tags » , , , «

+

17 | 10 | 2016

JetPack hat die XING-RSS-Anbindung gefressen :-(

Geschrieben von um 9:38 Uhr

Es kann natürlich auch eine Koinzidenz sein, aber just nach dem Installieren des JetPack-Plugins sagt der RSS-Reader von XING zu meinem Blog:

xing

Bis das geklärt ist, muss ich die Beiträge wohl manuell teilen 🙁

Tags » , , , «

1

10 | 10 | 2016

PowerShell Hack: TechNet-Teilnahme eines Users messen oder eine Übung im Web Grabbing

Geschrieben von um 9:04 Uhr

Wenn man im TechNet-Forum (https://social.technet.microsoft.com/Forums/de-de/home) unterwegs ist, kann man ja Punkte verdienen. Hat man eine Frage beantwortet und hat der Fragesteller das bestätigt, gibt es Punkte. Hat jemand den Post für hilfreich erklärt, gibt’s auch Punkte. Ist man in vielen Microsoft-Technologien unterwegs, möchte man manchmal wissen, wo man denn die meiste Contribution geleistet hat. Das Forumsystem selbst gibt da zwar eine sehr detaillierte Auskunft in Form einer Aktivitäten-History, aber man möchte ja eigentlich einfach nur schnell einen Überblick gewinnen. Und vielleicht auch nicht über sich, sondern auch über andere user. Was liegt an einem verregneten Sonntag also näher, als einfach ein Skript zu schreiben, das die Webseite für einen durchgeht und die Daten einsammelt.

Die Grundlage dafür ist das Cmdlet Invoke-WebRequest, welches ein Objekt vom Typ „Microsoft.PowerShell.Commands.HtmlWebResponseObject“ zurück liefert. Dieses hat eine Eigenschaft „ParsedHtml“, die vom Typ „mshtml.IHTMLDocument2“ ist. Damit wären wir schon fast am Ziel, man muss einfach nur an den Perversitäten der Web-Entwickler und der verschahtelten Struktur der DIV-Tags vorbei kommen. In der Thread-Ansicht zum Beispiel hat die Vorschau auf jeden Beitrag die Klasse „threadsnippet“:

paul_thread_snippet

Den Inhalt bekommt man also mit

$page = Invoke-WebRequest -Uri "https://social.technet.microsoft.com/Forums/en-us/user/threads?user=Paul++Cunningham"
$html = $page.ParsedHtml
$html.all.tags("DIV") | foreach {
    if ($_.className) {
        if ($_.className.Trim() -eq "threadsnippet") {
            $snippet = $_
            foreach ($head in $snippet.all.tags("H3")) {
                $thread_topic = $head.innerText.Trim()
                foreach($link in $head.all.tags("A")) {
                    $thread_link = $link.href
                }
            }
        }
    }
}

Am Ende hat man dann in $thread_topic den Header und in $thread_link den Link zum gesamten Thread. Und so weiter.
Ich habe dafür zwei Skripte geschrieben, die in der PSGallery heruntergeladen werden können:

Export-TechNetContributionToCSV.ps1 geht die Beiträge des angegebenen Users durch und macht daraus eine CSV-Dateie mit diversen Informationen inklusive Links zu den einzelnen Threads. Schauen wir uns zum Beispiel die Contribution des bekannten Exchange-MVP Paul Cunningham an (man beachte die zwei Leerzeichen im TechNet-Usernamen):

tn_paul_export

Ist die CSV fertig, so kann man sie mit Measure-TechNetContribution.ps1 nach Foren oder sogar nach einzelnen Subforen zusammenfassen und, je nach Lust und Laune, tabellarisch oder sonst wie darstellen lassen:tn_paul_measureoder nach Hauptforen gegliedert:

tn_paul_measure_main

So kann man herausfinden, in welchen Wissensgebieten sich z.B. ein Kollege betätigt, der gern im TechNet Forum schreibt.

Tags » , , , , «

+