Vulnerabilities in how to format strings in sprintf
This article shows you how to format string loopholes in sprintf, the content is concise and easy to understand, it will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.
First, let's look at the sprintf () function.
The sprintf () function writes the formatted string to the variable.
The sprintf (format,arg1,arg2,arg++) arg1, arg2, and + + parameters are inserted at the percent sign (%) symbol in the main string. This function is executed step by step. At the first% symbol, insert arg1, at the second% symbol, insert arg2, and so on. Note: if the% symbol is more than the arg parameter, you must use a placeholder. Placeholders are located after the% symbol and consist of numbers and "\ $".
Review sprintf with a few examples
Output: with two decimal places: 123.00 without decimal: 123
Example 2:
Output:% b = 111010110111100110100010101% c = 2 / Note var_dump ('2') is string% s = 123456789% x = 75bcd15% X = 75BCD15
0x02 sprintf injection principle
Underlying code implementation
Let's take a look at the underlying implementation of sprintf ()
Switch (format [inpos]) {case's questions: {zend_string * t; zend_string * str = zval_get_tmp_string (tmp, & t); php_sprintf_appendstring (& result, & outpos,ZSTR_VAL (str), width, precision, padding,alignment,ZSTR_LEN (str), 0, expprec, 0); zend_tmp_string_release (t); break } case'dcards: php_sprintf_appendint (& result, & outpos, zval_get_long (tmp), width, padding, alignment, always_sign); break; case'utilisation: php_sprintf_appenduint (& result, & outpos, zval_get_long (tmp), width, padding, alignment); break Case'gathers: case'Gags: case'eyed: case'eyed: case'fouls: case'Falls: php_sprintf_appenddouble (& result, & outpos, zval_get_double (tmp), width, padding, alignment, precision, adjusting, format [inpos], always_sign); break; case'cages: php_sprintf_appendchar (& result, & outpos, (char) zval_get_long (tmp)); break Case'ographies: php_sprintf_append2n (& result, & outpos, zval_get_long (tmp), width, padding, alignment, 3, hexchars, expprec); break; case'xtrees: php_sprintf_append2n (& result, & outpos, zval_get_long (tmp), width, padding, alignment, 4, hexchars, expprec); break; case'Xtrees: php_sprintf_append2n (& result, & outpos, zval_get_long (tmp), width, padding, alignment, 4, HEXCHARS, expprec); break Case'baked: php_sprintf_append2n (& result, & outpos, zval_get_long (tmp), width, padding, alignment, 1, hexchars, expprec); break; case'%': php_sprintf_appendchar (& result, & outpos,'%'); break; default: break;}
As you can see, only 15 types are matched in the php source code, and all other character types are directly break. Php does not do any processing and skips directly. So this leads to this problem: the biggest harm of not doing character type checking is that it can eat an escape character\. If a\ appears after%, then php will eat\ as a formatted character type, and finally%\ (or% 1 $\) will be replaced with empty so sprintf injection, or the principle of php format string injection is to understand the character after% (except%). % the above table has been given) will be eaten as a character type, that is, as a type to match the following variables, such as% c match ascii code,% d match integer, if not defined will match, match empty, such as%\, so that we have only one purpose, so that single quotation marks escape, that is, can play the role of closure.
Here are two examples.
NO.1
Do not use placeholder