Summary: Michael Howard proposes questions about integers operating security vulnerabilities and explains the security plan that can be used to protect their own applications.
Many years ago, few people heard that the integer overflow attack, but now it will have a new form every few days. The following short list is a security error that some integer overflow found in the last few months:
• Sun RPC XDR_Array • OpenSSH Authentication • Apache Chunked Encoding • Microsoft JScript • FreeBSD Socket and System Calls • Snort TCP Packet Reassembly
In this month's column, I will explain how these errors appear, how to search them in the code and how to fix them.
http://msdn.microsoft.com/library/en-us/dnse/html/strsafe.asp Read more about these string processing functions). However, this code may be affected by integers. If len1 is 64, len2 is 0xfffffffff, how will it be? It is determined that the code size of the buffer is legally added together, and 64 is generated due to the limitations of the add operation. Next, the code only assigns 64 bytes, then the code generates a new string of length 64 bytes, and then the 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff is connected to the string. Similarly, the application will end, in some cases, if you attack with a careful design size, the code may be affected by the available buffer.
Another lesson here is that if the buffer size is calculated correctly, the _safe string handler is not safe.
Back to top
JScript overflow attack
The same type of overflow error will occur when using multiplication, which occurs in Microsoft JScript errors. This error only shows that it will appear when you use JScript sparse array support:
VAR arr = new array ();
Arr [1] = 1;
Arr [2] = 2;
Arr [0x40000001] = 3;
In this example, the array has three elements, and the length is 0x40000001 (decimal 1073741825). However, since this example uses a sparse array, it only occupies an array of three elements of memory.
Implementing the C code of the JScript custom sort routine allocates a temporary buffer on the heap, copy the three elements into the temporary buffer, use the custom function to sort the temporary buffer, then transfer the contents of the temporary buffer to move back) . Below is the code to allocate the temporary buffer:
TemporaryBuffer = (Element *) Malloc (ElementCount * Sizeof (Element));
ELEMENT is a 20-byte data structure for saving the number of items. It seems that the program will try to assign approximately 20 GB for the temporary buffer. You may think that because there are no 20 GB of memory on most people's computers, allocation attempts will fail. Then, JScript regular memory insufficient processing routines will process the problem. Unfortunately, there is no such situation.
When using 32-bit integer algorithm, since the result (0x000000050000000014) is too large to be saved in a 32-bit value, we will be overflow attack:
0x40000001 * 0x00000014 = 0x0000000500000014
C will discard all non-conformable bits, so we will get 0x00000014. This is why the assignment has not failed - the assignment did not attempt to assign 20 GB, but only attempts to assign 20 bytes. Then, the sorting routine assumes that the buffer is large enough for the three elements in the sparse array, so it will make 60 bytes of these three elements to copy to 20 bytes of buffers, which overflows 40 bytes of buffers. It is too risky! Back to top
Symbol and no symbol error
Quickly view the following code. It is similar to the first example. See if you can find an error, if you find an error, try to determine what the error will generate.
Bool Func (Char * S1, INT LEN1,
Char * s2, int len2) {
Char buf [128];
IF (1 len1 len2> 128)
Return False;
IF (buf) {
STRNCPY (BUF, S1, LEN1);
STRNCAT (BUF, S2, LEN2);
}
Return True;
}
The problem here is that the size of the string is stored as an integer of a symbol, so as long as the Len2 is negative, the LEN1 can be greater than 128, and is less than 128 bytes. However, the call to STRNCPY will overflow the BUF buffer.
Back to top
Truncation error
Let's check the last attack type, pass the code example, you are guess.
Bool Func (Byte * Name, DWORD CBBUF) {
Unsigned short cbcalculatedbufsize = cbbuf;
Byte * buf = (byte *) malloc (cbcalculatedbufsize);
IF (buf) {
Memcpy (BUF, Name, CBBUF);
// do stuff with buf
IF (BUF) Free (BUF);
Return True;
}
Return False;
}
This kind of attack, at least this result is similar to the JScript error as described above. What if CBBUF is 0x00010020? Cbcalculatedbufsize is only 0x20 because only 16 bits are replicated from 0x00010020. Therefore, only 0x20 bytes are allocated, and 0x00010020 bytes are copied to the newly allocated target buffer. Please note that compiling this code using Microsoft Visual C / W4 options:
WARNING C4244: /// 'Initializing ///': conversion from //////// 'to ///' unsigned
Short /// ', Possible Loss Of Data
Please note that you do not mark a warning similar to the following operations:
INT LEN = 16;
Memcpy (BUF, SZDATA, LEN);
The last parameter of Memcpy is Size_T, and the parameter LEN is a symbol. Will not issue a warning because Memcpy always assumes that the third parameter is unsigned, and the converted into an unsigned no change the output of the function.
Note that if you try to assign a size_t for DWORD, you will receive a warning because data loss may appear on the 32-bit platform, but because data loss will appear on the 64-bit platform.
WARNING C4267: /// '= ///': conversion from /// 'size_t ///' to /// 'dword ///', Possible Lossof Data
You will receive this warning because all default C projects are compiled using the -WP64 option, which will notify the compiler to monitor 64-bit portability issues.
Back to top
Integer operation problem in hosted code
Integer operation errors may occur in hosted languages, such as C # and Visual Basic? Net, but potential damage will significantly reduce due to code does not directly access memory. However, calling this unit (assuming that your code is granted to call the unmanaged code) may still cause a security problem similar to the above. The integer in the General Language Specification (CLS) is a symbol, an error is to verify whether it is a symbolic integer parameter in the managed code when the variable is considered unsigned in the non-hosting code.
This particular example has put forward a more general recommendation: always check the content to pass to the unmanaged code. Many integer operations in the hosted code may cause reliability errors in Visual Basic .NET, because if overflow or underflow occurs, all such operations will trigger System.OverflowException.
By default, C # does not trigger these exceptions. If you want to check these questions, use the checked keyword:
UINT32 I = 0xffffffff0;
UINT32 J = 0x00000100;
UINT32 K;
Checked {k = i j;}
Back to top
Remedy
Who will think of just operating an integer will lead to security issues? Simple remedies for vulnerable code as follows:
IF (A B> max) Return -1;
Use the unsigned integer to use this code:
IF (A B> = A && A B // cool! } The first operation A B> = A. Check if there is surrounded, the second operation ensures additional and less than the target size. For operational problems in JScript, you can check the number of elements do not exceed a predetermined value, and the predetermined value is less than the maximum amount you will have to memory. For example, the following code will potentially assign up to 64 MB of memory: Const size_t max = 1024 * 1024 * 64; Const size_t elem_size = sizeof (element); const size_t max_elex = max / elem_size; IF (CELEMS> = MAX_ELEMS) Return False; Finally, for array indexes, buffers, and similar objects, use unsigned integers, such as DWORD and SIZE_T. Back to top Key code checkpoint Remember the following points when compiling or checking the code related to an integer, remember the following points: • Compile C and C code using the highest warning level / w4. • Use Size_T or DWORD for buffer size and element count. There is no reason to use a symbolic value for these structures. • Keep in mind that SIZE_T will represent different types according to the platform you use. SIZE_T is the size of the memory address, so on the 32-bit platform, it is a 32-bit value, but on the 64-bit platform, it is a 64-bit value. • If the code performs any type of integer operation (plus, multiplied, etc.), where the result is used to index to an array or compute the buffer size, make sure that the operand is within a small, easy to understand. • Availabile memory allocation function (New, Malloc, GlobalLalloC, etc.) because they will be considered unsigned integers. • Note the operation of the C4018, C4389, and C4244 warnings. • Note Abandon the conversion of C4018, C4389 and C4244 warnings. • Survey all the use of C4018, C4389, and C4244 warning #pragma Warning (Disable, CNNNN). In fact, mark them as comments, recompile, and check all new warnings related to integers. • The code that migrates from other platforms or compilers may use different data sizes. Be careful! • If you call the unmanaged code from the managed code, make sure it is correct. Many parameters of the Win32 API are unsigned int or DWORD, and many managed code variables are symbolic. • Finally, if you use managed code, make sure to use Catch OverflowException during the appropriate time. Back to top Discover security vulnerability Many people have checked my problem last month. It is an integer overflow attack. So what is the problem with this C # code? String status = /// "no ///"; String sqlstring = /// "///"; Try { SqlConnection SQL = New SQLCONNECTION @ /// "Data Source = localhost; ///" /// "User ID = sa; password = password; ///"); SQL.Open (); Sqlstring = /// "SELECT HASSHIPPED / / /" /// "from detail where id = /// '///" ID /// "///' ///"; SQLCommand cmd = new sqlcommand (sqlstring, sql); IF ((int) cmd.executescalar ()! = 0) Status = /// "Yes ///"; } catch (sqlexception se) { Status = SQLSTRING / / / "failednr ///"; Foreach (SQLERROR E IN Se.Error) { Status = E.Message /// "nr ///"; } } catch (exception e) { Status = e.tostring (); }