Functional testing asks, "Does the software do what it should?" Security testing adds a second question: "Can someone make it do what it should not?" This step in our cybersecurity basics learning path shows how testers answer that question systematically.
It builds on How Software Gets Attacked. If you are new to testing itself, What Is Software Testing? and Your First Test Cases are useful background.
Rule zero: permission
Security testing uses the same techniques attackers use. The difference is authorization: written permission from the owner of the system, with an agreed scope, schedule, and contact for emergencies. Without it, probing a system is illegal in most countries, regardless of intent.
To practice, use systems built for learning: intentionally vulnerable training applications that you run on your own computer, capture-the-flag exercises, and labs offered by training providers. Many organizations also run bug bounty or vulnerability disclosure programs that spell out exactly what outside researchers may test and how to report findings. Read those rules before you start, and follow them precisely.
Start with threats, not tools
Before testing anything, professionals ask what could go wrong and for whom. A lightweight version of threat modeling works for any feature:
- What are we protecting? Personal data, money, accounts, availability.
- Who might attack it? Outsiders, signed-in users reaching beyond their rights, insiders, automated bots.
- Where can they reach it? Forms, web addresses, file uploads, APIs, admin screens, integrations with other systems.
- What would hurt most? Rank the possibilities by likelihood and impact, exactly as risk-based testing does.
The output is a short, prioritized list of things to test. It keeps effort on the risks that matter instead of on whatever a tool happens to report.
Abuse cases: test cases for misbehavior
A normal test case describes a legitimate user doing something expected. An abuse case describes someone trying to misuse the feature. For a password reset feature, abuse cases might include:
| Abuse case | Expected result |
|---|---|
| Request a reset for an email address that has no account | Same message as for a real account, so attackers cannot tell which emails are registered |
| Use the same reset link twice | Second use rejected |
| Use a reset link after 24 hours | Rejected as expired |
| Request 100 resets in a minute | Requests limited; no flood of emails |
| Change the account identifier inside the reset link | Rejected; cannot reset someone else's password |
Each row is a test with a clear expected result, written the same way as any other test case. The techniques from earlier steps still apply: boundary values (exactly 24 hours), equivalence partitions (valid link, expired link, tampered link).
Testing access control
Broken access control is among the most common serious findings, and it is very testable. A simple, powerful method uses two or more test accounts with different permissions:
- Sign in as user A and note the addresses and requests used to view A's data.
- Sign in as user B and try those same addresses and requests directly.
- Sign in as an ordinary user and try the addresses of admin features.
- Sign out entirely and try them again.
Every attempt should be refused by the server. Hiding a button in the interface is not access control; the check has to happen on the server for every request.
Automated tools and where they fit
Several kinds of tools help, each with strengths and limits:
- Static analysis (SAST) reads source code looking for risky patterns, such as input passed straight to a database. It finds problems early but reports false alarms that need human review.
- Dynamic scanning (DAST) probes a running application from the outside, the way an attacker would, looking for known weaknesses and misconfigurations.
- Dependency scanning checks the third-party components an application uses against public lists of known vulnerabilities.
- Secret scanning looks for passwords and keys accidentally committed to code.
Tools are good at breadth and repetition. They are weak at business logic: no scanner knows that a customer should not be able to apply the same discount code fifty times. That is where human testers, guided by a threat model, earn their keep.
Penetration testing
A penetration test is an authorized, time-boxed attempt by skilled testers to break into a system the way a real attacker would, chaining small weaknesses into a meaningful compromise. It is valuable for high-risk systems and is often required by regulators and customers. It works best on top of everyday security testing, not instead of it; a penetration test that spends its time on issues a scanner would have found is money poorly spent.
Reporting security findings
Security bugs are reported like any bug, with steps to reproduce, expected and actual results, and evidence, plus two extras:
- Impact in business terms. "Any signed-in user can download any other customer's invoices" lands harder than a technical category name.
- Careful handling. Security findings go to a restricted audience until fixed. Do not post them in public channels or tickets visible to everyone.
Try it yourself
Pick a feature you know well, such as sign-up, password reset, or a shopping cart. Write a three-line threat model (what is protected, who might attack, where they can reach it), then write five abuse cases with expected results. If you want to run them, use an intentionally vulnerable training application on your own machine, never a live site.
The next steps in this path move from individual tests to the organization: reducing software security risk across a whole development process, and managing the risk that comes from vendors and outside components.