-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Implement DevSecOps demo page #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
@page | ||
@model webapp01.Pages.DevSecOpsModel | ||
@{ | ||
ViewData["Title"] = "DevSecOps Demonstration"; | ||
} | ||
|
||
<div class="text-center"> | ||
<h1 class="display-4">@ViewData["Title"]</h1> | ||
</div> | ||
|
||
<div> | ||
<h2>GitHub Advanced Security (GHAS)</h2> | ||
<p> | ||
GitHub Advanced Security provides a suite of tools to help you secure your software development lifecycle directly within your GitHub workflow. | ||
It helps you find and fix vulnerabilities earlier, automate security processes, and maintain compliance. | ||
</p> | ||
<p>Key features include:</p> | ||
<ul> | ||
<li><strong>Code scanning:</strong> Automatically analyzes your code for security vulnerabilities and coding errors. It supports a wide range of languages and frameworks. Results are displayed directly in pull requests.</li> | ||
<li><strong>Secret scanning:</strong> Detects secrets, such as tokens and private keys, that have been accidentally committed to your repository. It can prevent fraudulent use of compromised credentials.</li> | ||
<li><strong>Dependency review:</strong> Shows the full impact of changes to dependencies and displays details of any vulnerable versions before you merge a pull request.</li> | ||
</ul> | ||
|
||
<h3>Demonstrating Insecure Code Patterns</h3> | ||
<p>This page's backend includes examples of insecure code patterns for educational purposes. These are things GHAS can help identify.</p> | ||
|
||
<h4>Log Forging Example</h4> | ||
<p>Try adding <code>?userInput=test%0AINFO: Fake log entry</code> to the URL to see a log forging attempt.</p> | ||
<form method="get"> | ||
<div class="form-group"> | ||
<label for="userInputLog">User Input for Log:</label> | ||
<input type="text" class="form-control" id="userInputLog" name="userInput" value="test"> | ||
</div> | ||
<button type="submit" class="btn btn-primary mt-2">Test Log Forging</button> | ||
</form> | ||
@if (!string.IsNullOrEmpty(Model.LogForgingTestResult)) | ||
{ | ||
<div class="alert alert-info mt-2">@Model.LogForgingTestResult</div> | ||
} | ||
|
||
<h4>Regex Exposure (ReDoS) Example</h4> | ||
<p>The backend has a regex pattern <code>(a+)+$</code> which is vulnerable to ReDoS. Test with inputs like "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!" (many 'a's followed by an exclamation mark).</p> | ||
<form method="post"> | ||
<div class="form-group"> | ||
<label for="regexInput">Input for Regex Check:</label> | ||
<input type="text" class="form-control" id="regexInput" asp-for="RegexInput"> | ||
</div> | ||
<button type="submit" class="btn btn-primary mt-2" asp-page-handler="CheckRegex">Test Regex</button> | ||
</form> | ||
@if (!string.IsNullOrEmpty(Model.RegexTestResult)) | ||
{ | ||
<div class="alert alert-info mt-2">@Model.RegexTestResult</div> | ||
} | ||
|
||
</div> |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,84 @@ | ||||||||||||||||||||||||||
using Microsoft.AspNetCore.Mvc; | ||||||||||||||||||||||||||
using Microsoft.AspNetCore.Mvc.RazorPages; | ||||||||||||||||||||||||||
using Microsoft.Extensions.Logging; | ||||||||||||||||||||||||||
using System; | ||||||||||||||||||||||||||
using System.Text.RegularExpressions; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
namespace webapp01.Pages | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
public class DevSecOpsModel : PageModel | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
private readonly ILogger<DevSecOpsModel> _logger; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
[BindProperty(SupportsGet = true)] | ||||||||||||||||||||||||||
public string? UserInput { get; set; } | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
[BindProperty] | ||||||||||||||||||||||||||
public string? RegexInput { get; set; } | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public string? LogForgingTestResult { get; private set; } | ||||||||||||||||||||||||||
public string? RegexTestResult { get; private set; } | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public DevSecOpsModel(ILogger<DevSecOpsModel> logger) | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
_logger = logger; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public void OnGet() | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
_logger.LogInformation("DevSecOps page visited at {Time}", DateTime.UtcNow); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
if (!string.IsNullOrEmpty(UserInput)) | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
// Insecure Log Forging: UserInput is directly logged. | ||||||||||||||||||||||||||
// A malicious user could inject newline characters and fake log entries. | ||||||||||||||||||||||||||
// Example: userInput = "test%0AINFO:+User+logged+out" | ||||||||||||||||||||||||||
_logger.LogInformation("User input from query: " + UserInput); | ||||||||||||||||||||||||||
LogForgingTestResult = $"Logged: 'User input from query: {UserInput}'. Check the application logs."; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public IActionResult OnPostCheckRegex() | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
_logger.LogInformation("Checking regex pattern for input: {Input}", RegexInput); | ||||||||||||||||||||||||||
RegexTestResult = PerformRegexCheck(RegexInput ?? string.Empty); | ||||||||||||||||||||||||||
return Page(); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
private string PerformRegexCheck(string input) | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
// Insecure Regex (Potential ReDoS - Regular Expression Denial of Service) | ||||||||||||||||||||||||||
// The pattern (a+)+$ is an example of an "evil regex". | ||||||||||||||||||||||||||
// With inputs like "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!" (many 'a's followed by '!') | ||||||||||||||||||||||||||
// it can cause catastrophic backtracking, leading to high CPU usage and denial of service. | ||||||||||||||||||||||||||
// GHAS Code Scanning can often detect such vulnerable regex patterns. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the regex pattern is known to be vulnerable to ReDoS, add a comment or a TODO note clarifying that this insecure regex is for demonstration purposes only.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||||||
string pattern = @"(a+)+$"; | ||||||||||||||||||||||||||
string result; | ||||||||||||||||||||||||||
try | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
// It's good practice to set a timeout for regex operations. | ||||||||||||||||||||||||||
if (Regex.IsMatch(input, pattern, RegexOptions.None, TimeSpan.FromSeconds(2))) | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
result = "Regex pattern matched."; | ||||||||||||||||||||||||||
_logger.LogInformation(result); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
result = "Regex pattern did not match."; | ||||||||||||||||||||||||||
_logger.LogInformation(result); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
catch (RegexMatchTimeoutException ex) | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
result = $"Regex operation timed out for input: '{input}'. This indicates a potential ReDoS vulnerability. Exception: {ex.Message}"; | ||||||||||||||||||||||||||
_logger.LogWarning(result); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
catch (Exception ex) | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
result = $"An error occurred during regex matching: {ex.Message}"; | ||||||||||||||||||||||||||
_logger.LogError(ex, result); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
Comment on lines
+76
to
+80
Check noticeCode scanning / CodeQL Generic catch clause Note
Generic catch clause.
Copilot AutofixAI 7 days ago To fix the issue, replace the generic
This ensures that only anticipated errors are handled, while critical exceptions are not suppressed.
Suggested changeset
1
src/webapp01/Pages/DevSecOps.cshtml.cs
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
|
||||||||||||||||||||||||||
return result; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This direct concatenation of user input is intentionally insecure for demonstration of log forging; consider adding a clearer comment or a TODO indicating that this should never be used in production.
Copilot uses AI. Check for mistakes.