学习webgoat靶场的时候遇到一个有意思的sql注入
在这之前值得一提的是,sql的所有操作都会记录到access_log这个表中,如果可以堆叠注入,最后记得要清除这个表:
1';drop table access_log; -- -
然后是一道sql:
首先探测一下注入点
这里是实际是成功执行了查询,显示没有结果,所以没有注入点,否则应该会报错
这里比较扯,他说这个名字存在,但其实应该是注入生效返回了True
对密码进行测试的时候直接创建了,然而我两次输入的密码明明是不一样的,这里把握搞晕了。后来查看了一下博客发现我跑偏题了,username这里能进行注入,那么通过这个地方要么查询要么修改Tom的密码然后登陆
然后到了bool盲注的阶段,这里不再赘述了,只是个人经验不是很足,对这个回显麻痹了一下,觉得挺有意思的。
然后是一些防御:
静态查询
SELECT * FROM users WHERE user = "'" + session.getAttribute("UserID") + "'";
这里专门查询了一下:
- 静态 SQL:静态 SQL 语句一般用于嵌入式 SQL 应用中,在程序运行前,SQL 语句必须是确定的,例如 SQL 语句中涉及的列名和表名必须是存在的。静态 SQL 语句的编译是在应用程序运行前进行的,编译的结果会存储在数据库内部。而后程序运行时,数据库将直接执行编译好的 SQL 语句,降低运行时的开销。静态SQL在编译时已经确定了引用的表和列。 宿主变量不改变表和列信息。 可以使用主变量改变查询参数值, 但是不能用主变量代替表名或列名。
- 动态 SQL:动态 SQL 语句是在应用程序运行时被编译和执行的,不在编译时确定 SQL 的表和列,而是让程序在运行时提供,并将
SQL 语句文本传给 DBMS 执行。 静态 SQL 语句在编译时已经生成执行计划。 而动态 SQL 语句,只有在执行时才产生执行计划。动态 SQL 语句首先执行 PREPARE 语句要求 DBMS 分析、确认和优化语句,并为其生成执行计划。例如,使用 DB2 的交互式工具 CLP 访问数据库时,用户输入的 SQL 语句是不确定的,因此 SQL 语句只能被动态地编译。动态 SQL 的应用较多,常见的 CLI 和 JDBC 应用程序都使用动态 SQL。
所以这里的静态语句是直接确定的,在程序运行以前就编译好了,用户无法自主控制
预编译
这个就不说了,预编译虽然是一个非常有效的的sql注入防御方法,但是听D4n师傅说有些语句和sql的特性注定了会被注入,然后简单查询了一下:
[SQL预编译的绕过_sql注入绕过预编译-CSDN博客](https://blog.csdn.net/AoaNgzh/article/details/130459165#:~:text=SQL预编译的绕过 1 字符串拼接:如果在SQL预编译语句中使用了字符串拼接,攻击者可以通过构造特定的字符串来绕过预编译过程。 2,动态拼接SQL语句:如果动态地拼接SQL语句,例如使用字符串拼接、字符串格式化等方式,攻击者同样可以利用字符串的特性来绕过预编译过程。 3 SQL语句中使用函数或存储过程:如果在SQL语句中使用了函数或存储过程,攻击者可以构造恶意的输入,使其执行预期之外的操作,绕过预编译过程。 4 错误处理不当:如果SQL预编译过程中的错误处理不当,例如忽略异常或者异常处理不当,攻击者可能会通过特定的输入来触发错误,绕过预编译过程。)
显然虽然可以绕过,但是明显已经有了很强的局限性