无需“in”的SQL盲注
为了锻炼安全技术,我在TetCTF上想寻找一些新奇的网络挑战,并注意到一个有趣的系统——“Secure System”。
其中挑战目标是制作一个和SQL盲注有关的payload,并且不使用:
UNION … SELECT
information_schema
“in”和“or”等关键词
尽管还有其他安全过滤,但以上关键词是最难克服的障碍。
information_schema的替代方法
我在网上搜索了一下从MySQL数据库中检索表名的替代方法,但没有找到任何可行的方法。所有的技术都依赖于information_schema
或mysql.innodb_table_stats,但这两者都会被“in”关键词过滤掉。所以,我需要寻找新方法,并在研究了一段时间后成功发现了替代品sys.x$schema_flattened_keys
。
在上述示例中,不仅包含一个table_name
列,还包含“索引列”。但这不是唯一的方法,还有另一个表sys.schema_table_statistics
可显示更多的表:
通过这种方法和SQL盲注技术,我成功得到了目标表名Th1z_Fack1n_Fl4444g_Tabl3
。
他人的解决方案
在尝试检索列名的时候,我遇到了不小的困难,尝试了很多方法都不成功。但我发现的表格sys.x$statement_analysis
可让我查看其他参与者的解决方案。
我很好奇是否有人找到了列名,但脚本运行要花费很多时间,所以我只检索上面示例中的内容。这也许能在将来帮我解决其他SQL注入挑战!
在没有列名的情况下检索数据
如果一个表只包含一列,那么很轻易就可在不知道列名的情况下检索出数据,只需一个简单的SUBSTR((SELECT * FROM table),1,1)='x'
就可,但如果一个表包含多个列,那么这个查询就会抛出一个错误。不过这里有个技巧,就是将查询语句与相同数量的列进行比较!
通过小于号替换等号,你可以逐字符检索出数据。不过还有一个问题——MySQL中的字符串比较在默认情况下是不区分大小写的。
区分大小写
通过以上方法我可以得到全是小写字母的flag,现在就需要一个区分大小写的方法。我发现将字符串转换为二进制格式后,会强制进行字节对字节的比较,这正是我所需要的。但问题是,BINARY
函数中的“in”被过滤掉了。
此时我注意到,当一个字符串连接一个二进制的值时CONCAT("aa", BINARY("BB"))
,其得到的也将是二进制。因此我需要找到一个方法,将一个二进制字符串插入CONCAT
函数中。
经过反复试验,我终于发现MySQL中的JSON对象是二进制对象,因此,CAST(0 AS JSON)
会返回一个二进制字符串,进而SELECT CONCAT(“A”, CAST(0 AS JSON))
也会返回一个二进制字符串。
综合以上改进,我成功地获得了完整的flag,它实际上只含有一个大写字符,但还是花了我几个小时。
TetCTF{0wl_d0nkey_means_Liarrrrrrr}
有趣的挑战和解决方案
这正是我喜欢CTF的地方,一个简单的安全挑战就可以引导出很棒的研究。我不确定我的解决方案是否为最好,但对我来说这是一个伟大的旅程!
此外(关于这个挑战的其他内容),我们一开始希望使用ORD(SUBSTR((SELECT smth),x,1))=77
去检索值,但是由于过滤了“or”关键词,ORD
被禁止了。不过还是可以通过CONV(HEX(SUBSTR((SELECT ...),x,1)),16,10)=77
绕过。以下是Oracle盲注的payload:
最后根据这些方法和已经检索到的表名,payload如下:
详细链接点击这里。
本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场
来源:https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952
最新评论