- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的应用程序有很多使用 Statement 编写的 JDBC 查询,因此容易受到 SQL 注入(inject)的攻击。不幸的是,这个应用程序是大约 10 年前开发的,开发人员可能不知道 Prepared statement。
我知道解决这个问题的最好方法是使用 PreparedStatement 但是在整个应用程序中转换它是非常繁琐的。此外,为 SQL 注入(inject)编写任何类型的 Patten 匹配都可能非常棘手,因为 Select、insert、union 等关键字都是英文单词,它们也可能出现在用户键入的文本字段中。
有没有更聪明的方法来避免 SQL 注入(inject)而不使用 Prepared 语句。如果这是一个重复的问题,请给我一个有很好答案的问题的链接。感谢您的帮助。
最佳答案
哈哈。不幸的是,它几乎总是取决于货币和管理决定什么是合适的,但“它非常乏味”通常不被认为是一个有效的工程问题——它只是适当重构代码的借口.
与此同时,该问题要求使用非 PreparedStatement 方法:简而言之,如果您无法将工作卸载到库中(例如准备好的语句),那么唯一的其他方法就是为每个“注入(inject)”项目自己完成。无论哪种方式,都必须执行检查输入的工作。唯一的问题是它在哪里完成,以及程序员的专业知识是什么制作了输入验证代码。
例如,考虑一个简单的 SELECT 语句:
sql = "SELECT * FROM mytable WHERE id = " + untrustedVar;
为了完整起见,我们可以假设注入(inject)示例,其中 untrustedVar
是一个类似 1 OR 1
或 1 的字符串; DROP TABLE mytable;
显然这会导致不需要的行为,相对于返回给调用者的所有行,或者现在丢失的数据库表:
SELECT * FROM mytable WHERE id = 1;
DROP mytable;
在这种情况下,您可以让语言语义至少确保 unstrustedVar
是一个整数,也许在您的函数定义中:
String[] selectRowById ( int untrustedVar ) { ...
或者,如果它是一个字符串,您可以使用如下正则表达式执行此操作:
Pattern valid_id_re = Pattern.compile('^\d{1,10}$'); // ensure id is between 1 and 10 billion
Matcher m = valid_id_re.matcher( unstrustedVar );
if ( ! m.matches() )
return null;
但是,如果您的输入较长且没有任何语法或结构保证(例如,网络表单文本区域),那么您将需要进行较低级别的字符替换以转义潜在的错误字符。根据声明。每个变量。每个数据库风格(PostgreSQL、Oracle、MySQL、SQLite 等)。这......是一 jar 蠕虫。
当然,如果您不使用准备好的语句,并且还没有人完成其他工作来避免对您的应用程序进行 SQL 注入(inject)攻击,那么您别无选择,只能向上走。
与此同时,我敦促,敦促,敦促您重新考虑您对“我们不能使用准备好的陈述,因为某些原因”的立场。更重要的是,正如戈德·汤普森 (Gord Thompson) 在下面的评论中正确指出的那样,“在任何情况下,这都将是一项相当大的工作量,那么为什么不把它做好并完成它呢?”
写完上面的内容后,我突然想到有些人可能会认为仅仅编写准备好的语句 = 更好的安全性。实际上,它是带有绑定(bind)参数的准备好的语句,可以提高安全性。例如,可以这样写:
String sql = "SELECT * FROM mytable WHERE id = " + untrustedVar;
PreparedStatment pstmt = dbh.prepareStatement( sql );
return pstmt.executeQuery();
此时,您所做的只不过是准备了一个已被注入(inject)恶意代码的语句。相反,请考虑参数的实际绑定(bind):
String sql = "SELECT * FROM mytable WHERE id = ?"; // Raw string; never touched by "tainted" variable
PreparedStatment pstmt = dbh.prepareStatement( sql );
pstmt.setObject(1, p); // Perform the actual binding.
return pstmt.executeQuery();
后一个例子做了两件事。它首先创建一个已知的安全格式,然后将那个 发送到数据库进行准备。然后,DB 返回准备语句的句柄后,我们是否绑定(bind)变量,最后执行语句。
关于jdbc - 在不使用 Prepared 语句的情况下摆脱 SQL 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47272504/
我已阅读有关依赖注入(inject)的信息。然后来了 构造函数注入(inject), setter/getter 注入(inject) 二传手注入(inject) 接口(interface)注入(in
我正在研究依赖注入(inject)模式。我看过很多例子,其中一个典型的例子是使用 XxxService/XxxRepository 作为例子。但是在我看来,按照UML的概念,类XxxRepositor
我开始使用 Google Guice。 我有一个简单的问题: javax.inject 的 @Inject 注释和 com.google.inject 的 有什么区别@Inject 一个 ? 谢谢。
当使用构造函数注入(inject)工厂方法时,依赖的属性不会得到解析。但是,如果在解析依赖的组件之前解析了工厂方法,则一切都会按预期工作。此外,当仅使用属性注入(inject)或构造函数注入(inje
我有这样的事情: class Root { public Root(IDependency dep) {} } class Dependency:IDependency { p
听完Clean Code Talks ,我开始明白我们应该使用工厂来组合对象。因此,例如,如果 House有一个 Door和 Door有一个 DoorKnob , 在 HouseFactory我们创建
情况:我需要在一些 FooClass 中进行惰性依赖实例化,所以我通过 Injector类作为构造函数参数。 private final Injector m_injector; public Foo
在编写代码时,我们应该能够识别两大类对象: 注入(inject)剂 新品 http://www.loosecouplings.com/2011/01/how-to-write-testable-cod
这个问题是关于 Unity Container 的,但我想它适用于任何依赖容器。 我有两个具有循环依赖关系的类: class FirstClass { [Dependency] pub
如果我有 10 个依赖项我需要注入(inject)并且不想在构造函数中有 10 个参数,我应该使用哪种注入(inject)模式? public class SomeClass { privat
我在使用 Angular2 DI 时遇到了问题。我尝试将一个类注入(inject)另一个类,它引发了以下错误: 留言:"Cannot resolve all parameters for 'Produ
对依赖注入(inject)还很陌生,我想弄清楚这是否是一种反模式。 假设我有 3 个程序集: Foo.Shared - this has all the interfaces Foo.Users -
我正在尝试了解 Angular 14 的变化,尤其是 inject()我可以将模块注入(inject)功能的功能,我不需要为此创建特殊服务..但我想我弄错了。 我正在尝试创建一些静态函数来使用包 ng
希望这个问题不是太愚蠢,我试图掌握更高级的编程原理,因此试图习惯使用 Ninject 进行依赖注入(inject)。 因此,我的模型分为几个不同的 .dll 项目。一个项目定义了模型规范(接口(int
我最近一直在大量使用依赖注入(inject)、测试驱动开发和单元测试,并且开始喜欢上它。 我在类中使用构造函数依赖,这样我就可以为单元测试注入(inject)模拟依赖。 但是,当您实际需要生产环境中的
我有下面的代码来使用 Guice 进行依赖注入(inject)。第一个是使用构造函数注入(inject),而另一个是直接在字段上方添加 @Inject。这两种方式有什么区别吗? Guice官网似乎推荐
这个问题在这里已经有了答案: Angular2 Beta dependency injection (3 个答案) 关闭 7 年前。 我正在使用 angular2 测试版。并在使用 @Inject
有没有可能做这样的事情? (因为我尝试过,但没有成功): @Injectable() class A { constructor(private http: Http){ // <-- Injec
我很恼火必须通过 Constructor 传递管道对象,因为我想为业务实体或要传递的值保留构造函数参数。 所以我想通过 setter ,但只要这些 setter 没有被填充,我的包含依赖项的对象就不应
假设我有这个: SomePage.razor: @inject Something something @page "/somepage" My Page @code { // Using
我是一名优秀的程序员,十分优秀!