The OWASP Top 10 is a standard awareness document for developers and web application security. It represents a broad consensus about the most critical security risks to web applications.
In this article, I want to cover the first part of the TOP 10 vulnerabilities and how to protect against them using .NET.
What it is?
Almost any source of data can be an injection - vector, environment variables, parameters, external and internal web services, and all types of users. Injection flaws occur when an attacker can send hostile data to an interpreter. Injection vulnerabilities are often found in SQL, LDAP, XPath, or NoSQL queries, OS commands, XML parsers, SMTP headers, expression languages, and ORM queries. Injection can result in data loss, corruption, or disclosure to unauthorized parties, loss of accountability, or denial of access.
What to do?
SQL Injection
Good example:
var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id";
context.Database.ExecuteSqlCommand(
sql,
new SqlParameter("@FirstName", firstname),
new SqlParameter("@Id", id));
Bad example:
string strQry = "SELECT * FROM Users WHERE UserName='" + txtUser.Text + "' AND Password='"
+ txtPassword.Text + "'";
EXEC strQry // SQL Injection vulnerability!
OS Injection
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "validatedCommand";
startInfo.Arguments = "validatedArg1 validatedArg2 validatedArg3";
process.StartInfo = startInfo;
process.Start();
//User input
string ipAddress = "127.0.0.1";
//check to make sure an ip address was provided
if (!string.IsNullOrEmpty(ipAddress))
{
// Create an instance of IPAddress for the specified address string (in
// dotted-quad, or colon-hexadecimal notation).
if (IPAddress.TryParse(ipAddress, out var address))
{
// Display the address in standard notation.
return address.ToString();
}
else
{
//ipAddress is not of type IPAddress
}
}
LDAP injection
What it is?
Attackers can detect broken authentication using manual means and exploit them using automated tools with password lists and dictionary attacks. Attackers have to gain access to only a few accounts, or just one admin account to compromise the system. Depending on the domain of the application, this may allow money laundering, social security fraud, and identity theft, or disclose legally protected highly sensitive information.
What to do?
//startup.cs
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
options.Password.RequiredUniqueChars = 6;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 3;
options.SignIn.RequireConfirmedEmail = true;
options.User.RequireUniqueEmail = true;
});
//startup.cs
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.Expiration = TimeSpan.FromHours(1)
options.SlidingExpiration = true;
});
What it is?
Rather than directly attacking crypto, attackers steal keys, execute man-in-the-middle attacks, or steal clear text data off the server, while in transit, or from the user’s client, e.g. browser. The most common flaw is simply not encrypting sensitive data. When crypto is employed, weak key generation and management, and weak algorithm, protocol and cipher usage is common, particularly for weak password hashing storage techniques. Failure frequently compromises all data that should have been protected. Typically, this information includes sensitive personal information (PII) data such as health records, credentials, personal data, and credit cards, which often require protection as defined by laws or regulations such as the EU GDPR or local privacy laws.
What to do?
Example for headers
app.UseHsts(hsts => hsts.MaxAge(365).IncludeSubdomains());
app.UseXContentTypeOptions();
app.UseReferrerPolicy(opts => opts.NoReferrer());
app.UseXXssProtection(options => options.FilterDisabled());
app.UseXfo(options => options.Deny());
app.UseCsp(opts => opts
.BlockAllMixedContent()
.StyleSources(s => s.Self())
.StyleSources(s => s.UnsafeInline())
.FontSources(s => s.Self())
.FormActions(s => s.Self())
.FrameAncestors(s => s.Self())
.ImageSources(s => s.Self())
.ScriptSources(s => s.Self())
);
What it is?
Attackers can exploit vulnerable XML processors if they can upload XML or include hostile content in an XML document, exploiting vulnerable code, dependencies or integrations. By default, many older XML processors allow specification of an external entity, a URI that is dereferenced and evaluated during XML processing. These flaws can be used to extract data, execute a remote request from the server, scan internal systems, perform a denial-of-service attack, as well as execute other attacks.
What to do?
static void LoadXML()
{
string xxePayload = "<!DOCTYPE doc [<!ENTITY win SYSTEM 'file:///C:/Users/testdata2.txt'>]>"
+ "<doc>&win;</doc>";
string xml = "<?xml version='1.0' ?>" + xxePayload;
XmlDocument xmlDoc = new XmlDocument();
// Setting this to NULL disables DTDs - Its NOT null by default.
xmlDoc.XmlResolver = null;
xmlDoc.LoadXml(xml);
Console.WriteLine(xmlDoc.InnerText);
Console.ReadLine();
}
XmlReader reader = XmlReader.Create("example.xml");
XPathDocument doc = new XPathDocument(reader);
XPathNavigator nav = doc.CreateNavigator();
string xml = nav.InnerXml.ToString();
What it is?
Exploitation of access control is a core skill of attackers. Access control is detectable using manual means, or possibly through automation for the absence of access controls in certain frameworks. Access control weaknesses are common due to the lack of automated detection, and lack of effective functional testing by application developers. The technical impact is attackers acting as users or administrators, or users using privileged functions, or creating, accessing, updating or deleting every record.
What to do?
CookieHttpOnly = true,
ExpireTimeSpan = TimeSpan.FromMinutes(60),
SlidingExpiration = false
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[AllowXRequestsEveryXSecondsAttribute(Name = "LogOn",
Message = "You have performed this action more than {x} times in the last {n} seconds.",
Requests = 3, Seconds = 60)]
public async Task<ActionResult> LogOn(LogOnViewModel model, string returnUrl)
[Authorize(Roles = "Admin")]
[HttpGet]
public ActionResult Index(int page = 1)
// or better yet, at controller level:
[Authorize]
public class UserController
// Insecure
public ActionResult Edit(int id)
{
var user = _context.Users.FirstOrDefault(e => e.Id == id);
return View("Details", new UserViewModel(user);
}
// Secure
public ActionResult Edit(int id)
{
var user = _context.Users.FirstOrDefault(e => e.Id == id);
// Establish user has right to edit the details
if (user.Id != _userIdentity.GetUserId())
{
HandleErrorInfo error = new HandleErrorInfo(
new Exception("INFO: You do not have permission to edit these details"));
return View("Error", error);
}
return View("Edit", new UserViewModel(user);
}
P.S. Thanks for reading! Part two coming soon.
Read more about OWASP - https://owasp.org/www-project-top-ten/