此文是由于一个CTF题而引发的学习和思考,以后坚持做CTF,还是能学不少东西的,有点后悔没早点开始了。。。
False注入


The following rules describe how conversion occurs for comparison operations: If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed. If both arguments in a comparison operation are strings, they are compared as strings. If both arguments are integers, they are compared as integers. Hexadecimal values are treated as binary strings if not compared to a number. If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN()! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type. If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value. In all other cases, the arguments are compared as floating-point (real) numbers.
为了大家看起来理解起来更加方便点,我贴段百度翻译过来,感觉这次机翻还是挺准确的。。。
以下规则描述比较操作的转换方式: 如果一个或两个参数都为空,则比较结果为空,但空安全<=>相等比较运算符除外。对于空值<=>空值,结果为真。不需要转换。 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。 如果两个参数都是整数,则将它们作为整数进行比较。 如果不与数字进行比较,十六进制值将被视为二进制字符串。 如果其中一个参数是timestamp或datetime列,而另一个参数是常量,则在执行比较之前,该常量将转换为timestamp。这样做是为了更好地支持ODBC。注意,这不是为in()中的参数所做的!为了安全起见,在进行比较时始终使用完整的日期时间、日期或时间字符串。例如,要在与日期或时间值之间使用时获得最佳结果,请使用cast()将值显式转换为所需的数据类型。 如果其中一个参数是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,则将这些参数作为十进制值进行比较;如果另一个参数是浮点值,则将这些参数作为浮点值进行比较。 在所有其他情况下,参数都是作为浮点数(实数)进行比较的。
select * from test where name=0
。在我们表中name所有的数据都是字符串,现在要拿字符串和0(整数)来比较,所以要把字符串和0都转成浮点数,但是字符串转成浮点数会失败的,所以字符串就会转成0,结果就变成了0=0,于是匹配成功,可以显示出整张表的数据。

当我使用flag=0时,居然只出现了两项记录,id=3的这条不见了,我们来看看第3条记录,flag是为1san579的,如果把此字符串转成浮点数,是可以转换成功的,结果为1,因为当字符串转浮点时如果是以数字开头就转到数字处再截断,于是结果就变成了1=0,所以第3条数据没了。

select * from test where name='1'='0' and flag='1'='0'
,实际上是select * from test where name=0 and flag=0
,也就是要把之前查询name=0和flag=0两张表相同的部分整理出来即可,所以应该是2条数据,因为flag=0的时候是没有第3条数据的,但是结果和我想的不一样。。。

select * from test where name='1'='0' and flag='1'='0'
实际上不是select * from test where name=0 and flag=0
,啊啊啊!!!再接下来的测试中确定了是下面的问题。。。


原来如果有连续多个=号,是从左往后依次执行。。所以'1san579'='1'='0'这样的东西就变成了0='0',结果为1,但是如果是从右往左的后就变成了'1san579'=0,结果为0。
select * from test where name='1'='0' and flag='1'='0'
最后变成了select * from test where 1 and 1
,就是这样显示出全表的。
总结
来源:CSDN
作者:baynk
链接:https://blog.csdn.net/u014029795/article/details/98803880