NT-Password (NT Hash) unter Windows generieren
Hallo,
es muss doch irgendwie möglich sein ein NT-Password (einen NT-Hash) unter Windows zu erzeugen!?
Es ist doch ein "Windows-Ding":
Die einzigen Möglichkeiten des Erzeugens, die ich gefunden habe, sind entweder nur online oder unter Linux.
Online: https://tobtu.com/lmntlm.php
Linux:
Ich benötige es, weil ich einen Radiusserver betreiben möchte, der auf einer LinuxVM läuft, sich aber die Zugangsdaten aus einer MySQL-Datenbank seines Windows-Hosts holen soll.
Ich möchte die Eingabe und Pflege der Zugangsdaten, die in der selbstentworfenen MySQL-Datenbank gespeichert werden, unter Windows (per selbstgeschriebenen Webinterface) durchführen.
Weniger aus Sicherheitsgründen, mehr aus Gründen der Diskretion, möchte ich die Kennwörter nicht im Klartext in der Datenbank ablegen.
(Ich möchte nicht sehen können, wer welches Kennwort nutzt.)
Das kompatibelste Hash-Format ist NT-Password (NT-Hash)
Quelle: http://deployingradius.com/documents/protocols/compatibility.html
Was ich Suche ist ein offline Hash-Generator für Windows.
Das kann gerne eine der folgenden Ansätze sein:
- exe
- PowerShell
- php
- MySQL
- JavaScript
- eventuell Sonstiges
Ich habe mir jetzt einen Workaroud geschrieben, der nicht gerade das Ei des Kolumbus ist (bestenfalls sein Linkes).
Workaround
Auf der Linux-VM namens "linuxvm" habe ich Apache 2.4 und php 7.0 installiert.
Im Webroot der Linux-VM habe ich ein php-Skript abgelegt, das ein per Get übergegenes Kennwort mit
Die Ausgabe des php-Skripts ist inhaltlich wie eine php-Datei, die lediglich eine Variable zuweist.
Auf dem Windows-Rechner ist ebenfalls Apache und php installiert.
Zusätzlich ist dort das Tool "WGet" vorhanden.
Auf dem Windowsrechner liegt im Web-Ordner ein php-Skript, das ein per Get übergegenes Kennwort mit
WGet ruft damit das php-Script der Linux-VM auf und speichert dessen Ausgabe in eine temporäre php-Datei, die im Skript per
Ab dann steht dem php-Skript auf dem Windowsrechner das gehashte Kennwort in einer Variablen namens "verschluesselt" zur weiteren Verarbeitung zur Verfügung.
php-Skript "nthash.php" auf der Linux-VM
Beim Aufruf per
wird Folgendes generiert:
php-Skript "nthash.php" auf dem Windows-Host
Beim Aufruf per
steht im Skript die Variable "verschluesselt" mit dem NT-Hash als Inhalt, zur Verfügung.
Resultat:
(Kennwort "geheim" wir zu "C2AE1FE6E648846352453E816F2AEB93")
...und schon ist die Aufgabe erledigt.
(Die Eingangs erwähnte Diskretion sollte mich noch dazu veranlassen die Übergaben des Kennworts per Post und nicht per Get auszuführen.)
Mit der Behauptung "Das muss auch einfacher gehen" stehe ich hoffentlich nicht alleine da.
Gruß Frank
es muss doch irgendwie möglich sein ein NT-Password (einen NT-Hash) unter Windows zu erzeugen!?
Es ist doch ein "Windows-Ding":
NT-Password = Windows NT hashed passwords
Quelle: https://freeradius.org/radiusd/man/rlm_pap.txtDie einzigen Möglichkeiten des Erzeugens, die ich gefunden habe, sind entweder nur online oder unter Linux.
Online: https://tobtu.com/lmntlm.php
Linux:
/usr/bin/smbencrypt "geheim"
Ich benötige es, weil ich einen Radiusserver betreiben möchte, der auf einer LinuxVM läuft, sich aber die Zugangsdaten aus einer MySQL-Datenbank seines Windows-Hosts holen soll.
Ich möchte die Eingabe und Pflege der Zugangsdaten, die in der selbstentworfenen MySQL-Datenbank gespeichert werden, unter Windows (per selbstgeschriebenen Webinterface) durchführen.
Weniger aus Sicherheitsgründen, mehr aus Gründen der Diskretion, möchte ich die Kennwörter nicht im Klartext in der Datenbank ablegen.
(Ich möchte nicht sehen können, wer welches Kennwort nutzt.)
Das kompatibelste Hash-Format ist NT-Password (NT-Hash)
Quelle: http://deployingradius.com/documents/protocols/compatibility.html
Was ich Suche ist ein offline Hash-Generator für Windows.
Das kann gerne eine der folgenden Ansätze sein:
- exe
- PowerShell
- php
- MySQL
- JavaScript
- eventuell Sonstiges
Ich habe mir jetzt einen Workaroud geschrieben, der nicht gerade das Ei des Kolumbus ist (bestenfalls sein Linkes).
Workaround
Auf der Linux-VM namens "linuxvm" habe ich Apache 2.4 und php 7.0 installiert.
Im Webroot der Linux-VM habe ich ein php-Skript abgelegt, das ein per Get übergegenes Kennwort mit
exex()
an das Tool /usr/bin/smbencrypt
übergibt.Die Ausgabe des php-Skripts ist inhaltlich wie eine php-Datei, die lediglich eine Variable zuweist.
Auf dem Windows-Rechner ist ebenfalls Apache und php installiert.
Zusätzlich ist dort das Tool "WGet" vorhanden.
Auf dem Windowsrechner liegt im Web-Ordner ein php-Skript, das ein per Get übergegenes Kennwort mit
exex()
an das Tool wget.exe
übergibt.WGet ruft damit das php-Script der Linux-VM auf und speichert dessen Ausgabe in eine temporäre php-Datei, die im Skript per
include
eingebunden und gleich wieder gelöscht wird.Ab dann steht dem php-Skript auf dem Windowsrechner das gehashte Kennwort in einer Variablen namens "verschluesselt" zur weiteren Verarbeitung zur Verfügung.
php-Skript "nthash.php" auf der Linux-VM
<?php
$kennwort="";
$kennwort=$_GET['kennwort'];
if ($kennwort == "") {
die;
};
$modus="";
$modus=$_GET['modus'];
if ($modus != "php") {
$modus = "show";
}
$befehl="/usr/bin/smbencrypt \"".$kennwort."\"";
exec($befehl, $ausgabe, $fehler);
if ($fehler != 0) {
die;
};
$teile = explode("\t", $ausgabe);
$verschluesselt=$teile[1];
if ($modus == "show") {
echo $verschluesselt;
}
if ($modus == "php") {
echo "<?php \$verschluesselt=\"$verschluesselt\" ?>";
}
?>
http://linuxvm/nthash.php?kennwort=geheim&modus=php
wird Folgendes generiert:
<?php $verschluesselt="C2AE1FE6E648846352453E816F2AEB93" ?>
php-Skript "nthash.php" auf dem Windows-Host
<?php
$kennwort="";
$kennwort=$_GET['kennwort'];
if ($kennwort == "") {
die;
}
// WGet mit Parametern vorbereiten
$url="http://linuxvm/nthash.php?kennwort=".$kennwort."^&modus=php";
$nthashtmp="D:\www\webroot\Test\\nthashtmp.php";
$befehl="\"C:\Program Files (x86)\Tools\WGET\WGET.EXE\" ".$url." -O ".$nthashtmp;
// Achtung:
// Enthält ein Pfad "\t" oder "\n" so ist entweder "\\t" bzw. "\\n" anzugeben
// oder Großbuchstaben zu verwenden: "\T" bzw. "\N", damit nicht Tab oder NewLine daraus wird.
//Ausgabe zur Überprüfung
//echo "nthashtmp: ".$nthashtmp."<br>\n";
//echo "Befehl : ".$befehl."<br>\n";
// php-Datei des Linux-Rechners mit WGet aufrufen
exec($befehl, $ausgabe, $fehler);
// Erzeugte Datei einbinden und dann löschen
if ($fehler == 0) {
include $nthashtmp;
unlink($nthashtmp);
}
else {
$verschluesselt="Fehler";
}
// Ergebnis ausgeben (alternativ mit der Variablen andere Dinge machen)
echo $verschluesselt."\n";
?>
Beim Aufruf per
http://windowshost/nthash.php?kennwort=geheim
steht im Skript die Variable "verschluesselt" mit dem NT-Hash als Inhalt, zur Verfügung.
Resultat:
$verschluesselt="C2AE1FE6E648846352453E816F2AEB93"
...und schon ist die Aufgabe erledigt.
(Die Eingangs erwähnte Diskretion sollte mich noch dazu veranlassen die Übergaben des Kennworts per Post und nicht per Get auszuführen.)
Mit der Behauptung "Das muss auch einfacher gehen" stehe ich hoffentlich nicht alleine da.
Gruß Frank
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 364398
Url: https://administrator.de/contentid/364398
Ausgedruckt am: 24.11.2024 um 17:11 Uhr
7 Kommentare
Neuester Kommentar
Hallo,
hab das jetzt vor ein Paar wochen auch gemacht, für ein Mitarbeiter W-LAN. Nur Liegt das Webfrontend (PHP) auf nem Linux Server.
Ich such's kurz raus und Schick es dir.
Wo ich das gefunden hab, kann ich leider nicht mehr sagen.
hab das jetzt vor ein Paar wochen auch gemacht, für ein Mitarbeiter W-LAN. Nur Liegt das Webfrontend (PHP) auf nem Linux Server.
Ich such's kurz raus und Schick es dir.
function NTLMHash($Input) {
// Convert the password from UTF8 to UTF16 (little endian)
$Input=iconv('UTF-8','UTF-16LE',$Input);
// Encrypt it with the MD4 hash
$MD4Hash=bin2hex(mhash(MHASH_MD4,$Input));
// You could use this instead, but mhash works on PHP 4 and 5 or above
// The hash function only works on 5 or above
//$MD4Hash=hash('md4',$Input);
// Make it uppercase, not necessary, but it's common to do so with NTLM hashes
$NTLMHash=strtoupper($MD4Hash);
// Return the result
return($NTLMHash);
}
Wo ich das gefunden hab, kann ich leider nicht mehr sagen.
Zitat von @Pedant:
In Bezug auf PS bin ich noch sehr unbedarft.
Ich habe den dortigen Code in eine Datei kopiert und diese Get-MD4Hash.ps genannt.
Rufe ich sie dann auf:
erhalte ich:
Das ist falsch. Die PS1 muss ja erst mal so aufgerufen werden damit die Funktion der aktuellen Powershell-Konsole bekannt ist.In Bezug auf PS bin ich noch sehr unbedarft.
Ich habe den dortigen Code in eine Datei kopiert und diese Get-MD4Hash.ps genannt.
Rufe ich sie dann auf:
PS D:\Temp> ./Get-MD4Hash -DataToHash $([Text.Encoding]::Unicode.GetBytes("geheim"))
erhalte ich:
Mach es folgendermaßen, kopiere den u.s. Code in eine PS1 und dann rufst du diese in der Powershell so auf
.\script.ps1 'Geheim'
param(
[parameter(mandatory=$true)][string]$password
)
Function Get-MD4Hash
{
<#
.SYNOPSIS
This cmdlet returns the MD4 hash of the data that is input.
WARNING: MD4 is not secure, so it should NEVER be used to
protect sensitive data. This cmdlet is for research purposes only!
.DESCRIPTION
This cmdlet returns the MD4 hash of the data that is input.
WARNING: MD4 is not secure, so it should NEVER be used to
protect sensitive data. This cmdlet is for research purposes only!
This cmdlet uses Microsoft's implementation of MD4, exported
from bcrypt.dll. The implementation is fully compliant with
RFC 1320. This cmdlet takes a byte array as input, not a string.
So if you wanted to hash a string (such as a password,) you
need to convert it to a byte array first.
.EXAMPLE
Get-MD4Hash -DataToHash $([Text.Encoding]::Unicode.GetBytes("YourPassword1!"))
.PARAMETER DataToHash
A byte array that represents the data that you want to hash.
.INPUTS
A byte array containing the data you wish to hash.
.OUTPUTS
A 128-bit hexadecimal string - the MD4 hash of your data.
.NOTES
Author: Ryan Ries, 2014, ryan@myotherpcisacloud.com
.LINK
https://myotherpcisacloud.com
#>
[CmdletBinding()]
Param ([Parameter(Mandatory=$True, ValueFromPipeline=$False)]
[Byte[]]$DataToHash)
END
{
Set-StrictMode -Version Latest
Add-Type -TypeDefinition @'
using System;
using System.Text;
using System.Runtime.InteropServices;
public class BCrypt
{
[DllImport("bcrypt.dll", CharSet = CharSet.Auto)]
public static extern NTStatus BCryptOpenAlgorithmProvider(
[Out] out IntPtr phAlgorithm,
[In] string pszAlgId,
[In, Optional] string pszImplementation,
[In] UInt32 dwFlags);
[DllImport("bcrypt.dll")]
public static extern NTStatus BCryptCloseAlgorithmProvider(
[In, Out] IntPtr hAlgorithm,
[In] UInt32 dwFlags);
[DllImport("bcrypt.dll", CharSet = CharSet.Auto)]
public static extern NTStatus BCryptCreateHash(
[In, Out] IntPtr hAlgorithm,
[Out] out IntPtr phHash,
[Out] IntPtr pbHashObject,
[In, Optional] UInt32 cbHashObject,
[In, Optional] IntPtr pbSecret,
[In] UInt32 cbSecret,
[In] UInt32 dwFlags);
[DllImport("bcrypt.dll")]
public static extern NTStatus BCryptDestroyHash(
[In, Out] IntPtr hHash);
[DllImport("bcrypt.dll")]
public static extern NTStatus BCryptHashData(
[In, Out] IntPtr hHash,
[In, MarshalAs(UnmanagedType.LPArray)] byte pbInput,
[In] int cbInput,
[In] UInt32 dwFlags);
[DllImport("bcrypt.dll")]
public static extern NTStatus BCryptFinishHash(
[In, Out] IntPtr hHash,
[Out, MarshalAs(UnmanagedType.LPArray)] byte pbInput,
[In] int cbInput,
[In] UInt32 dwFlags);
[Flags]
public enum AlgOpsFlags : uint
{
BCRYPT_PROV_DISPATCH = 0x00000001,
BCRYPT_ALG_HANDLE_HMAC_FLAG = 0x00000008,
BCRYPT_HASH_REUSABLE_FLAG = 0x00000020
}
// This is a gigantic enum and I don't want to copy all of it into this Powershell script.
// Basically anything other than zero means something went wrong.
public enum NTStatus : uint
{
STATUS_SUCCESS = 0x00000000
}
}
'@
[Byte[]]$HashBytes = New-Object Byte 16
[IntPtr]$PHAlgorithm = [IntPtr]::Zero
[IntPtr]$PHHash = [IntPtr]::Zero
$NTStatus = [BCrypt]::BCryptOpenAlgorithmProvider([Ref] $PHAlgorithm, 'MD4', $Null, 0)
If ($NTStatus -NE 0)
{
Write-Error "BCryptOpenAlgorithmProvider failed with NTSTATUS $NTStatus"
If ($PHAlgorithm -NE [IntPtr]::Zero)
{
$NTStatus = [BCrypt]::BCryptCloseAlgorithmProvider($PHAlgorithm, 0)
}
Return
}
$NTStatus = [BCrypt]::BCryptCreateHash($PHAlgorithm, [Ref] $PHHash, [IntPtr]::Zero, 0, [IntPtr]::Zero, 0, 0)
If ($NTStatus -NE 0)
{
Write-Error "BCryptCreateHash failed with NTSTATUS $NTStatus"
If ($PHHash -NE [IntPtr]::Zero)
{
$NTStatus = [BCrypt]::BCryptDestroyHash($PHHash)
}
If ($PHAlgorithm -NE [IntPtr]::Zero)
{
$NTStatus = [BCrypt]::BCryptCloseAlgorithmProvider($PHAlgorithm, 0)
}
Return
}
$NTStatus = [BCrypt]::BCryptHashData($PHHash, $DataToHash, $DataToHash.Length, 0)
$NTStatus = [BCrypt]::BCryptFinishHash($PHHash, $HashBytes, $HashBytes.Length, 0)
If ($PHHash -NE [IntPtr]::Zero)
{
$NTStatus = [BCrypt]::BCryptDestroyHash($PHHash)
}
If ($PHAlgorithm -NE [IntPtr]::Zero)
{
$NTStatus = [BCrypt]::BCryptCloseAlgorithmProvider($PHAlgorithm, 0)
}
$HashString = New-Object System.Text.StringBuilder
Foreach ($Byte In $HashBytes)
{
[Void]$HashString.Append($Byte.ToString("X2"))
}
Return $HashString.ToString()
}
}
Get-MD4Hash -DataToHash ([System.Text.Encoding]::Unicode.getBytes($password))
Ich schätze mal das kommt vom unterschiedlichen PHP-Encoding seiner PHP-Umgebung. Er sollte prüfen ob alles auf UTF-8 kodiert vorliegt/eingestellt ist. Oder eben das Input-Encoding mit mb_http_input auslesen und an iconv übergeben.