The Role of QA in Product Security Testing
Hello, my name is Dmitry Krylatkov, and I work as a QA engineer at Doubletapp. I have always been interested in the topic of security testing, participating in bug bounty programs and raising awareness of existing vulnerabilities among testing and development teams. In this article, I will discuss how QA can save company resources and ensure the verification of essential vulnerabilities, what to pay attention to, and why it is beneficial for both specialists and businesses.
The testing team primarily concentrates on the product’s functional requirements — checking if the application works according to expectations, conducting regressions, and dealing with requirements and layouts. Generally, it ensures the product’s quality at all stages. However, QA often does not address the security of the product. For this, specifically trained professionals are required to identify vulnerabilities, and this type of testing is usually neglected. Why could this be a problem?
From my experience, I believe that the cost of a missed bug is much lower than that of a vulnerability. There are many tools that can localize and hotfix bugs — regressions, monitoring, or simply user support if something stops working.
However, an unnoticed vulnerability can be exploited for a long time without our knowledge, threatening the product’s reputation and incurring costs for the business. Neither users nor QA might be aware of it. Consequently, the goal of QA to ensure the product’s quality at all stages is not fully achieved, and the responsibility shifts to the security department, which may not exist in the company. Moreover, security experts, being human, can overlook something. Thus, the cost of a missed vulnerability significantly increases for the business.
Our task as QA is to prevent such costs and enhance product quality through additional security checks. If we can identify security issues during functional testing, it will reduce the hours of security experts and prevent expenses on a bug bounty program if it exists in the company.
If there is no security department, QA skills in security testing will make you a particularly valuable specialist.
How to define a vulnerability and how is it different from a bug?
I like the definitions that are almost identical. A bug is the program’s failure to meet expected behavior, while a vulnerability is the execution of unexpected behavior. With some additional actions, a malicious actor can perform a scenario that was not part of the product requirements, extract information, act on behalf of the user, compromise data integrity, bypass protection mechanisms, and more — anything beyond expected behavior with malicious intent.
Another difference is that bugs are always unique. Finding a bug in one application does not guarantee that similar reproduction steps will cause a similar bug in another application. This uniqueness arises from unique product requirements and implementations. Vulnerabilities are more classified (see CWE), and by knowing the search pattern for a specific vulnerability, we can search for it in any web application without relying on product requirements. A good example is XSS, which QA can find within the framework of functional testing in application areas with user input.
Vulnerabilities: starting with the basics
I have prepared a list of vulnerabilities that are relatively easy to master but are widespread in web applications. By mastering the methodology of their search, a tester will be able to cover the main cases related to the security of client-side applications. Also, there is no need to worry about breaking anything since these vulnerabilities target users. As long as they are test users!
List of vulnerabilities:
- Clickjacking
- XSS
- CSRF
- IDOR
- Open Redirect
As a technical example from this list, I chose the IDOR vulnerability. IDOR stands for Insecure Direct Object Reference, meaning an insecure direct reference to an object. The IDOR vulnerability is one of the most common authentication problems that can lead to critical security issues. IDORs arise when an application provides access to objects based on user-entered data. I am sure that checking for this vulnerability falls within the competencies of QA, so let’s take a closer look at how to search for it.
The first two letters of the name indicate what we pay attention to when testing for IDORs: ID — any object identifiers in HTTP requests.
The simplest example is when a user sees a link in the browser like https://example.com/profile/passport/123, where the last three digits are the ID of the user’s passport. If a user wants to change the passport ID to, say, 122, and there is no validation for this action, they will open another user’s passport page and get information that should not be accessible within their session.
What can we gain from manipulating IDs? Primarily, unauthorized access to sensitive information. Using the ID, we can retrieve various objects belonging to other users. This does not necessarily have to be personal information and passport data. Any information that should not be available within a specific session and role in the application will be considered a valid find if we can find it by manipulating the ID of someone else’s object.
During testing, rely on the logic of authorization rather than subjective perceptions of the criticality of the information you find — such findings might be crucial for the business.
Secondly, gaining unauthorized access to an object allows us to modify other people’s data. For example, consider a request DELETE /api/users/550123, which potentially can delete all users in the application.
Moreover, there may be examples of privilege escalation if we can attack a role higher in the hierarchy, gaining access to requests and objects, such as a user-admin. By revealing information, we can further enhance the impact of the IDOR vulnerability. For instance, it might expose an object containing logins and passwords. In my practice, I found an IDOR that led to the compromise of several accounts.
Thirdly, let’s consider direct access to files. Files are also susceptible to IDORs, so if you encounter a URL like https://example.com/passports/123.pdf, it is crucial to ensure that we cannot view and fetch “passports” with other IDs — unless permitted by the current session’s rights.
Speaking of the search methodology, we can highlight several approaches. Firstly, this involves modifying the IDs in the request. Remember that an identifier can be assigned to any object, so always check the entire request, including its body, not just the query parameters. The request may contain multiple IDs in different combinations — try changing any of them and see how the backend reacts. Certainly, before doing this, understand the logic of the application’s authorization — what these objects return and in what role.
Different manipulations with parameters can be identified. One attack method is HTTP Parameter Pollution, which involves splitting the same parameter into multiple entities. In the example below, we added another parameter user_id via an ampersand and wrote the ID of another user to it.
GET /api_v1/messages?user_id=YOUR_USER_ID&user_id=ANOTHER_USER_ID
Similarly, we can try swapping query parameters:
GET /api_v1/messages?user_id=ANOTHER_USER_ID&user_id=YOUR_USER_ID
IDORs can occur in arrays — when an array of identifiers is accepted, the objects of which are available to certain users.
{“users”: [“user_1”: “123”, “user_2”: “124”]}
In this case, we can “expand” the array by substituting the ID of a user who should not be within the logic of authorization, or use familiar methods to change IDs in existing parameters.
{“users”: [“user_1”: “123”, “user_2”: “124”, “user_5”: ”999”]}
Rarely but effectively, not only IDs can trigger. In the following request, object identification occurs via a username that, however, does not look familiar. For example, the username is encoded in base64, and after decoding, we can see the username super_admin.
GET/user/c3VwZXJfYWRtaW4=/data → GET /user/super_admin/data
Usernames are often public information, suggesting that it’s worth trying to encode them in the required encoding for the request and attempt to insert them into the query. Always pay attention to how access to various objects in the application is implemented; it might not always be IDs.
A couple of additional points not to forget: If you test a request for an IDOR vulnerability and receive a 403 or if illegitimate actions are correctly validated by other errors, try adding a slash GET private/users/89934 → GET private/users/89934/. Perhaps this slash will allow you to escape the regex validation and return someone else’s object. Also, try using URL-encoded characters, such as %20: GET private/users/89934%20.
We can check access to requests and objects by changing the request’s authorization. If we have multiple roles, we can make a request for an admin (or any role above), switch the session to a lower role, and make a request. If we get the same result as when requesting from an admin and the admin’s objects become available, it is equivalent to an IDOR since it is part of insufficient object authorization.
A few final tips on this vulnerability:
- Don’t report unguessable IDs if you couldn’t prove how to find them through other API requests. Bruteforcing UUIDs or GUIDs is practically useless.
- Understand what is expected behavior in the application and what is not. Some reports on HackerOne were closed as Not Applicable because the researcher treated certain queries with different IDs as a security issue, even though it was done by design. For example, GET /users/150150 returns information about the user, although this information was equivalent to what he could have clicked on the client side. What you retrieve using an ID should be different from what you see on the client side and what should be protected in reality. Another example: the ability to grant permissions for viewing specific objects might be available to the user on the client side. Then, it is the expected result, not a security issue.
- Understand the roles within the application and what each role should have access to. You might discover IDOR for a role that should have access to certain information, even if the initial request was made from another role.
I’ve covered the basic methodologies and search patterns. For a more in-depth understanding of this and other vulnerabilities, I recommend the resource PortSwigger. It succinctly describes vulnerabilities, including those I suggested exploring initially. Read the descriptions there, try solving labs to reinforce your knowledge (don’t worry if it doesn’t work out — solutions are always available online). The information from this source should be sufficient for you to grasp what various vulnerabilities represent and how we can find them within the scope of functional testing.
One of the best sources is reading public reports on discovered vulnerabilities, for example, on HackerOne. It greatly helps to understand the logic and payloads used.
Software for finding vulnerabilities
While you can use familiar tools like Fiddler or Postman, it will be less convenient than a tool specifically designed for security professionals. I’m talking about Burp Suite — a debugging proxy less popular among QA but suitable for functional API testing. With Burp Suite, you can intercept traffic, use a convenient interface to analyze and modify HTTP requests, intercept requests and responses, brute force, decode, run built-in scanners, and many other useful features for testing.
Burp also supports various plugins from the community that can facilitate vulnerability searches, such as Authmatrix for testing IDORs.
The Community Edition is free and covers the essential functionality, so I suggest trying it even for regular functional testing as a proxy.
Where knowledge of vulnerability search is applicable
The application field is quite broad. You can:
- Participate in bug bounty programs for additional income.
- Engage in various CTFs and other competitions.
- As a security specialist, you can have several career paths — develop in pentesting, mobile application testing, DevSecOps, and more.
And most importantly, answering the question, “What is the role of QA in product security testing?” you can look at the product not only from the functionality and usability side but also with a critical assessment — how secure your product is from various vulnerabilities.
Security testing can certainly be part of QA competencies. With the acquisition of new skills, you can perform additional checks on your products, cover previously unknown cases, and try to introduce new approaches and practices, which will positively impact product quality. As QA, you can influence the product from the perspective of the best security practices even during the creation/testing of requirements. And, of course, being a specialist of a broader format, you can share knowledge not only with other testers but also with the development team.
So let’s make our products not only of high quality but also a bit more secure!
Read our other stories:
- Overview of Monitoring System with Prometheus and Grafana
- “External” navigation in a multi-module project in Kotlin
- Parsing responses to BLE commands in Swift using the example of GoPro
- What Is Happening With The Mobile App Market
- Yandex Travel
- Case Ural Music Night
- Player’s Health Protect
- DJU Drone Club
- Case Alibra School
- Case Praktika
- Case Watchmen
- Case Adventure Aide
- Neural Network Optimization: Ocean in a Drop
- Case Elixir Gallery
- Forgive us, John Connor, or How We Taught a Neural Network to Accurately Recognize Gunshots
- Case Bus Factor
- CI/CD for iOS-projects: device or cloud? What’s better, Doubletapp’s take
- How to set up Gitlab CI/CD with Fastlane for iOS-project on a Mac mini
- The story about the contest from telegram
- What should be done before starting the site? Checklist from Doubletapp
- How to Generate PDF Documents in Python
- How to manage Gradle dependencies in an Android project properly
- The History of the Doubletapp Company