Home >Backend Development >PHP Tutorial >Solution to the problem of CI automatically filtering out the last two digits of percent sign _PHP tutorial
In the website made by CodeIgniter, I want to enter a piece of code:
$var = sprintf("%04d", 2);
But I found that after entering the library, the code changed to
$var = sprintf("d", 2);
I tested it in both online environment and local environment, and it was finally confirmed that it was a problem with the CodeIgniter system. Let’s talk about the problem-solving process and thinking methods:
1. Is it permitted_uri_chars of config.php?
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
I found several similar questions on stackoverflow, and some answers said that just change permitted_uri_chars in config.php.
Ahem... after looking at your sample string again. Here is why you get "
The URI you submitted has disallowed characters
".Short explanation: Add the ampersand & to the allowed characters list
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_+&-';
I tried it, but it didn’t work, so I looked for the code that applied $config['permitted_uri_chars'].
2. Is it a problem with the _clean_input_keys() function of core/Input.php?
function _clean_input_keys($str) { $config = &get_config('config'); if ( ! preg_match("/^[".$config['permitted_uri_chars']."]+$/i", rawurlencode($str))) { exit('Disallowed Key Characters.'); } // Clean UTF-8 if supported if (UTF8_ENABLED === TRUE) { $str = $this->uni->clean_string($str); } return $str; }
This function uses $config['permitted_uri_chars'] to directly filter the post data. The main reason is the culprit. I separated it and found after testing that post $var = sprintf("%04d", 2);, the result is still $var = sprintf("%04d", 2);, %04 has not been filtered, see You have to look for it carefully.
3. Is it a defense mechanism for xss?
Someone on stackoverflow said that he solved this problem perfectly and it was caused by xss clean.
:) God damn URLDECODE, I have looked at the code in URI.php but the xss clean is doing the job so I missed it. Thank you now everything is perfect. – RaduM
So I found the xss_clean() function under core/security.php. Comment out all the function body code and find that the input will still filter out %04, which is obviously not a problem with xss.
4. The problem lies in the _clean_input_data() function
Go back to Input.php and find that _clean_input_data is related to _clean_input_keys.
$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
So I commented out the function body of _clean_input_data(), and the input was not filtered. Continuing to narrow down the scope, I found that this code was causing trouble:
// Remove control characters // 就是这个会把%0x过滤掉 $str = remove_invisible_characters($str);
5. The culprit found the remove_invisible_characters() function
So what is the remove_invisible_characters() function?
This function is in core/Common.php, I pulled it out:
function remove_invisible_characters($str, $url_encoded = TRUE) { $non_displayables = array(); // every control character except newline (dec 10) // carriage return (dec 13), and horizontal tab (dec 09) if ($url_encoded) { $non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15 $non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31 } $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127 do { $str = preg_replace($non_displayables, '', $str, -1, $count); } while ($count); return $str; }
Look at these lines of code:
if ($url_encoded) { $non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15 $non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31 }
Let’s be clear, it will filter out the three characters starting with %0 and %1. Just comment this out and the problem will be solved.
Record the entire thinking process of solving this problem.