GIGO

Would you let someone in your house if you thought they should not be there?

You wouldn’t. So why allow any input to your application? Why allow symbols into a variable that is intended to be numeric?

Even when validation is used, a common mistake is to use black lists. For example an application will prevent symbols that are known to cause trouble. The weakness of this countermeasure is that some symbols may be overlooked.

Would you maintain a black list of people that cannot come to your house?

You wouldn’t. So why block quotes when you know the input should be numeric? You should only allow numbers.

In the two code samples below one has a security issue due to improper input validation. Can you tell which?

gigo.png

Both code samples, shell out, to execute OS commands, in this case sending a ping to a server. Shelling out is an insecure practice because it can lead to OS Command Injection, however the bottom code mitigates the issue because it uses an allow list to prevent hazardous characters while the top code uses a block list which is, in this case, insufficient since an attacker could pass in something like updateserver.com `command` or updateserver.com |commandand neither ` nor | have been included in the block list.

As you can see, allow lists are much more effective at preventing application security issues. A simple multi-purpose function that checks if the input is alphanumeric can prevent multiple types of flaws:

public class InputValidation {

/**
Sample java input validation function that validates that the input is alphanumeric or part of a list of allowed exceptions
 */
public static boolean isAlphanumOrExcepted(int maxSize, String val, char ... excepted){
    boolean result = true;
    int count = val.length();
    if(count>maxSize) return false;

    for(int i=0;i<count;i++){
        char c = val.charAt(i);
        boolean isOk = false;
        //if  alphabetic turns true , this works for Unicode chars
        isOk = isOk | Character.isAlphabetic(c);
        //if it's a digit turns true, this works for Unicode chars
        isOk = isOk | Character.isDigit(c);
        //if it's in the list of exceptions turns true
        for(char ex : excepted){
            isOk = isOk | ex==c;
        }

        if(isOk == false){ //if one of the characters didn't meet the requirements return false
            return false;
        }
    }
    return result;
}

And here is how to use this simple function to prevent a wide range of attacks:

`` protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String input = request.getParameter("input");

if(InputValidation.isAlphanumericOrExcepted(EXPECTED_SIZE,input,'.','-','_')){
    //process the input
}
else{
    //return 400 Invalid Input and log attack attempt
}

}

One little function can prevent multiple attack types. The table below demonstrates how the function prevents SQL Injection, OS Injection, Cross-Site Scripting and Path Traversal.

table.png

The function also works for multi-language support. For example the character è will be considered a letter and will be allowed.

In an HTTP request there are many parameters that are simply numeric or alphanumeric. Let’s analyze the URL below which is part of a Twitter API request generated by executing a search for security.

https://api.twitter.com/2/search/adaptive.json?include_profile_interstitial_type=1&include_blocking=1&include_blocked_by=1&include_followed_by=1&include_want_retweets=1&include_mute_edge=1&include_can_dm=1&include_can_media_tag=1&skip_status=1&cards_platform=Web-12&include_cards=1&include_composer_source=true&include_ext_alt_text=true&include_reply_count=1&tweet_mode=extended&include_entities=true&include_user_entities=true&include_ext_media_color=true&send_error_codes=true&q=security&count=20&query_source=typd&pc=1&spelling_corrections=1&ext=mediaStats%2ChighlightedLabel

The only parameter here that may need to be excluded from validation is q . More than 90% of the request parameters can benefit from an alphanumeric allow list. By applying input validation to 90% of the input on the request, we reduce 90% of the attack surface. This is why input validation is the most effective way of reducing vulnerabilities.