Forced Validation Paradigm
Forced Validation Paradigm
(A) Forced Validation using Validation Service Interface
In this article, I will try to explain to you how to ensure validation is always forced by the caller of any given functionality.
Let’s consider a simple example.
Here, in order to reduce the redundancy of calling the same piece of code, the developer decides to write a function where code is written once but called by multiple references.
Assume an interface that has a method that receives a parameter and performs some critical action.
We decided to design our application with a utility class that would take care of the aspect of executing this critical function.
Example:
| //utility class class Processor{ public static void process(String str) { $AttackVectorFunction$(str); // Potential Vulnerability } } |
In the above code, $AttackVectorFunction$() is a placeholder for that critical function.
$AttackVectorFunction$() has the potential for different types of weakness.
The Attack Vector is where Veracode Static Analysis will report the flaw.
A few CWE scenarios for $AttackVectorFunction$().
Please note that this article also applies to other CWEs and Veracode Static Analysis may also report these flaws on other methods.
| CWEs | Attack Vector in Java | Attack Vector in .Net |
| CWE 501 Trust Boundary Violation | HttpSession.setAttribute() | Session.Add() |
| CWE 89 SQL Injection | Statement.executeQuery() | SqlCommand.ExecuteNonQuery() |
| CWE 566 Authorization Bypass Through User-Controlled SQL Primary Key | org.hibernate.Session.get() | SqlCommand.ExecuteNonQuery() |
| CWE 601 URL Redirection to Untrusted Site | HttpServletResponse.sendRedirect(url); | Response.Redirect() |
| CWE 470 Unsafe Reflection | Class.forName() | Assembly.LoadFile(), Assembly.CreateInstance() |
Some business logic implementations use the utility to make a call to $AttackVectorFunction$() indirectly.
class BusinessA{
public void functionA1(String str) {
// do something
Processor.process(str);
}
public void functionA2(String str) {
//do something
Processor.process(str);
}
}
class BusinessB{
public void functionB1(String str) {
// do something
Processor.process(str);
}
}
public class ProcessorDemo{
public static void main (String args[]) {
BusinessA a = new BusinessA();
a.functionA1(args[0]);
a.functionA2(args[1]);
BusinessB b = new BusinessB();
b.functionB1(args[2]);
}
}
As it receives the ‘str’ string and calls the "$AttackVectorFunction$()" function without precautionary measures.Untrusted data used as ‘str’ could be dangerous.
In order to mitigate the flaw, the general recommendation would be adding validation logic as below:
| public static void process(String str) { if(validate(str)){ $AttackVectorFunction$(str); } } |
Here, validate() is function that would take care of required validation before it makes a call to $AttackVectorFunction$()
--> Hence, the flaw is successfully mitigated.
However, it is getting invoked from multiple business logic modules, there is the possibility that validation may NOT be always the same.
For e.g. functionA1 needs different validation compared to that of functionB2().
Now in order to mitigate the flaw, we will have to add validation within those function calls and remove validate() logic from process() itself.
class Processor{
public static void process(String str) {
$AttackVectorFunction$(str);
}
}
class BusinessA {
public void functionA1(String str) {
// do something
if(validateA1(str)){
Processor.process(str);
}
}
public void functionA2(String str) {
//do something
if(validateA2(str)){
Processor.process(str);
}
}
}
class BusinessB{
public void functionB1(String str) {
// do something
if(validateB1(str)){
Processor.process(str);
}
}
}
A good example is that $AttackVectorFunction$() can accept below valid inputs :
- An email address (for e.g. “abc@example.com” )
- An alphanumeric Request ID (for e.g. “AJS90056GH3” )
- A hyphen separated Serial Id(For e.g. “12001-TX23-7281”)
Business logic would be :
But we may introduce a new business code OR modify the existing code which does not do required Pre-validation.
For example, in the below example, we will invoke the Processor.process() by passing the untrusted OrderId coming from untrusted sources.
In such case, via process() --> $AttackVectorFunction$() would be invoked without the OrderId validation.
--> Implying that the vulnerability finding is valid.
It is critical as this 1 usage or reference to the process() without validation can bring several types of weaknesses in the software.
How to Fix?
--> using Validation Service Interface
Here, we like to introduce ValidationService as an interface that has a validate() abstract method.
The abstract method validate() will be enforced by its implementors.
Now I would modify the Processor method like this :-
As we see ‘validator’ passed as an argument will ensure ‘validation’ of the given variable ‘str’ before using the variable for $AttackVectorFunction$(). This is how we could implement forceful validation on it.
This means the Business class should provide the ValidationService instance reference for every call now.
Example:
For instance;
For example in class BusinessD:
Click Here to see more details on these validation strategies on Page 2 of this article.
Page 2, we will learn how to :
- Mitigate several CWEs ( CWE 501, CWE 601, CWE 566, etc. )
- Define default validators.
- Define AllowList-based validators.
class BusinessC {
public void doProcessEmail(String email) {
// do something
if(validateEmail(email)){
Processor.process(email);
}
}
public void doProcessRequest(String reqId) {
// do something
if(validateRequest(reqId)){
Processor.process(reqId);
}
}
public void doProcessSerialId(String serialId) {
// do something
if(validateSerialId(serialId)){
Processor.process(serialId);
}
}
}
class Processor{
public static void process(String str) {
$AttackVectorFunction$(str);
}
}
The problem with this implementation $AttackVectorFunction$() is invoked assuming that a Pre-validation is done before calling the Processor.process() by the caller program.But we may introduce a new business code OR modify the existing code which does not do required Pre-validation.
For example, in the below example, we will invoke the Processor.process() by passing the untrusted OrderId coming from untrusted sources.
Class BusinessD {
public void doOrder(String orderId) {
Processor.process(orderId);
}
}
Where I forget to add validation of Order id, OR I may find it convenient to skip this validation.In such case, via process() --> $AttackVectorFunction$() would be invoked without the OrderId validation.
--> Implying that the vulnerability finding is valid.
It is critical as this 1 usage or reference to the process() without validation can bring several types of weaknesses in the software.
How to Fix?
--> using Validation Service Interface
Here, we like to introduce ValidationService as an interface that has a validate() abstract method.
| public interface ValidationService { public boolean validate(Object obj); } |
The abstract method validate() will be enforced by its implementors.
Now I would modify the Processor method like this :-
class Processor{
public static void process(Object obj, ValidationService validator) {
if(validator.validate(obj)){
$AttackVectorFunction$(obj);
}
}
}
As we see ‘validator’ passed as an argument will ensure ‘validation’ of the given variable ‘str’ before using the variable for $AttackVectorFunction$(). This is how we could implement forceful validation on it.
This means the Business class should provide the ValidationService instance reference for every call now.
Example:
class BusinessC {
public void doProcessEmail(String email) {
Processor.process(email , new EmailValidator());
}
public void doProcessRequest(String reqId) {
Processor.process(reqId , new RequestValidator());
}
}
In the above example, ‘EmailValidator’ and ‘RequestValidator’ are both implementations of ValidationService.For instance;
public class EmailValidator implements ValidationService {
@Override
public boolean validate(Object obj) {
if( obj instanceof String )
{
// check email string validity.
}
}
}
public class RequestValidator implements ValidationService {
@Override
public boolean validate(Object obj) {
if( obj instanceof String )
{
// check requested string validity.
}
}
}
With this implementation we will be forced to provide ValidationService implementations in every call:For example in class BusinessD:
Class BusinessD {
public void doProcessOrder(String orderId) {
Processor.process(orderId , new OrderValidator());
}
}
where OrderValidator must be defined:
public class OrderValidator implements ValidationService {
@Override
public boolean validate(Object obj) {
if( obj instanceof String )
{
// check orderid string validity.
}
}
}
Another alternative if we can instead of String , use POJO objects as arguments to doProcess methods()
class BusinessC {
public void doProcessEmail(Email useremail) {
Processor.process(useremail);
}
public void doProcessRequest(Request req) {
Processor.process(req);
}
}
Class BusinessD {
public void doProcessOrder(Order order) {
Processor.process(order);
}
}
class Processor{
public static void process(Object obj) {
if(obj instanceof Email && EmailValidator.getInstance().validate(obj)){
$AttackVectorFunction$(obj);
}else if(obj instanceof Process && ProcessValidator.getInstance().validate(obj)){
$AttackVectorFunction$(obj);
}else if(obj instanceof Order && OrderValidator.getInstance().validate(obj)){
$AttackVectorFunction$(obj);
}else{
// other validations followed by $AttackVectorFunction$(obj) calls.
}
}
}
With the above approach, we keep the signature of Processor.process() to default.Click Here to see more details on these validation strategies on Page 2 of this article.
Page 2, we will learn how to :
- Mitigate several CWEs ( CWE 501, CWE 601, CWE 566, etc. )
- Define default validators.
- Define AllowList-based validators.
Related Articles
Web.War Module 533Number of Views Module selection 5.69KNumber of Views What is "Expert Member" and How to Be Listed 2.46KNumber of Views Grace Period in New Policy 971Number of Views Initial Dynamic Analysis (DAST) Customer Onboarding 79Number of Views
This topic isn't available in this community.
Related Topics
Ask the Community
Get answers, share a use case, discuss your favorite features, or get input from the Community.
.png)