Skip to main content

Untitled

· 4 min read
Mark Burton
Software Engineer & Technical Writer

I was reviewing one of my old sample projects codebase which makes use of asp.net Identity for storage of users and passwords, in the startup I noticed the following code:

services.Configure<PasswordHasherOptions>(options => {
options.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2;
});
``` This can be used to migrate from older versions of asp.net Identity and Identity Server using asp.net Identity to the latest version without needing to handle the migration of users passwords to the new hashing algorithm. That is good for ease of development, but should the hashes get into the wrong hands they will be easier to crack.

The PasswordHasher code can be read in the [AspNetCore GitHub repo](https://github.com/dotnet/AspNetCore/blob/main/src/Identity/Extensions.Core/src/PasswordHasher.cs).

The comments at the top of that file explain the 2 different hashing algorithms supported by the default password hasher implementation. This shows that V2 is a relatively weak hash with a small number of iterations, whereas V3 is now SHA-512 with 100,000 iterations after being SHA-256 with . This is recent update

```csharp
/*
* =======================
* HASHED PASSWORD FORMATS
* =======================
*
* Version 2:
* PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations.
* (See also: SDL crypto guidelines v5.1, Part III)
* Format: { 0x00, salt, subkey }
*
* Version 3 (.net 7 and above):
* PBKDF2 with HMAC-SHA512, 128-bit salt, 256-bit subkey, 100000 iterations.
* Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
* (All UInt32s are stored big-endian.)
*
* Version 3 (.net 6 and below):
* PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations.
* Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
* (All UInt32s are stored big-endian.)
*/
``` In 2014 Brock Allen wrote the post [How MembershipReboot stores passwords properly](https:/brockallen.com20140209how-membershipreboot-stores-passwords-properly) where it was written; > This means in 2012 we should have been using 64000 iterations and in 2014 we should be using 128000 iterations. As previously mentioned, this is hardware dependent and the real target is 500 to 1000 milliseconds. The code in the MembershipReboot repo suggests that did not remain correct and in 2018 the default was set to 50,000. In 2017 NIST published the following guidance [800-63B
Digital Identity Guidelines - Authentication and Lifecycle Management](https:/pages.nist.gov800-63-3sp800-63b.html) > The salt SHALL be at least 32 bits in length and be chosen arbitrarily so as to minimize salt value collisions among stored hashes. Both the salt value and the resulting hash SHALL be stored for each subscriber using a memorized secret authenticator. > For PBKDF2, the cost factor is an iteration count: the more times the PBKDF2 function is iterated, the longer it takes to compute the password hash. Therefore, the iteration count SHOULD be as large as verification server performance will allow, typically at least 10,000 iterations. With that, lets try and crack these password hashes, we have a salted hash, so how easy can it be to crack such a password? ## Converting the hash into hashcat format There are many tools in various languages to convert the base64 encoded password hash into a format hashcat can crack. Based on 2 different GitHub repos I created Replits to cover the V2 and V3 asp.net Identity hashing algorithms. ### Replit base64 encoded V2 hash to hashcat format
[Replit aspnet Identity V2 to Hashcat](https:/replit.com@markburton2aspnetIdentityV2ToHashcat#main.py) `python main.py -i base64hash -o out` `AAR65WvZryqTHSnKGfH+D6aInhFCZfk2khdye+6PMdRiVeG2Ai9eBtErYndhtu6Iw==` `sha1:1000:BHrla9mvKpMdKcr8Z8f4Pg==:miJ4RQmX5NpIXcnvujzHUYlXhtgIvXgbRK2J3YbbuiM=` `12000 PBKDF2-HMAC-SHA1` ### Replit base64 encoded V3 hash to hashcat format
https:/replit.com@markburton2aspnetIdentityToHashcat#main.cs `sha256:10000:bvHHyyaHNxgVoCE9JGPWuA==:MXwKKigb+FjP+EfmdErxcbcbjJH4AUtvKdTEM71dDnk=` ``` csharp ``` https:/github.comNetDevPackNetDevPackblobmastersrcNetDevPackUtilitiesAspNetIdentityHashInfo.cs
``` csharp ``` https:/hashcat.netwikidoku.php?id=example_hashes `10900 PBKDF2-HMAC-SHA256 sha256:1000:MTc3MTA0MTQwMjQxNzY=:PYjCU215Mi57AYPKva9j7mvF4Rc5bCnt` `12100 PBKDF2-HMAC-SHA512 sha512:1000:ODQyMDEwNjQyODY=:MKaHNWXUsuJB3IEwBHbm3w==` ## Dotnet Global tool I wanted to be able to look at my databases and check what the hashes were so I created a dotnet tool with the knowledge gained from the previous libraries. [](https:/www.nuget.orgpackagesNallixion.ASPNET.Identity.HashDecoder) ``` powershell
dotnet tool install --global Nallixion.ASPNET.Identity.HashDecoder --version 0.0.1-alpha.1
``` ## Hashing rate on a VM on my laptop This is far from what a machine with a GPU could achieve.

Untitled

· 3 min read
Mark Burton
Software Engineer & Technical Writer

I wanted to understand more about how ChatGPT and Co-Pilots like those from GitHub and Pieces work and how I could do something similar including private content, whilst reading around the topic I read the article Demystifying Retrieval Augmented Generation with .NET and thought it described what I wanted to achieve so decided to follow along. The first challenge I encountered was that Azure OpenAI Service is only available for "eligible customers and partners" which, for my personal projects, I do not qualify. That is not a problem though as Stephan explains in the post it is trivial to switch to OpenAI which offers a free quota of $5 per month. Next issue was that the code examples did not compile, this seems to be because the Semantic Kernel library has moved on from version 0.24 to 1.0.1 since the post was written. Some of the the changes are covered in the post Saying hello to Microsoft Semantic Kernel V1 (and upgrading from preview). ### Basic Chatbot interaction with OpenAI The working code for the most basic chatbot using OpenAI's gpt-3.5-turbo model is below. csharp using Microsoft.SemanticKernel; internal class Program \\\{ private static async Task Main(string[] args) \{ string oaiApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!; string oaiModel = "gpt-3.5-turbo-1106"; Initialize the kernel IKernelBuilder builder = Kernel.CreateBuilder(); builder.Services.AddOpenAIChatCompletion(oaiModel, oaiApiKey); var kernel = builder.Build(); // Q&A loop while (true) { Console.Write("Question: "); Console.WriteLine((await kernel.InvokePromptAsync(Console.ReadLine()!)).GetValue&lt;string>()); Console.WriteLine(); \\} } } ### Storing Messages In The Chat History Adding chat history means the chatbot can keep track of the conversation and be given a bit of personality. csharp private static async Task Main(string[] args) \\\{ string aoaiApiKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!; string oaiModel = "gpt-3.5-turbo-1106"; Initialize the kernel IKernelBuilder builder = Kernel.CreateBuilder(); builder.Services.AddOpenAIChatCompletion(oaiModel, aoaiApiKey); var kernel = builder.Build(); // Create a new chat IChatCompletionService ai = kernel.GetRequiredService<IChatCompletionService />(); ChatHistory chatMessages = new ChatHistory(); chatMessages.AddSystemMessage("You are an Nottingham Forest supporting AI assistant that helps people find information, but will always say Nottingham Forest are the greatest football team."); // Q&A loop while (true) \{ Console.Write("Question: "); chatMessages.AddUserMessage(Console.ReadLine()!); // Get the chat completions OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new() { ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions \\}; var result = ai.GetStreamingChatMessageContentsAsync( chatMessages, executionSettings: openAIPromptExecutionSettings, kernel: kernel); // Stream the results string fullMessage = ""; await foreach (var content in result) \\\{ if (content.Role.HasValue) \{ System.Console.Write("Assistant &gt; "); \\} System.Console.Write(content.Content); fullMessage += content.Content; } System.Console.WriteLine(); // Add the message from the agent to the chat history chatMessages.AddAssistantMessage(fullMessage); } } So far so good, but there is a limit to how much data you can pass in with messages before hitting errors like context_length_exceeded.

Untitled

· One min read
Mark Burton
Software Engineer & Technical Writer

For years I have felt that if you are offering a public API it should be documented well enough for consumers to generate a client library in whatever language they are using, it is almost implausible to create client libraries in all languages your consumers might use, but a good OpenAPI definition allows consumers to understand an API and use tools to generate client libraries. Over the years I have worked with NSwag, which was good but put all the code in 1 file which I didn't like. AutoRest, which seemed to get more difficult to work with when V3 was released, so I looked around again and found OpenAPI Generator, which is great but needs Java. With the release of Kiota I was excited to look at how a dotnet tool could tackle the same requirement. ## What is Kiota? Kiota is a client generator for OpenAPI and was introduced at .NET Conf 2023.

<iframe width="560" height="315" src="https:/www.youtube.comembedsQ9Pv-rQ1s8?si=4wl3jIZWa3VY9sWF" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen> ## Quickstart Kiota Project Learn

Untitled

· One min read
Mark Burton
Software Engineer & Technical Writer

What is zakwas and żurek?

Untitled

· One min read
Mark Burton
Software Engineer & Technical Writer

csharp SAST with Semgrep ### Installation Run sudo apt-get update && sudo apt-get upgrade because it is good for you. https:/semgrep.devdocsgetting-started/ ### The command semgrep scan --config=auto

Untitled

· One min read
Mark Burton
Software Engineer & Technical Writer

Initial setup

Red lights flashing seem to be undocumented errors. ## HolyStone support ## 2nd Try! ## Restricted flight Zones in Luxembourg https:/map.geoportail.luthememain?lang=fr&version=3&zoom=9&X=683912&Y=6420160&rotation=0&layers=1928-1927&opacities=0.5-0.5&bgLayer=basemap_2015_global&time=--&crosshair=false ## Drone registration https:/dac.gouvernement.luendroneswhere-when-register.html

Untitled

· One min read
Mark Burton
Software Engineer & Technical Writer
  • Learn how to use alternative authentication material to move laterally.
  • Learn different methods to use compromised hosts as pivots. ### Task 2 - Moving Through the Network #### Question 1 #### Answer

Reveal Answer ### Task 3 - Spawning Processes Remotely #### Question 1 #### Answer Reveal Answer

Sourdough Starter

· One min read
Mark Burton
Software Engineer & Technical Writer

Try Hack Me, Password Attacks

· One min read
Mark Burton
Software Engineer & Technical Writer
  • Password attacks techniques
  • Online password attacks ### Task 2 - Password Attacking Techniques #### Question 1 Which type of password attack is performed locally? #### Answer

Password cracking Reveal Answer