Security of C# Applications: Top 10 Vulnerabilities for Beginners
\n\nDeveloping secure applications in C# is not just a trend, but a necessity. Every day, thousands of vulnerabilities are discovered worldwide, and your application could be the next target. In this article, we will break down the 10 most common vulnerabilities in C# (.NET) applications that beginner developers encounter. You will learn how to detect them and, most importantly, how to protect your code.
\n\n1. SQL Injection
\n\nThe oldest and still dangerous vulnerability. It occurs when user input is directly inserted into an SQL query.
\n\nVulnerable code:
\nstring userName = Request["username"];\nstring query = "SELECT * FROM Users WHERE Name = '" + userName + "'";\nSqlCommand cmd = new SqlCommand(query, connection);\n\nProtection: Use parameterized queries or Entity Framework.
\nstring userName = Request["username"];\nstring query = "SELECT * FROM Users WHERE Name = @name";\nSqlCommand cmd = new SqlCommand(query, connection);\ncmd.Parameters.AddWithValue("@name", userName);\n\n2. Cross-Site Scripting (XSS)
\n\nXSS attacks allow an attacker to inject a malicious script into a page that is displayed to other users.
\n\nVulnerable code:
\nstring comment = Request["comment"];\nResponse.Write("<div>" + comment + "</div>");\n\nProtection: Always encode output. Use HttpUtility.HtmlEncode():
string comment = Request["comment"];\nResponse.Write("<div>" + HttpUtility.HtmlEncode(comment) + "</div>");\n\n3. Missing Authentication and Authorization
\n\nMany beginners forget to check access rights to resources. For example, a user could access another user's profile simply by changing the ID in the URL.
\n\nVulnerable code:
\npublic IActionResult Profile(int userId)\n{\n var user = _context.Users.Find(userId);\n return View(user);\n}\n\nProtection: Always verify that the current user has permission to the requested resource:
\npublic IActionResult Profile(int userId)\n{\n var currentUserId = User.FindFirst(ClaimTypes.NameIdentifier).Value;\n if (userId != currentUserId) return Forbid();\n var user = _context.Users.Find(userId);\n return View(user);\n}\n\n4. Leaking Sensitive Data Through Exceptions
\n\nDevelopers often output full error information, including the call stack and connection strings.
\n\nVulnerable code:
\ntry\n{\n // code\n}\ncatch (Exception ex)\n{\n Response.Write(ex.ToString()); // DANGEROUS!\n}\n\nProtection: In production, use generic error messages and log details to a secure location:
\ntry\n{\n // code\n}\ncatch (Exception ex)\n{\n _logger.LogError(ex, "Error processing request");\n return StatusCode(500, "An internal server error occurred");\n}\n\n5. Insecure Password Storage
\n\nStoring passwords in plain text or using weak hashes (MD5, SHA1) is a serious mistake.
\n\nVulnerable code:
\nstring passwordHash = MD5.Hash(password); // NOT ALLOWED!\n\nProtection: Use modern hashing algorithms with salt, such as BCrypt or ASP.NET Core Identity:
var passwordHasher = new PasswordHasher<IdentityUser>();\nstring passwordHash = passwordHasher.HashPassword(user, password);\n\n6. Insufficient Protection Against CSRF (Cross-Site Request Forgery)
\n\nAn attack where the attacker forces the victim's browser to perform an unwanted action on another site where