diff --git a/csharp/src/detectors/cookie-without-http-only-flag/web-config-insecure-cookie-settings-csharp-rule.web.config b/csharp/src/detectors/cookie-without-http-only-flag/web-config-insecure-cookie-settings-csharp-rule.web.config new file mode 100644 index 0000000..e6af28c --- /dev/null +++ b/csharp/src/detectors/cookie-without-http-only-flag/web-config-insecure-cookie-settings-csharp-rule.web.config @@ -0,0 +1,88 @@ +// {fact rule=cookie-without-http-only-flag@v1.0 defects=0} + + + + // Compliant: Sensitive cookie with 'HttpOnly' flag + + + + + + + + + + + + + + + + + + + + + + + + + //{fact} + + + //{fact rule=cookie-without-http-only-flag@v1.0 defects=0} + + + + // Noncompliant: Sensitive cookie without 'HttpOnly' flag + + + + + + + + + + + + + + + + + + + + + + + + + //{fact} \ No newline at end of file diff --git a/csharp/src/detectors/csharp-ldap-injection/csharp-ldap-injection.cs b/csharp/src/detectors/csharp-ldap-injection/csharp-ldap-injection.cs new file mode 100644 index 0000000..e6519ce --- /dev/null +++ b/csharp/src/detectors/csharp-ldap-injection/csharp-ldap-injection.cs @@ -0,0 +1,55 @@ +// {fact rule=ldap-injection@v1.0 defects=1} +public User Login(string userName, string password) + { + using (DirectoryEntry entry = new DirectoryEntry(config.Path, config.UserDomainName + "\\" + userName, password)) + { + using (DirectorySearcher searcher = new DirectorySearcher(entry)) + { + // Noncompliant: improper validation or sanitization + searcher.Filter = String.Format("({0}={1})", SAMAccountNameAttribute, userName); + searcher.PropertiesToLoad.Add(DisplayNameAttribute); + searcher.PropertiesToLoad.Add(SAMAccountNameAttribute); + var result = searcher.FindOne(); + if (result != null) + { + var displayName = result.Properties[DisplayNameAttribute]; + var samAccountName = result.Properties[SAMAccountNameAttribute]; + + return new User + { + DisplayName = displayName == null || displayName.Count <= 0 ? null : displayName[0].ToString(), + UserName = samAccountName == null || samAccountName.Count <= 0 ? null : samAccountName[0].ToString() + }; + } + } + } + } +// {/fact} + +// {fact rule=ldap-injection@v1.0 defects=0} + public User Login1(string userName, string password) + { + using (DirectoryEntry entry = new DirectoryEntry(config.Path, config.UserDomainName + "\\" + userName, password)) + { + using (DirectorySearcher searcher = new DirectorySearcher(entry)) + { + // Compliant: proper validation or sanitization + searcher.Filter = String.Format("({0}={1})", Encoder.LdapFilterEncode(SAMAccountNameAttribute), Encoder.LdapFilterEncode(userName)); + searcher.PropertiesToLoad.Add(DisplayNameAttribute); + searcher.PropertiesToLoad.Add(SAMAccountNameAttribute); + var result = searcher.FindOne(); + if (result != null) + { + var displayName = result.Properties[DisplayNameAttribute]; + var samAccountName = result.Properties[SAMAccountNameAttribute]; + + return new User + { + DisplayName = displayName == null || displayName.Count <= 0 ? null : displayName[0].ToString(), + UserName = samAccountName == null || samAccountName.Count <= 0 ? null : samAccountName[0].ToString() + }; + } + } + } + } + // {/fact} \ No newline at end of file diff --git a/csharp/src/detectors/double-epsilon-equality/doubleepsilonequality.cs b/csharp/src/detectors/double-epsilon-equality/doubleepsilonequality.cs new file mode 100644 index 0000000..251fa43 --- /dev/null +++ b/csharp/src/detectors/double-epsilon-equality/doubleepsilonequality.cs @@ -0,0 +1,22 @@ +using System; + + public class Example + { + + // {fact rule=double-epsilon-equality@v1.0 defects=1} + static bool lazyEqualLeftCompare(double v1, double v2){ + // Noncompliant: valur other than 0 + return Math.Abs(v1 - v2) <= Double.Epsilon; + } + // {/fact} + + // {fact rule=double-epsilon-equality@v1.0 defects=0} + + static bool uselessZeroEqual(){ + double v1 = 0; + double v2 = 0; + // Compliant: value is zero + return Math.Abs(v1 - v2) <= Double.Epsilon; + } + // {/fact} + } \ No newline at end of file diff --git a/csharp/src/detectors/jwt-tokenvalidationparameters-no-expiry/jwttokenvalidationparametersnoexpiry.cs b/csharp/src/detectors/jwt-tokenvalidationparameters-no-expiry/jwttokenvalidationparametersnoexpiry.cs new file mode 100644 index 0000000..9e4064e --- /dev/null +++ b/csharp/src/detectors/jwt-tokenvalidationparameters-no-expiry/jwttokenvalidationparametersnoexpiry.cs @@ -0,0 +1,30 @@ +// {fact rule=jwt-no-expiry@v1.0 defects=1} +services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => + { + + options.TokenValidationParameters = new TokenValidationParameters + { + // Noncompliant: ValidateLifetime is set to false + ValidateLifetime = false, + RequireSignedTokens = true, + ValidateIssuer = false, + ValidateAudience = false, + RequireExpirationTime = true + }; + }); + // {/fact} + + // {fact rule=jwt-no-expiry@v1.0 defects=0} + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => + { + + options.TokenValidationParameters = new TokenValidationParameters + { + // Compliant: ValidateLifetime is set to true + ValidateLifetime = true, + RequireSignedTokens = true, + ValidateIssuer = false, + ValidateAudience = false, + RequireExpirationTime = true + }; + }); diff --git a/csharp/src/detectors/mass-assignment/MassAssignment.cs b/csharp/src/detectors/mass-assignment/MassAssignment.cs new file mode 100644 index 0000000..7cd8c6a --- /dev/null +++ b/csharp/src/detectors/mass-assignment/MassAssignment.cs @@ -0,0 +1,18 @@ + using Microsoft.AspNetCore.Mvc; + // {fact rule=mass-assignment@v1.0 defects=1} + public IActionResult Create(UserModel model) + { + context.SaveChanges(); + // Noncompliant: `Bind` attribute not present + return View("Index", model); + } + // {fact} + + // {fact rule=mass-assignment@v1.0 defects=0} + public IActionResult Create([Bind(nameof(UserModel.Name))] UserModel model) + { + context.SaveChanges(); + // Compliant: `Bind` attribute present + return View("Index", model); + } + // {fact} \ No newline at end of file diff --git a/csharp/src/detectors/memory-marshal-create-span/MemMarshalCreateSpan.cs b/csharp/src/detectors/memory-marshal-create-span/MemMarshalCreateSpan.cs new file mode 100644 index 0000000..230ffb9 --- /dev/null +++ b/csharp/src/detectors/memory-marshal-create-span/MemMarshalCreateSpan.cs @@ -0,0 +1,22 @@ +namespace MemMarshalCreateSpan { + public class MemMarshalCreateSpan { + // {fact rule=memory-marshal-create-span@v1.0 defects=1} + public void MarshalNoncompliant() { + + // Noncompliant: length argument is not checked + Span ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 1); + + } + // {/fact} + + // {fact rule=memory-marshal-create-span@v1.0 defects=0} + public void MarshalCompliant() { + memory-marshal-create-span@v1.0 + + // Compliant: length argument is checked + Span intSpan = MemoryMarshal.Cast(byteSpan); + + } + // {/fact} + } + } \ No newline at end of file diff --git a/csharp/src/detectors/net-web-config-debug/net-web-config-debug.web.config b/csharp/src/detectors/net-web-config-debug/net-web-config-debug.web.config new file mode 100644 index 0000000..1080f39 --- /dev/null +++ b/csharp/src/detectors/net-web-config-debug/net-web-config-debug.web.config @@ -0,0 +1,25 @@ + + #{fact rule=debugbinary@v1.0eifjcbfcvuunegvkrtccfccigfktjuddgegletttbctr + defects=1} + + + # Noncompliant: `debug` is set to `false` + + + + + #{fact} + + #{fact rule=debugbinary@v1.0 defects=0} + + + # complaint: `debug` is set to `true` + + + + #fact \ No newline at end of file diff --git a/csharp/src/detectors/prevent-excessive-authentication/PreventExcessiveAuthentication.cs b/csharp/src/detectors/prevent-excessive-authentication/PreventExcessiveAuthentication.cs new file mode 100644 index 0000000..5ca2c7f --- /dev/null +++ b/csharp/src/detectors/prevent-excessive-authentication/PreventExcessiveAuthentication.cs @@ -0,0 +1,73 @@ +// {fact rule=prevent-excessive-authentication@v1.0 defects=1} +public async Task OnPostAsync(string returnUrl = null) + { + returnUrl = returnUrl ?? Url.Content("~/"); + + if (ModelState.IsValid) + { + // Noncompliant: lockoutOnFailure us set to false + var result = await _signInManager.PasswordSignInAsync(Input.Email, + Input.Password, Input.RememberMe, + lockoutOnFailure: false); + if (result.Succeeded) + { + _logger.LogInformation("User logged in."); + return LocalRedirect(returnUrl); + } + if (result.RequiresTwoFactor) + { + return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, + Input.RememberMe }); + } + if (result.IsLockedOut) + { + _logger.LogWarning("User account locked out."); + return RedirectToPage("./Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid login attempt."); + return Page(); + } + } + + return Page(); + } + //{fact} + + // {fact rule=prevent-excessive-authentication@v1.0 defects=0} + public async Task OnPostAsync(string returnUrl = null) + { + returnUrl = returnUrl ?? Url.Content("~/"); + if (ModelState.IsValid) + { + // Compliant:lockoutOnFailure is set to true + var result = await _signInManager.PasswordSignInAsync(Input.Email, + Input.Password, Input.RememberMe, + lockoutOnFailure: true); + + if (result.Succeeded) + { + _logger.LogInformation("User logged in."); + return LocalRedirect(returnUrl); + } + if (result.RequiresTwoFactor) + { + return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, + Input.RememberMe }); + } + if (result.IsLockedOut) + { + _logger.LogWarning("User account locked out."); + return RedirectToPage("./Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid login attempt."); + return Page(); + } + } + + return Page(); + } +//{fact} \ No newline at end of file diff --git a/csharp/src/detectors/razor-use-of-htmlstring/razor-use-of-htmlstring.cshtml b/csharp/src/detectors/razor-use-of-htmlstring/razor-use-of-htmlstring.cshtml new file mode 100644 index 0000000..3686a10 --- /dev/null +++ b/csharp/src/detectors/razor-use-of-htmlstring/razor-use-of-htmlstring.cshtml @@ -0,0 +1,31 @@ + + + public void RenderDescription(string description) + { + var newcontent = new Microsoft.AspNetCore.Html.HtmlString(description); + } + + +
+
+ +
@(new HtmlString(description))
+
+
+ + + + + public void RenderDescription(string description) + { + var newcontent = new Microsoft.AspNetCore.Html.HtmlString(WebUtility.HtmlEncode(description)); + } + + +
+
+ +
@(new HtmlString(HttpUtility.HtmlEncode(description)))
+
+
+ diff --git a/csharp/src/detectors/regioninfo-inter-process-write/RegioninfoInterProcessWrite.cs b/csharp/src/detectors/regioninfo-inter-process-write/RegioninfoInterProcessWrite.cs new file mode 100644 index 0000000..24644d3 --- /dev/null +++ b/csharp/src/detectors/regioninfo-inter-process-write/RegioninfoInterProcessWrite.cs @@ -0,0 +1,33 @@ +using System; + using System.Globalization; + + public class SamplesRegionInfo { + + public static void Main() { + + RegionInfo myRI1 = new RegionInfo( "US" ); + + RegionInfo myRI2 = new RegionInfo( new CultureInfo("en-US",false).LCID ); + + // {fact rule=regioninfointerprocesswrite@v1.0 defects=1} + using (AnonymousPipeServerStream pipeServer = + new AnonymousPipeServerStream(PipeDirection.Out, + HandleInheritability.Inheritable)){ + using(StreamWriter sw = new StreamWriter(pipeServer)){ + // Noncompliant: two-letter culture name + sw.WriteLine(myRI1); + }} + // {/fact} + + // {fact rule=regioninfointerprocesswrite@v1.0 defects=0} + using (AnonymousPipeServerStream pipeServer = + new AnonymousPipeServerStream(PipeDirection.Out, + HandleInheritability.Inheritable)){ + using(StreamWriter sw = new StreamWriter(pipeServer)){ + // Compliant: full culture name used + sw.WriteLine(myRI2); + }} + // {/fact} + } + } + diff --git a/csharp/src/detectors/unsigned-security-token-csharp-rule/impropercryptographicsignatureverification.cs b/csharp/src/detectors/unsigned-security-token-csharp-rule/impropercryptographicsignatureverification.cs new file mode 100644 index 0000000..a0bd17e --- /dev/null +++ b/csharp/src/detectors/unsigned-security-token-csharp-rule/impropercryptographicsignatureverification.cs @@ -0,0 +1,27 @@ +// {fact rule=impropercryptographicsignatureverification@v1.0 defects=1} +services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => + + { + + options.TokenValidationParameters = new TokenValidationParameters + { + // Noncompliant: RequireSignedTokens to false + RequireSignedTokens = false, + ValidateIssuer = false, + ValidateAudience = false + }; + }); + // {/fact} + +// {fact rule=impropercryptographicsignatureverification@v1.0 defects=0} +services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => + { + options.TokenValidationParameters = new TokenValidationParameters + { + // Compliant: RequireSignedTokens to True + RequireSignedTokens = true, + ValidateIssuer = false, + ValidateAudience = false + }; + }); + // {/fact} diff --git a/csharp/src/detectors/unvalidated-redirect/OpenRedirect.cs b/csharp/src/detectors/unvalidated-redirect/OpenRedirect.cs new file mode 100644 index 0000000..e0763cc --- /dev/null +++ b/csharp/src/detectors/unvalidated-redirect/OpenRedirect.cs @@ -0,0 +1,52 @@ +[HttpPost] + public ActionResult LogOn(LogOnModel model, string returnUrl) + { + if (ModelState.IsValid) + { + if (MembershipService.ValidateUser(model.UserName, model.Password)) + { + FormsService.SignIn(model.UserName, model.RememberMe); + if (!String.IsNullOrEmpty(returnUrl)) + { + // Noncompliant: open-redirect-csharp-rule + return Redirect(returnUrl); + } + else + { + return RedirectToAction("Index", "Home"); + } + } + else + { + ModelState.AddModelError("", + "The user name or password provided is incorrect."); + } + } + } + + + [HttpPost] + public ActionResult LogOn(LogOnModel model, string returnUrl) + { + if (ModelState.IsValid) + { + if (MembershipService.ValidateUser(model.UserName, model.Password)) + { + FormsService.SignIn(model.UserName, model.RememberMe); + if (IsLocalUrl(returnUrl)) + { + // Compliant: open-redirect-csharp-rule + return Redirect(returnUrl); + } + else + { + return RedirectToAction("Index", "Home"); + } + } + else + { + ModelState.AddModelError("", + "The user name or password provided is incorrect."); + } + } + } diff --git a/csharp/src/detectors/weak-cipher-algorithm/WeakCipherAlgorithm.cs b/csharp/src/detectors/weak-cipher-algorithm/WeakCipherAlgorithm.cs new file mode 100644 index 0000000..59fa018 --- /dev/null +++ b/csharp/src/detectors/weak-cipher-algorithm/WeakCipherAlgorithm.cs @@ -0,0 +1,21 @@ +using System.Security.Cryptography; + + class WeakCipherAlgorithm + { + + + // {fact rule=impropercryptographicsignatureverification@v1.0 defects=1} + static void DES() + { + // Noncompliant: insecure cryptographic algorithms used + DES provider = System.Security.Cryptography.DES.Create(); + } + // {/fact} + + // {fact rule=impropercryptographicsignatureverification@v1.0 defects=0} + public void CreateAes1() { + // Compliant: secure cryptographic algorithms used + var key = Aes.Create(); + } + // {/fact} + } \ No newline at end of file diff --git a/csharp/src/detectors/xpath-injection/XpathInjection.cs b/csharp/src/detectors/xpath-injection/XpathInjection.cs new file mode 100644 index 0000000..3d17cf0 --- /dev/null +++ b/csharp/src/detectors/xpath-injection/XpathInjection.cs @@ -0,0 +1,42 @@ +using System; +using System.Web; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Schema; +using System.Xml.XPath; +class XPathInjection +{ + // {fact rule=mass-assignment@v1.0 defects=1} + public List Search(string input) + { + List searchResult = new List(); + var webRoot = _env.WebRootPath; + var file = System.IO.Path.Combine(webRoot,"Knowledgebase.xml"); + + XmlDocument XmlDoc = new XmlDocument(); + XmlDoc.Load(file); + + XPathNavigator nav = XmlDoc.CreateNavigator(); + // Noncompliant: Improper input validation and sanitization. + XPathExpression expr = nav.Compile(@"//knowledge[tags[contains(text(),'" + input + "')] and sensitivity/text() ='Public']"); + } + // {/fact} + + // {fact rule=mass-assignment@v1.0 defects=0} + public List Search(string input) + { + List searchResult = new List(); + var webRoot = _env.WebRootPath; + var file = System.IO.Path.Combine(webRoot,"Knowledgebase.xml"); + + XmlDocument XmlDoc = new XmlDocument(); + XmlDoc.Load(file); + + XPathNavigator nav = XmlDoc.CreateNavigator(); + // Compliant:proper input validation and sanitization. + XPathExpression expr = nav.Compile(@"//knowledge[tags[contains(text(),'keyword')] and sensitivity/text() ='Public']"); + + var matchedNodes = nav.Select(expr); + } + // {/fact} +} \ No newline at end of file