本文将为您提供关于SQL注入保护的详细介绍,我们还将为您解释sql注入的防护的相关知识,同时,我们还将为您提供关于c#–何时担心SQL注入保护、c#–如何保护此功能免于SQL注入?、Mybatis-p
本文将为您提供关于SQL注入保护的详细介绍,我们还将为您解释sql注入的防护的相关知识,同时,我们还将为您提供关于c# – 何时担心SQL注入保护、c# – 如何保护此功能免于SQL注入?、Mybatis-plus sql注入及防止sql注入详解、MySQL 及 SQL 注入:防止SQL注入、Like语句中的注入的实用信息。
本文目录一览:- SQL注入保护(sql注入的防护)
- c# – 何时担心SQL注入保护
- c# – 如何保护此功能免于SQL注入?
- Mybatis-plus sql注入及防止sql注入详解
- MySQL 及 SQL 注入:防止SQL注入、Like语句中的注入
SQL注入保护(sql注入的防护)
我想我会从您认为可以基本上消除SQL注入可能性的选项中获得您的意见(我认为)。
当前,我有我的管理员帐户,该帐户显然可以为我提供数据库的完整命令(更改,删除等)。我将拥有一个PHP使用的帐户,该帐户只能访问SELECT,UPDATE,DELETE,INSERT。如何为每个操作设置一个用户,然后仅在mysql_query语句中引用连接ID呢-
现在很明显,这将给服务器带来更多压力,本质上每页必须建立4个连接,但是如果安全性是重要的是,在我看来,通过将命令限制为要在这种情况下执行的EXACT函数,这将是一个有效的选择。关于此选项的可行性有何想法?
更新:正如我之前没有提到的那样,这不是防止SQL注入,mysql_real_escape_string(),准备好的语句等的唯一障碍。但是我只是想也许所有这些都失败了,不是吗?至少限制了他们可能造成的损害?(例如,在注册表上,他们将无法选择哈希或删除条目)。
c# – 何时担心SQL注入保护
也就是说,该公司有一个DLL(Database.dll),其中包含“我需要的所有数据库交互”.在,它有一个Query(),Update(),Insert()等.现在,我正在编写的项目设置对Database.dll的引用.我的项目接受零用户输入.与用户输入最接近的是用户可以从中选择日期的下拉框.没有太多的经验,我很好奇我是否还需要担心sql注入?如果是这样,那么查询会写得像
var query = string.Format("SELECT timestamp FROM table1 WHERE date = \"{0}\" AND measured_dist = bit_loc AND rop > 0",Date))
足够作为参数化查询?请记住,所有查询执行都由预先存在的Query()处理,我告诉我必须使用它,并且无法编辑.
编辑
该程序是一个WinForm应用程序.
解决方法
c# – 如何保护此功能免于SQL注入?
public static bool TruncateTable(string dbAlias,string tableName) { string sqlStatement = string.Format("TruncATE TABLE {0}",tableName); return ExecuteNonQuery(dbAlias,sqlStatement) > 0; }
解决方法
在这种情况下这是错误的答案.您不能在DDL语句中为表名使用SQL查询参数.
SQL查询参数只能用于替换sql表达式中的文字值.这是sql的每个实现的标准.
当您有表名时,我的防止sql注入的建议是根据已知表名的列表验证输入字符串.
您可以从informatION_SCHEMA获取有效表名的列表:
SELECT table_name FROM informatION_SCHEMA.Tables WHERE table_type = 'BASE TABLE' AND table_name = @tableName
现在,您可以将输入变量作为sql参数传递给此查询.如果查询不返回任何行,则您知道该输入无效用作表.如果查询返回一行,则匹配,因此您可以更安全地使用它.
您还可以根据您定义的特定表的列表来验证表名称,以便您的应用程序截断,如@John Buchanan suggests.
即使在确认tableName作为RDBMS中的表名称后,我也建议分隔表名,以防万一使用带有空格或特殊字符的表名.在Microsoft sql Server中,默认标识符分隔符是方括号:
string sqlStatement = string.Format("TruncATE TABLE [{0}]",tableName);
现在,如果tableName匹配一个真实的表,那么sql注入的风险就是这样,而你实际上在表的名称中使用方括号!
Mybatis-plus sql注入及防止sql注入详解
一、SQL注入是什么?
SQL注入是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL语句被 插入到执行的SQL语句中来改变查询结果,例如: OR 1=1 或者 ;drop table sys_user;等等
二、mybatis是如何做到防止sql注入的
mybatis中我们所写的sql语句都是在xml只能完成,我们在编写sql会用到 #{},${} 这个两个表达式。那 #{} 和 ${}两者之间有什么区别嘞?下面我将用两个SQL语句例子来进行说明。
<select id="selectUserByUserName" parameterType="java.lang.String" resultType="com.domain.UserInfo"> SELECT USER_ID, USER_NAME, PWD, USER_PHONE FROM SYS_USER <where> USER_ID= #{userName,jdbcType=VARCHAR} </where> </select>
<select id="selectUserByUserName" parameterType="java.lang.String" resultType="com.domain.UserInfo"> SELECT USER_ID, USER_NAME, PWD, USER_PHONE FROM SYS_USER <where> USER_NAME= ${userName,jdbcType=VARCHAR} </where> </select>
- 第一种SQL语句中使用的#{}方式,#{}中当传入的数据是字符串,会在使用" "双引号将值引起来。
- 示例:例如 userName 传入的值是 9;DROP TABLE SYS_USER;那么#{}去取后得到的结果就是 USER_NAME="9;DROP TABLE SYS_USER;"就算传入删除表的命令也不会被执行,因为9;DROP TABLE SYS_USER;会帮当成一个完成的字符串去进行值匹配。
- 第二种SQL${}方式取值,那就变成了USER_NAME=9;DROP TABLE SYS_USER; , 因 为 ${}直接将值拼接在SQL语句后面的,使其成为SQL,因此直接将值拼接在SQL语句后面的,因此${}是存在SQL注入的风险的,在使用时要注意手动处理。
1. #{} 和 ${} 两者的区别
- #{}:解析为一个 JDBC 预编译语句,一个 #{} 被解析为一个参数占位符 ? ,#{}方式将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。 如:WHERE USER_NAME =#{username},如果传入的值是9,那么解析成sql时的值为WHERE USER_NAME =“9”,如果传入的值是12345678,则解析成的sql为WHERE USER_NAME =“12345678”,
- ${} 仅 仅 为 一 个 纯 粹 的 s t r i n g 替 换 ,${}方式传入的变量直接拼接在sql中。如:WHERE USER_NAME = ${username},如果传入的值是9,那么解析成sql时的值为WHERE USER_NAME =9; 如果传入的值是;DROP TABLE SYS_USER;,则解析成的sql为:SELECT USER_ID, USER_NAME, PWD, USER_PHONE FROM SYS_USER WHERE USER_NAME="9;DROP TABLE SYS_USER;所以象 ORDER BY 或者 GROUP BY 等可以使用 ${}方式。
- #{}方式底层采用预编译方式PreparedStatement,能够很大程度防止sql注入,因为SQL注入发生在编译时;${}方式底层只是Statement,无法防止Sql注入。
$方式一般用于传入数据库对象,例如传入表名
2.PreparedStatement和Statement的区别
① PreparedStatement 在执行sql命令时,命令会先被数据库进行解析和编译,然后将其放到命令缓存区,然后,当每一个执行的相同的sql 命令时,若在缓存区发了编译命令,就不会再次进行解析和编译,这样就可以进行重复使用。PreparedStatement 在编译是会将每个#{}标记符号解析为参数参数占位符?,传入的变量就是做为参数,不会对sql语句进行修改,这样就能防止SQL注入的攻击。‘’
②Statement是直接将Sql命令直接交给数据库进行运行,不能做到拦截SQL注入的攻击,因为SQL注入时发生在运行时。Statement每次都会对SQL命令进行解析和编译,增加大数据库的开销,因此它效率不如PreparedStatement。
3.什么是预编译
预编译是做些代码文本的替换工作。是整个编译过程的最先做的工作。处理以# 开头的指令 , 比如拷贝 #include 包含的文件代码,#define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段。主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。而SQL注入只能发生在运行时。
4.mybaits-plus sql注入产生的原因
Mybatisplus中的 PaginationInterceptor 主要用于处理数据库的物理分页,避免内存分页。
分析PaginationInterceptor 的源码可以发现
Orderby场景下的SQL注入
前面提到了分页中会存在Orderby的使用,因为Orderby动态查询没办法进行预编译,所以不经过安全检查的话会存在注入风险。PaginationInnerInterceptor主要是通过设置com.baomidou.mybatisplus.extension.plugins.pagination.page对象里的属性来实现orderby的,主要是以下函数的调用,因为直接使用sql拼接,所以需要对进行排序的列名进行安全检查:
page.setAscs(); page.setDescs();
源码:
可以看出,分页是通过字符串拼接的方式,所以出现SQL注入的风险
public static String concatOrderBy(String originalSql, IPage<?> page, boolean orderBy) { if (!orderBy || !ArrayUtils.isNotEmpty(page.ascs()) && !ArrayUtils.isNotEmpty(page.descs())) { return originalSql; } else { StringBuilder buildSql = new StringBuilder(originalSql); String ascStr = concatOrderBuilder(page.ascs(), " ASC"); String descStr = concatOrderBuilder(page.descs(), " DESC"); if (StringUtils.isNotEmpty(ascStr) && StringUtils.isNotEmpty(descStr)) { ascStr = ascStr + ", "; } if (StringUtils.isNotEmpty(ascStr) || StringUtils.isNotEmpty(descStr)) { buildSql.append(" ORDER BY ").append(ascStr).append(descStr); } return buildSql.toString(); } }
三、Mybatis-plus是如何做到防止sql注入的
在使用分页的controller,对传入的分页插件,对ascs与descs进行检查,判断是否有非法字符,如有,则提示参数中含有非法的列名:create_time aaaa
示例:
校验字段的util:
package com.koal.util; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.koal.exception.BizException; import com.koal.web.ErrorCode; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; import java.util.Optional; import java.util.regex.Pattern; /** * @author sunrj */ public class RegexUtils { /** * 对Page校验防止sql注入 * * @param */ public static void verifyPageFileld(Page page) { //asc校验 Optional.ofNullable(page.ascs()).ifPresent(ascs -> { Arrays.asList(ascs).forEach(asc -> { boolean rightfulString = RegexUtils.isRightfulString(asc); if (!rightfulString) { throw new BizException(ErrorCode.COMMON_VERIFY_ERROR.getCode(), "ascs参数中含有非法的列名:" + asc); } }); }); //desc校验 Optional.ofNullable(page.descs()).ifPresent(descs -> { Arrays.asList(descs).forEach(desc -> { boolean rightfulString = RegexUtils.isRightfulString(desc); if (!rightfulString) { throw new BizException("10011", "desc参数中含有非法的列名:" + desc); } }); }); } /** * 判断是否为合法字符(a-zA-Z0-9-_) * * @param text * @return */ public static boolean isRightfulString(String text) { return match(text, "^[A-Za-z0-9_-]+$"); } /** * 正则表达式匹配 * * @param text 待匹配的文本 * @param reg 正则表达式 * @return */ private static boolean match(String text, String reg) { if (StringUtils.isBlank(text) || StringUtils.isBlank(reg)) { return false; } return Pattern.compile(reg).matcher(text).matches(); } }
controller校验page中的字段:
@GetMapping @ApiOperation(value = "查询用户列表", notes = "查询用户列表") public ServerResponse<IPage<Account>> queryAccount(Page<Account> page) { //校验page中的字段,防止sql注入 RegexUtils.verifyPageFileld(page); return ServerResponse.successMethod(accountService.query(page)); }
结果:
POST http://127.0.0.1:8080/account?current=1&size=10&ascs=create_time;DROP TABLE tb_account;
结果:
{
"code": "10011",
"msg": "ascs参数中含有非法的列名:create_time;DROP TABLE ag_account_info;",
"timestamp": 1653547051505
}
补充:Mybatis Plus自定义全局SQL注入
实现步骤如下:
- 在 Mapper接口中定义相关的 CRUD方法
- 扩展 AutoSqlInjector inject 方法,实现 Mapper接口中方法要注入的 SQL
- 在 MP全局策略中,配置 自定义注入器
① mapper中定义业务方法
如下所示:
public interface EmployeeMapper extends BaseMapper<Employee> { int deleteAll(); }
② 实现自己的MySqlInjector
如下所示:
/** * 自定义全局操作 */ public class MySqlInjector extends AutoSqlInjector{ /** * 扩展inject 方法,完成自定义全局操作 */ @Override public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { //将EmployeeMapper中定义的deleteAll, 处理成对应的MappedStatement对象,加入到configuration对象中。 //注入的SQL语句 String sql = "delete from " +table.getTableName(); //注入的方法名 一定要与EmployeeMapper接口中的方法名一致 String method = "deleteAll" ; //构造SqlSource对象 SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); //构造一个删除的MappedStatement this.addDeleteMappedStatement(mapperClass, method, sqlSource); } }
③ 把自定义的MySqlInjector 配置到全局策略中
如果是xml配置方式,实例如下:
<!-- 定义MybatisPlus的全局策略配置--> <bean id ="globalConfiguration"> <!-- 在2.3版本以后,dbColumnUnderline 默认值就是true --> <property name="dbColumnUnderline" value="true"></property> <!-- Mysql 全局的主键策略 --> <property name="idType" value="0"></property> <!-- 全局的表前缀策略配置 --> <property name="tablePrefix" value="tbl_"></property> <!--注入自定义全局操作 --> <property name="sqlInjector" ref="mySqlInjector"></property> </bean> <!-- 定义自定义注入器 --> <bean id="mySqlInjector"></bean>
总结
到此这篇关于Mybatis-plus sql注入及防止sql注入的文章就介绍到这了,更多相关Mybatis-plus防止sql注入内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
- Mybatis-Plus通过SQL注入器实现批量插入的实践
- Mybatis-Plus注入SQL原理分析
- Mybatis-Plus的应用场景描述及注入SQL原理分析
MySQL 及 SQL 注入:防止SQL注入、Like语句中的注入
MySQL 及 SQL 注入
如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题。
本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入的字符。
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
我们永远不要信任用户的输入,我们必须认定用户输入的数据都是不安全的,我们都需要对用户输入的数据进行过滤处理。
以下实例中,输入的用户名必须为字母、数字及下划线的组合,且用户名长度为 8 到 20 个字符之间:
if (preg_match("/^\w{8,20}$/", $_GET[''username''], $matches))
{
$result = mysqli_query($conn, "SELECT * FROM users
WHERE username=$matches[0]");
}
else
{
echo "username 输入异常";
}
让我们看下在没有过滤特殊字符时,出现的SQL情况:
// 设定$name 中插入了我们不需要的SQL语句
$name = "Qadir''; DELETE FROM users;";
mysqli_query($conn, "SELECT * FROM users WHERE name=''{$name}''");
以上的注入语句中,我们没有对 $name 的变量进行过滤,$name 中插入了我们不需要的SQL语句,将删除 users 表中的所有数据。
在PHP中的 mysqli_query() 是不允许执行多个 SQL 语句的,但是在 SQLite 和 PostgreSQL 是可以同时执行多条SQL语句的,所以我们对这些用户的数据需要进行严格的验证。
防止SQL注入,我们需要注意以下几个要点:
- 1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
- 2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
- 3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
- 4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
- 5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
- 6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。
防止SQL注入
在脚本语言,如Perl和PHP你可以对用户输入的数据进行转义从而来防止SQL注入。
PHP的MySQL扩展提供了mysqli_real_escape_string()函数来转义特殊的输入字符。
if (get_magic_quotes_gpc())
{
$name = stripslashes($name);
}
$name = mysqli_real_escape_string($conn, $name);
mysqli_query($conn, "SELECT * FROM users WHERE name=''{$name}''");
Like语句中的注入
like查询时,如果用户输入的值有"_"和"%",则会出现这种情况:用户本来只是想查询"abcd_",查询结果中却有"abcd_"、"abcde"、"abcdf"等等;用户要查询"30%"(注:百分之三十)时也会出现问题。
在PHP脚本中我们可以使用addcslashes()函数来处理以上情况,如下实例:
$sub = addcslashes(mysqli_real_escape_string($conn, "%something_"), "%_");
// $sub == \%something\_
mysqli_query($conn, "SELECT * FROM messages WHERE subject LIKE ''{$sub}%''");
addcslashes() 函数在指定的字符前添加反斜杠。
语法格式:
addcslashes(string,characters)
参数 | 描述 |
---|---|
string | 必需。规定要检查的字符串。 |
characters | 可选。规定受 addcslashes() 影响的字符或字符范围。 |
我们今天的关于SQL注入保护和sql注入的防护的分享已经告一段落,感谢您的关注,如果您想了解更多关于c# – 何时担心SQL注入保护、c# – 如何保护此功能免于SQL注入?、Mybatis-plus sql注入及防止sql注入详解、MySQL 及 SQL 注入:防止SQL注入、Like语句中的注入的相关信息,请在本站查询。
本文标签: