whitelabel error page SpEL RCE vulnerability reproduction

Vulnerability cause

Under normal circumstances, you can obtain the article content by accessing /article and entering the numeric ID. However, if a spel expression is passed in, it will lead to an error page and the spel expression content will be parsed and reflected in the error page.

debug process

Also starting from the DispatcherServlet.doDispatch() function, we quickly located the key class: the PropertyPlaceholderHelper class.
An error is reported in DispatcherServlet due to the following judgment

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    
...
		if (asyncManager.isConcurrentHandlingStarted()) {
    
    
		                    return;
		                }
...
}

The error content is NumberFormatException, which is an error in converting the input value into a number.

Let’s look at the PropertyPlaceholderHelper.parseStringValue() method first

rotected String parseStringValue(String strVal, PropertyPlaceholderHelper.PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {
    
    
        StringBuilder result = new StringBuilder(strVal);
        int startIndex = strVal.indexOf(this.placeholderPrefix);

        while(startIndex != -1) {
    
    
            int endIndex = this.findPlaceholderEndIndex(result, startIndex);
            if (endIndex != -1) {
    
    
                String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
                String originalPlaceholder = placeholder;
                if (!visitedPlaceholders.add(placeholder)) {
    
    
                    throw new IllegalArgumentException("Circular placeholder reference '" + placeholder + "' in property definitions");
                }

                placeholder = this.parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
                //这里传入
                String propVal = placeholderResolver.resolvePlaceholder(placeholder);
                if (propVal == null && this.valueSeparator != null) {
    
    
                    int separatorIndex = placeholder.indexOf(this.valueSeparator);
                    if (separatorIndex != -1) {
    
    
                        String actualPlaceholder = placeholder.substring(0, separatorIndex);
                        String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
                        propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
                        if (propVal == null) {
    
    
                            propVal = defaultValue;
                        }
                    }
                }

                ......
        }

        return result.toString();
    }

After that, the view will be returned, and the view contains ${timestamp}, ${error}, ${status}, ${message}. The view will judge whether the value starts with "${" through loop traversal.
Insert image description here

As long as it starts with "${", it will enter the spel expression execution phase. But when we set the value of the message to the payload, which also starts with '${', the payload will also be executed. It does not verify the value of the controllable parameter message.

Then use the ErrorMvcAutoConfiguration.resolvePlaceholder() method to parse the spel expression and obtain the value.
Insert image description here
This step is to get the value of status. When the payload is reached, it will be parsed into the Runtime class and the exec method will be executed. This step is reflection to obtain the Runtime instance.
Insert image description here

Summarize

Since the incoming value will be judged whether it is a number, if it is not a number, an error will be reported and the error page will be entered. The error page contains some spel expressions, so the spel expressions in the error page will be searched in a loop and Parse it out and finally render it to the page. But the reason for the problem is that if the value of ${messgae} is also a spel expression, then it will continue to parse the expression in a loop, thereby achieving command injection, that is, the user-controllable parameters are not verified.

Repair suggestions

The reason is that the ID is not filtered in the spel direction. Therefore, my summary suggestions are as follows:

  1. Filter IDs, set black and white lists, and filter values ​​such as ${ etc.
  2. Upgrade framework version
  3. Patch
  4. Custom error page

Guess you like

Origin blog.csdn.net/qq_40519543/article/details/121403143