最最重要的SQL手工注入基础语法知识

SQL注入必备基础知识


初学SQL注入的小白,整理一下必备的一些基础知识,如有不如或者错误请指出。

注释符

  • 单行注释: - -
  • 多行注释:/* … */
    在sql-labs中,经常使用- - +放在最后注释多余部分

WHERE 子句

如果只希望选取居住在西安中的人,我们需要向select语句添加where子句:

select * from persons where city=‘xi’an’


SELECT查询

  • select 列名 from 表名
  • select * from 表名

如果把一个学校比作数据库,那么年级就是表名,班级就是列名,意思就是从某年级查看一下某班级。

例如:
select column_name from table_name


查字段数(ORDER BY)

order by 语句用于根据指定的列对结果集进行排序,order by语句默认按照升序对记录进行排序,如果您希望按照降序对记录进行排序。
sql-labs中,因为union前面列数必须一致,我们必须找出实际列数。这里我们使用了order by,因为order by 排序列数多于实际列数会报错。

假设这里有一个包含SQL注入漏洞的URL,它会将HTTP GET方法中名为“order”的参数的值(该值由用户指定)传递给SQL查询。该URL如下所示:

http://xxx/.asp?data=yes&order=column_name

然后,应用程序会从HTTP GET方法的参数“order”中接收用户提供的数据,并生成如下所示的SQL查询:

Select table_name,column_name from information_schema.columns order by column_name


分组(GREAT BY)

great bygreat表示分组,by后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,great by比较类似Excel里面的透视表。
great by必须得配合聚合函数来用,分组之后你可以计数(count),求和(sum),求平均数(avg)等。

例如:
select column_name, aggregate_function(column_name) from table_name where column_name operator value order by column_name


合并语句(UNION)

union用于合并两个或多个select语句,而且union内部的select必须有相同数量的列,列有相似的数据类型,简单的说就是它内部列的属性相同,要么都是数字型,要么都是字符型。

例如:
select column_name from table_name1
union
select column_name from table_name2


连接字符(CONCAT)

concat用于将两个字符连为一个字符串,返回结果为连接产生的字符串,如有任何一个参数为NULL(空),则返回值为NULL(空)。

例如:
select concat (admin,passward) fromwhere


延时函数(SLEEP)

select sleep (N) 可以让语句运行N秒钟
sleep可以强制产生一个固定的延迟

例如:
id=1 and sleep(5) //判断下是否存在延时注入,若5秒钟页面返回则存在。


COUNT函数

COUNT() 函数返回匹配指定条件的行数。

例如:

select count (column_name)from table_name //返回指定列的值的数目
select count (*)from table_name //返回表中的值的数目


在 Java 中检测 SQL 语句的有效性和安全性是非常重要的一步,尤其是在防止 SQL 注入攻击方面。虽然没有专门针对整个 SQL 查询的完整正则表达式(因为这涉及到复杂的 SQL 文法),但我们可以通过编写一些简单的正选模式来检查常见的危险特征,并结合预处理语句等手段增强应用程序的安全性。 以下是几种方法可以在 Java 应用程序里验证用户输入到 SQL 命令之前是否安全: ### 方法一:使用预编译 PreparedStatement 推荐的方式还是尽量避免直接拼接字符串构成终要执行的 SQL ,而是采用 JDBC 的PreparedStatement 接口。这种方式会自动为我们处理转义特殊字符的问题。 ```java String query = "SELECT * FROM Users WHERE username=?"; try (Connection conn = DriverManager.getConnection(url); PreparedStatement pstmt = conn.prepareStatement(query)) { // 设置实际参数值 pstmt.setString(1, userName); ResultSet rs = pstmt.executeQuery(); } catch (SQLException e) { System.err.println(e.getMessage()); } ``` 这种方法能够有效地防范绝大多数类型的注入威胁。 ### 方法二:限制特定字符序列出现频率 如果确实需要用到动态生成 SQL,则可以考虑加入一层基于正则表达式的过滤机制。例如不允许连续出现两个以上的单引号、反斜杠或其它可疑符号组合: ```java public static boolean isValidSql(String sql){ if(sql == null || "".equals(sql.trim())) return false; String[] invalidKeywords={"drop","truncate","delete from"}; for(String keyword :invalidKeywords){ Pattern pattern =Pattern.compile(keyword ,Pattern.CASE_INSENSITIVE|Pattern.MULTILINE); Matcher matcher =pattern.matcher(sql.toLowerCase()); while(matcher.find()){ return false; } } // 简易版禁止过多标点符号连用 final int MAX_ALLOWED_SYMBOLS_COUNT=5; long countSpecialCharaters = sql.chars() .filter(c -> !Character.isLetterOrDigit((char)c)) .count(); return !(countSpecialCharaters >MAX_ALLOWED_SYMBOLS_COUNT ); } // 测试一下上述方法的效果 System.out.println(isValidSql("select name from user where id='1")); //true System.out.println(isValidSql(";DROP DATABASE students --"));//false ``` 这里展示了一个比较基础的例子,只是一些简单的规则集合;现实中还需要根据具体的业务场景调整关键词列表和其他细节配置项。此外要注意的是,这种做法并不能完全消除风险,好还是要结合其他防护措施一起使用。 ### 方法三:引用第三方库做进一步解析审核 对于那些对数据访问层有着更高要求的应用系统来说,建议引入专业的工具包来进行严格的语法树分析以及内容审计工作。比如 Hibernate Validator 可以为开发者提供更高级别的约束定义能力,而 OWASP ESAPI 这样的框架也内嵌了一些实用的小工具帮助抵御恶意企图。 总结而言,在 Java 环境下确保提交给 DBMS 处理之前的每一句话都是干净可靠的既包括技术层面的选择也有管理流程上的把控。务必优先选择成熟的 API 或组件减少手工编码带来的潜在漏洞可能性!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值