Follow practical code examples and expert advice to protect your software from potential threats.
1. Input Validation
The input validation prevents any unauthorized user or their script from penetrating deeper into the code to access sensitive information. In other words, the input validation layer prevents invalid data or scripts executed in the code.
public bool IsValidEmail(string email)
{
try
{
var addr = new System.Net.Mail.MailAddress(email);
return addr.Address == email;
}
catch
{
return false;
}
}
2. Use Parameterized Queries
These attacks can be simply blocked by using parametrized SQL queries instead of using string concatenation using the “+” symbol
using (SqlConnection connection = new SqlConnection(connectionString))
{
string query = "SELECT * FROM Users WHERE UserName = @UserName";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@UserName", userName);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Process results
}
3. Avoid Hardcoded Secrets
It's a really bad practice to hardcode any sensitive information like connection strings, API keys or passwords. Try to keep them in configuration or via AWS Secret Manager or Azure Key Vault to prevent unauthorized access.
// Use environment variables
string apiKey = Environment.GetEnvironmentVariable("API_KEY");
// Or use configuration files with appropriate protection
*Recommendation: * It is NOT even recommended to check the configuration files on Github containing connection strings (with passwords).
4. Encrypt Sensitive Data
Encrypt any sensitive information before storing it in files or databases or even logging. For example, use AES encryption for files or database fields.
public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] iv)
{
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
}
return ms.ToArray();
}
}
}
5. Use Strong Authentication and Authorization
It is crucial to have trusted authentication schemes to prevent any unauthorized users from entering the application. Validation of user credentials is the key and the recommendation is to use multi-factor authentication rather than basic which involves username/password validation.
public bool ValidateUserCredentials(string username, string password)
{
// Example: Validate against a hashed password in the database
string storedHash = GetStoredPasswordHash(username); // Fetch stored hash from database
return VerifyPasswordHash(password, storedHash);
}
public bool VerifyPasswordHash(string password, string storedHash)
{
// Implementation of hash verification
}
6. Regularly Update Dependencies
Keep your libraries and frameworks up to date to eliminate vulnerabilities in third-party components available in the Nuget or any other package store.
# Update NuGet packages via command line
dotnet add package PackageName --version x.y.z
7. Implement Proper Error Handling
The recommendation is to display generic messages to the users, and never reveal any sensitive information like exception messages or stack traces.
Log the exception details for tracking.
try
{
// Code that might throw an exception
}
catch (Exception ex)
{
// Log exception details securely
LogException(ex);
// Display a generic message to the user
ShowErrorMessage("An error occurred. Please try again later.");
}
8. Use Secure Transport (HTTPS)
Always use HTTPS to protect data in transit between the client and server.
// Configure your web server to use HTTPS
// Example for ASP.NET Core:
app.UseHttpsRedirection();
9. Limit User Input Length
It happens when there are no input size validations in the application. Sending too long data in the input can cause the application to crash. Hence validating the input size is crucial.
public IActionResult SubmitForm(string input)
{
if (input.Length > 100) // Example length check
{
return BadRequest("Input is too long.");
}
// Process input
}
10. Apply the Principle of Least Privilege
Never provide full database access to the application i.e. admin level privileges. The application should always have the least privileged access to the database to prevent runtime failures.
// Configure database user permissions in SQL Server
-- Create a user with limited permissions
CREATE USER LimitedUser FOR LOGIN LimitedLogin;
GRANT SELECT ON dbo.SomeTable TO LimitedUser;
Conclusion
The above tips will enhance application security, but they still need to be updated with best security practices to maintain applications against future threats.
The crucial segment is to always update application packages to the latest version because the latest vulnerabilities will be constantly fixed by the owner of the package.
Top comments (0)