PHP is a general open source scripting language. Its syntax mixes the syntax of excellent languages such as C, Java, and Perl. In addition, it also provides a large number of function libraries for developers to use. However, if used improperly, PHP can also bring very large security risks to applications.
In this article, we will conduct an in-depth analysis of some problems that often occur in PHP applications, especially when we use "==" (comparison operator) to perform string comparisons, which may Some security issues arise. Although many articles have recently discussed this topic, I decided to discuss how to use this problem to penetrate and attack targets from the perspective of "black box testing". First, I will analyze the root cause of this problem so that we can have a deeper understanding of its working mechanism, so as to ensure that we can avoid this security problem as much as possible.
Description of the problemIn fact, this situation will occur when using comparison operators like "==" to operate. The problem in the above example cannot be regarded as a vulnerability, because it is a function called "type conversion" provided by PHP. Essentially, when we use specific comparison operators (such as ==, !=, ) to operate, PHP will first try to determine the data type participating in the comparison. However, such a type conversion mechanism may cause the calculation results to be greatly different from our expected results, and will also cause very serious security issues. Security research experts wrote in a full disclosure report on the issue: This type conversion mechanism may lead to privilege escalation and even make the program's password verification process unsafe.
As you can see, when we use "==" to compare these numerical strings, what is involved in the comparison is the actual size of the numbers in the string, from safety From this perspective, this is a very interesting question. In this case, you can use scientific notation to represent a number and put it in a string, and PHP will automatically treat it as a number type. The reason why we get such an output type is because PHP uses a hash algorithm (usually represented by a hexadecimal value) for processing. For example, if a number is 0, PHP will automatically convert its type during the loose comparison, but its value will always be 0. For a given hashing algorithm, the password may become replaceable. For example, when a password hash is converted into a number using scientific notation, it will likely match other password hashes. In this way, even a completely different password may still pass the system's verification. But what’s interesting is that when comparing certain numbers expressed in scientific notation, the results may surprise you:
import random import hashlib import re import string import sys prof = re.compile("^0+ed*$") # you can also consider: re.compile("^d*e0+$") prefix = string.lower(sys.argv[1])+'!'+string.upper(sys.argv[1])+"%s" num=0 while True: num+=1 b = hashlib.sha256(prefix % num).hexdigest() if (b[0]=='0' and prof.match(b)): print(prefix+str(num),b)For this, I specially wrote a Python script, although I No effort has been made to optimize the performance of this script, but with the help of the PyPy compiler, this well-written script runs stably on all available CPU cores of my AMD FX8350. In addition, I also used the hash function in the hashlib library, and in order to avoid encountering the process synchronization problem of Python GIL, I also generated an independent process to process the password data. Not only that, I also used a very sophisticated technique to generate a different prefix for each password, as shown in the code above.
The calculation results of the passwords are very similar, as shown below:
You can randomly select two passwords for comparison. The comparison demonstration results are as follows:
If you cannot get the password as shown above Calculate the results, then you should feel lucky. You could try bundling the username and password together and then using a hash algorithm with a "salt" value to calculate it. You only need to modify a small part of the code to achieve it. Click "here" to get the modified script.