public void Inspect(ResponseAnalysisContext context, CancellationToken cancellationToken) { if (context.IsHtml()) { // read content string html = context.ReadAsString(); if (html == null) { return; } string csrfTag = null; // enumerate forms foreach (var formIndex in FastHtmlParser.FindAllTagIndexes(html, "form")) { // check method attribute var method = FastHtmlParser.GetAttributeValueAtTag(html, "method", formIndex); if (method.Equals("post", StringComparison.OrdinalIgnoreCase)) { // generate CSRF hidden field if (csrfTag == null) { var tokens = Antiforgery.GetAndStoreTokens(context.HttpContext); csrfTag = $"<input type=\"hidden\" name=\"{HtmlEncoder.Default.Encode(tokens.FormFieldName)}\" value=\"{HtmlEncoder.Default.Encode(tokens.RequestToken)}\" />"; } // insert field int close = FastHtmlParser.FindClosePairFlatIndex(html, "form", formIndex); context.AddChange(TextChange.Insert(html, close, csrfTag)); } } } }
private static void InspectBody(ResponseAnalysisContext context) { var html = context.ReadAsString(); if (html != null) { foreach (var index in FastHtmlParser.FindAllTagIndexes(html, "meta")) { if (FastHtmlParser.GetAttributeValueAtTag(html, "name", index).Equals("generator", StringComparison.OrdinalIgnoreCase)) { var end = FastHtmlParser.FindEndOfOpenTag(html, index) + 1; context.AddChange(TextChange.Remove(html, index, end - index)); } } } }
public async Task InspectAsync(ResponseAnalysisContext context, CancellationToken cancellationToken) { if (context.IsHtml()) { var html = context.ReadAsString(); // find all script tags foreach (var index in FastHtmlParser.FindAllTagIndexes(html, "script")) { // get 'src' attribute var src = FastHtmlParser.GetAttributeValueAtTag(html, "src", index); if (src.IndexOf(':') != -1 || src.StartsWith("//", StringComparison.Ordinal)) { // check whether there is an 'integrity' attribute alrady var integrity = FastHtmlParser.GetAttributeValueAtTag(html, "integrity", index); if (integrity.Length > 0) { continue; } // compute integrity var sri = await MemoryCache.GetOrCreateAsync($"SRI_{src}", async ce => { ce.SetAbsoluteExpiration(DateTimeOffset.MaxValue); ce.SetPriority(CacheItemPriority.High); var client = HttpClientFactory.CreateClient(); try { // download script using var request = new HttpRequestMessage(HttpMethod.Get, RelativeTo(src).ToString()); request.Headers.TryAddWithoutValidation("Origin", $"{context.HttpContext.Request.Scheme}://{context.HttpContext.Request.Host}"); using var response = await client.SendAsync(request); if (!response.IsSuccessStatusCode) { return(null); } if (response.Content == null) { return(null); } if (!response.Headers.Any(h => h.Key.StartsWith("Access-Control-Allow", StringComparison.OrdinalIgnoreCase))) { return(null); } var stream = await response.Content.ReadAsStreamAsync(); // compute hash var hash = HashAlgorithmPool.Sha256.ComputeHash(stream); var base64 = Convert.ToBase64String(hash); return($"sha256-{base64}"); } catch (HttpRequestException) { return(null); } }); // add attribute if (sri != null) { context.AddChange(FastHtmlParser.CreateInsertAttributeChange(html, index, "script", "integrity", sri)); if (FastHtmlParser.GetAttributeValueAtTag(html, "crossorigin", index).Length == 0) { context.AddChange(FastHtmlParser.CreateInsertAttributeChange(html, index, "script", "crossorigin", "anonymous")); } } } } } }