Der Hash-basierte Nachrichtenauthentifizierungscode (HMAC) ist ein Mechanismus zur Berechnung eines Nachrichtenauthentifizierungscodes, der eine Hash-Funktion in Kombination mit einem geheimen Schlüssel umfasst. Dies kann verwendet werden, um die Integrität und Authentizität einer Nachricht zu überprüfen.
Diese Implementierung ist stark von der Hauptauthentifizierungsmethode von Amazon Web Services (AWS Signature V4) inspiriert, da sie sehr gut verstanden wird und es eine Reihe von Bibliotheken gibt, die sie implementieren. Um diese Form der Authentifizierung zu verwenden, verwenden Sie eine Schlüsselkennung und einen geheimen Schlüssel, wobei beide normalerweise in einer Admin-Oberfläche generiert werden.
HmacAuthentication stellt einen AuthenticationHandler
bereit, der die HMAC-Authentifizierung in einem ASP.NET Core-Projekt unterstützt.
Verwendung:
appsettings.json
. Für die HMAC-Authentifizierung ist für jeden Client, der Zugriff erhalten soll, eine AppId
und ein ApiKey
erforderlich. var hmacAuthenticatedApps = this . Configuration
. GetSection ( " Authentication " )
. GetSection ( " HmacAuthenticatedApps " )
. Get < HmacAuthenticationClientConfiguration [ ] > ( )
. ToDictionary ( e => e . AppId , e => e . ApiKey ) ;
{
"Authentication" : {
"HmacAuthenticatedApps" : [
{
"AppId" : " <some-app-id> " ,
"ApiKey" : " <some-api-key> "
}
]
}
}
Startup.cs
in der Methode ConfigureServices
: services
. AddAuthentication ( o =>
{
o . DefaultScheme = HmacAuthenticationDefaults . AuthenticationScheme ;
} )
. AddHmacAuthentication ( HmacAuthenticationDefaults . AuthenticationScheme , " HMAC Authentication " , o =>
{
o . MaxRequestAgeInSeconds = HmacAuthenticationDefaults . MaxRequestAgeInSeconds ;
o . HmacAuthenticatedApps = hmacAuthenticatedApps ;
} ) ;
MemoryCache
(von Microsoft.Extensions.Caching.Memory) in Startup.cs
in der Methode ConfigureServices
hinzu. Der MemoryCache
wird vom HMAC AuthenticationHandler
verwendet, um Replay-Angriffe zu ermitteln. services . AddMemoryCache ( ) ;
Startup.cs
in der Methode Configure
: app . UseAuthentication ( ) ;
[ Authorize ( AuthenticationSchemes = HmacAuthenticationDefaults . AuthenticationScheme ) ]
[ Route ( " api/[controller] " ) ]
public class HomeController : Controller
{
// ...
}
HmacAuthenticaion bietet außerdem einen DelegatingHandler
zum Hinzufügen eines HMAC-Autorisierungsheaders zu HTTP-Anfragen.
Instanziieren Sie Ihre HttpClient
Instanz mit dem ApiKeyDelegatingHandler
. Stellen Sie sicher, dass Sie nicht für jede Anfrage neue HttpClient
-Instanzen erstellen (siehe auch diesen Blogbeitrag für Details):
new HttpClient ( new ApiKeyDelegatingHandler ( appId , apiKey ) ) ;
Oder falls es sich bei Ihrem WebAPI-Client um eine andere ASP.NET-WebAPI (>= ASP.NET Core 2.1) handelt, registrieren Sie Ihren HttpClient
beispielsweise wie folgt in Startup.cs
:
services . AddTransient ( sp => new ApiKeyDelegatingHandler ( appId , apiKey ) ) ;
services
. AddHttpClient ( " HmacHttpClient " )
. AddHttpMessageHandler < ApiKeyDelegatingHandler > ( ) ;
Um einen API-Schlüssel zu generieren, kann die folgende einfache Konsolenanwendung verwendet werden. Diese Implementierung wird auch auf .NET Fiddle bereitgestellt.
using System . Security . Cryptography ;
public class Program
{
public static void Main ( )
{
Console . WriteLine ( $" AppID: { Guid . NewGuid ( ) } or <some-speaking-name> " ) ;
Console . WriteLine ( $" ApiKey: { GenerateApiKey ( ) } " ) ;
}
private static string GenerateApiKey ( )
{
using ( var cryptoProvider = new RNGCryptoServiceProvider ( ) )
{
byte [ ] secretKeyByteArray = new byte [ 32 ] ; //256 bit
cryptoProvider . GetBytes ( secretKeyByteArray ) ;
return Convert . ToBase64String ( secretKeyByteArray ) ;
}
}
}
Die größten Sicherheitsrisiken liegen in der Regel nicht im Auth-Protokoll, sondern in den Richtlinien und Verfahren rund um seine Verwendung. Den Implementierern wird dringend empfohlen, zu bewerten, wie dieses Modul ihren Sicherheitsanforderungen gerecht wird. Dieser Abschnitt enthält eine unvollständige Liste von Sicherheitsüberlegungen, die vor der Bereitstellung dieses Authentifizierungsprotokolls auf dem Server überprüft und verstanden werden müssen. Viele der in den Spezifikationen vorgesehenen Schutzmaßnahmen hängen davon ab, ob und wie sie verwendet werden.
HmacAuthentication bietet keinen Mechanismus zum Erhalten oder Übertragen der erforderlichen gemeinsamen Anmeldeinformationen. Jeder Mechanismus, der zum Abrufen von HmacAuthentication- Anmeldeinformationen verwendet wird, muss sicherstellen, dass diese Übertragungen durch Transportschichtmechanismen wie TLS geschützt sind.
HmacAuthentication bietet zwar einen Mechanismus zur Überprüfung der Integrität von HTTP-Anfragen, bietet jedoch keine Garantie für die Vertraulichkeit der Anfragen. Sofern keine anderen Vorkehrungen getroffen werden, haben Abhörer vollen Zugriff auf den Inhalt der Anfrage. Server sollten die Datentypen, die im Rahmen solcher Anfragen voraussichtlich gesendet werden, sorgfältig abwägen und Sicherheitsmechanismen auf der Transportschicht einsetzen, um sensible Ressourcen zu schützen.
HmacAuthentication bietet eine begrenzte Überprüfung der Serverauthentizität. Beim Empfang einer Antwort vom Server.
Eine feindliche Partei könnte dies ausnutzen, indem sie die Anfragen des Kunden abfängt und irreführende oder anderweitig falsche Antworten zurückgibt. Dienstanbieter sollten bei der Entwicklung von Diensten, die dieses Protokoll verwenden, solche Angriffe in Betracht ziehen und für alle Anfragen, bei denen die Authentizität des Ressourcenservers oder der Serverantworten ein Problem darstellt, Transportschichtsicherheit fordern.
Der HmacAuthentication- Schlüssel funktioniert auf die gleiche Weise wie Passwörter in herkömmlichen Authentifizierungssystemen. Um den Anforderungs-MAC zu berechnen, muss der Server Zugriff auf den Schlüssel im Klartext haben. Dies steht beispielsweise im Gegensatz zu modernen Betriebssystemen, die nur einen Einweg-Hash der Benutzeranmeldeinformationen speichern.
Wenn ein Angreifer Zugriff auf diese Schlüssel erhalten würde – oder schlimmer noch, auf die Datenbank aller dieser Schlüssel auf dem Server – wäre er oder sie in der Lage, im Namen eines beliebigen Ressourceneigentümers jede beliebige Aktion auszuführen. Dementsprechend ist es wichtig, dass Server diese Schlüssel vor unbefugtem Zugriff schützen.
Sofern kein Transportschicht-Sicherheitsprotokoll verwendet wird, haben Abhörer vollen Zugriff auf authentifizierte Anforderungen und Anforderungs-MAC-Werte und können daher Offline-Brute-Force-Angriffe durchführen, um den verwendeten Schlüssel wiederherzustellen. Server sollten darauf achten, Schlüssel zuzuweisen, die lang genug und zufällig genug sind, um solchen Angriffen mindestens so lange zu widerstehen, wie die HmacAuthentication- Anmeldeinformationen gültig sind.
Wenn die Anmeldeinformationen beispielsweise zwei Wochen lang gültig sind, sollten Server sicherstellen, dass es nicht möglich ist, einen Brute-Force-Angriff durchzuführen, der den Schlüssel in weniger als zwei Wochen wiederherstellt. Natürlich sind Server dazu angehalten, auf Nummer sicher zu gehen und den längsten sinnvollen Schlüssel zu verwenden.
Ebenso wichtig ist, dass der zur Generierung dieser Schlüssel verwendete Pseudozufallszahlengenerator (PRNG) von ausreichend hoher Qualität ist. Viele PRNG-Implementierungen generieren Zahlenfolgen, die zufällig erscheinen, aber dennoch Muster oder andere Schwächen aufweisen, die Kryptoanalysen oder Brute-Force-Angriffe erleichtern. Um diese Probleme zu vermeiden, sollten Implementierer darauf achten, kryptografisch sichere PRNGs zu verwenden.
Der Anforderungs-MAC deckt nur den HTTP- Host
-Header, den Content-Type
-Header und optional einen bestimmten Satz von Headern ab. Es deckt keine anderen Header ab, die ihm nicht bekannt sind und die sich häufig auf die Interpretation des Anforderungstexts durch den Server auswirken können. Wenn das Serververhalten durch das Vorhandensein oder den Wert solcher Header beeinflusst wird, kann ein Angreifer die Anforderungsheader unbemerkt manipulieren. Implementierer sollten die headers
Funktion verwenden, um Header zu übergeben, die der Signatur über den Authorization
Header hinzugefügt werden sollen, der durch den Anforderungs-MAC geschützt ist. Der Signature Base String ist dann dafür verantwortlich, diese gegebenen Header zur Signatur hinzuzufügen, damit sie Teil des MAC werden.
Wenn die Antwortauthentifizierung durchgeführt wird, deckt sie nur den Antworttext (Nutzlast) und einige der vom Client in seiner Anfrage bereitgestellten Anforderungsinformationen ab, z. B. Zeitstempel und Nonce. Es deckt nicht den HTTP-Statuscode oder andere Antwort-Header-Felder (z. B. Standort) ab, die sich auf das Verhalten des Clients auswirken können.
Wenn ein Angreifer in der Lage ist, diese Informationen zu manipulieren und den Client dazu zu bringen, eine falsche Zeit zu verwenden, könnte er dazu führen, dass der Client in Zukunft authentifizierte Anfragen unter Verwendung der Zeit generiert. Solche Anfragen schlagen fehl, wenn sie vom Client gesendet werden, und hinterlassen wahrscheinlich keine Spuren auf dem Server (angesichts der allgemeinen Implementierung von Nonce, wenn überhaupt erzwungen). Der Angreifer kann die Anfrage dann zum richtigen Zeitpunkt erneut abspielen, ohne dass er erkannt wird.
Eine Lösung für dieses Problem wäre eine Uhrensynchronisierung zwischen Client und Server. Um dies zu erreichen, informiert der Server den Client über seine aktuelle Uhrzeit, wenn ein ungültiger Zeitstempel empfangen wird. Dies geschieht in Form eines Date-Headers in der Antwort. Sehen Sie RFC2616 als Motivation hierfür.
Der Client sollte die vom Server bereitgestellten Zeitinformationen nur verwenden, wenn:
Wenn eine Anfrage mit einem fehlerhaften Zeitstempel eingeht, stellt der Server dem Client seine aktuelle Uhrzeit zur Verfügung. Der Client darf die vom Server erhaltene Zeit niemals zum Anpassen seiner eigenen Uhr verwenden und darf sie nur zum Berechnen eines Offsets für die Kommunikation mit diesem bestimmten Server verwenden.
HmacAuthentication validiert den eingehenden Anforderungs-MAC anhand des eingehenden HTTP-Host-Headers. Ein bösartiger Client kann neue Hostnamen erstellen, die auf die IP-Adresse des Servers verweisen, und diese für einen Angriff verwenden, indem er eine gültige Anfrage sendet, die für einen anderen Hostnamen als den vom Server verwendeten gedacht ist. Serverimplementierer müssen manuell überprüfen, ob der empfangene Host-Header ihren Erwartungen entspricht. Wenn Sie beispielsweise API-Aufrufe auf test.myapi.com erwarten, stellen Sie sicher, dass es sich bei der Serverimplementierung um die Domäne handelt, an die die Anforderung gesendet wurde.