Web, mobile, and desktop applications are crucial in today’s tech world. Most software developers overlook the concept of ‘security’ while developing these applications. In this article, I will address some challenges I have encountered both in software development and penetration testing.
Regardless of size, every software begins with an idea before coming into existence. Each software has a idea it serves in the background, and there are features it must have to fulfill that purpose. For instance, in a banking system, the purpose is to organize money transfers, provide information about budget, etc. The situation is no different for small-scale applications. For example, the purpose of a simple note-taking app is to create a product where users can store and organize their notes. This is precisely where software developers focus their efforts. Before starting coding, a software developer gets an idea about the purpose of the product and writes code that aligns with that purpose. Although this topic may seem unrelated to security, I believe it is the first aspect a pentester should consider when attempting to pentest an application. We can liken this topic to encryption algorithms. In encryption algorithms, the technique of the algorithm is not kept secret; the main goal is to ensure security even when the technique is known. The situation in software is somewhat similar. The primary goal is not the security of what the software does but how securely the software performs its intended function.
Most software starts to be developed by defining data before anything else. The data the application will hold, process, and present to the user is identified, and a suitable database architecture is employed. At this stage, software developers should ask themselves the following question: Which data will we show to the user, and which data will we not show? For example, data indicating the user’s role, known as ‘role,’ should never be displayed to the user in any form (except for certain scenarios). Neither in cookies nor in any part of the application (including HTTP requests and responses). This role value is a crucial piece of information for the smooth operation of the software in the background and should never be shown to the user in any way.
In today’s software world, developers should beware from sending their own database queries directly to databases. nstead of writing separate database queries for each task, Data Transfer Objects (DTOs) can be used. Using DTOs helps prevent injection vulnerabilities like SQL injection and clearly defines which data will be retrieved for each operation. However, using a single User DTO for the User update process can endanger the software in certain situations. When updating a user, not every field associated with the user is typically updated. The CreatedDate field is an example of a value that should not be accessible by the User update function. In a system using email as a unique identifier, where email is supposed to be immutable, the User update DTO should not include the email value. While you might assume that the email parameter won’t come from the user and therefore the email value in the DTO won’t change, security researchers like us can add undesired values to HTTP requests. Therefore, when making updates in the database, it should be the software, not the user, that is restricted.
Another important process during the software development is authentication/authorization. After setting up the database in the software architecture, this becomes the second most essential task. If the users and their permissions in the system are known, establishing the architecture in alignment with the data from the beginning will be both more efficient and secure.
When setting up the authorization mechanism, a critical consideration is ensuring session control for each endpoint/function. For instance, if session management is only checked for the /dashboard endpoint and not for the /product endpoint, a user can view products by simply entering /product in the URL, even if they haven’t logged into the system.
Authentication is yet another important aspect. Like authorization, authentication should be considered during the design of the system. The values that users can view and access should be controlled not only on the front end but also on the back end. The software should have its own hierarchy.
The concepts of Authentication/Authorization are much more in-depth topics that require thorough discussion. This article only contains headlines and general explanations.
In software security, the most crucial aspect is how much trust is placed in the end user. Every parameter, that is, every parameter in HTTP request, should be verified. Validating values in the HTTP body or query string may not be sufficient in some cases. Headers such as Host, Cookie, X-Forwarded-For, if used in the software, must be checked.
All parameters sent by the user must pass the necessary security measures before being processed. For these security measures, cybersecurity researchers generally recommend the use of a whitelist rule.
The most important question that arises in parameter validation is: Should we determine the characters we allow or the characters we disallow? The answer to this question may vary depending on the situation, but the general approach should be a whitelist.
A whitelist is an approach where the values that should be present in the incoming parameters are defined. For example, if we want to validate the phone number field, we can use a regex that only accepts numbers and use a whitelist.
On the other hand, a blacklist is an approach where the values that should not be present in the incoming parameters are defined. For example, in the case of a phone number, this approach would restrict alphabetical characters and special characters.
Is it healthier to have an approach that only checks for numbers in the incoming data, or to include all characters except numbers in the rule and check those values?
Another security measure that needs to be taken, aside from the scenarios mentioned above, is the modification of characters. For instance, characters like ‘<’, and ‘>’ can be received from the user, revealing to a potential XSS vulnerability. To avoid this, these characters should be HTML-encoded.
To prevent SQL injection vulnerabilities, it is necessary to validate characters that could exploit the vulnerability, such as the quoute character(‘) .
Software developers may accept certain special conditions during the software development process. One of these is enabling the application’s debug mode. A developer intentionally allows the debug mode open while developing to analyze the cause of errors. Similarly, they may leave the default SQL string used on the server open to the public. While this can be an advantage during software development, it can create significant issues when the software is released to the public. Therefore, certain features used during software development should be disabled when the software is made available to the public.