Security 在Groovy/Grails中不安全地使用用户提供的GString:s

Security 在Groovy/Grails中不安全地使用用户提供的GString:s,security,grails,groovy,gstring,Security,Grails,Groovy,Gstring,Groovy中的GString概念非常强大(请参阅) GString允许您执行以下操作: world = "World" println "Hello ${world}" # Output: Hello World println "1+2 = ${1+2}" # Output: 1+2 = 3 println "${System.exit(-1)}" # Program terminated 我试图弄清楚使用Groovy GString:s是否会在代码中引入类似于SQL注入攻击的安全问题 在

Groovy中的GString概念非常强大(请参阅)

GString允许您执行以下操作:

world = "World"
println "Hello ${world}"
# Output: Hello World
println "1+2 = ${1+2}"
# Output: 1+2 = 3
println "${System.exit(-1)}"
# Program terminated
我试图弄清楚使用Groovy GString:s是否会在代码中引入类似于SQL注入攻击的安全问题

在上面的示例中,代码是由程序作者编写的,因此System.exit(-1)命令的执行不能被视为安全缺陷,因为这是作者声明的意图

假设我正在编写一个GrailsWeb应用程序,其中用户输入来自表单字段(读取POST/GET参数)和数据库表(使用GORM)。假设攻击者控制发送给服务器的POST/GET请求以及数据库中的内容

我的应用程序中的代码如下所示:

def str1 = params.someParameterControlledByTheAttacker
def str2 = SomeGORMPersistedObject.get(1).somePropertyFieldControlledByTheAttacker
render "Hello! Here is some text: ${str1} and ${str2}"
在上述场景中,攻击者是否有办法执行代码?为什么?为什么不呢?我最初的假设是GString的使用总是安全的。请随便证明我错了。请尽量具体

更新#1:为了保持讨论的重点,请忽略代码中的任何HTML-XSS问题,因为这个问题是关于服务器端而不是客户端的代码执行


更新#2:一些人指出“过滤掉不需要的字符串通常是个好主意”。虽然过滤掉“潜在的坏字符”可能会使您免于某些类别的安全问题,但编写即使没有过滤也安全的代码会更好。您可以将其与Java JDBC API中PreparedStatements的使用情况进行比较—PreparedStatements的正确使用可以保证避免某些类型的注入攻击。过滤SQL输入可能会得到相同的结果,但使用PreparedStatements严格控制着IMHO的过滤方法。

对于给定的代码示例,没有安全问题。str1和str2只是调用了它们的toString方法,并且gstring上的默认toString方法没有安全漏洞

除非您,程序的作者,已经为“由attacker控制的somePropertyField”定义了getter来实际评估值的内容,否则它是安全的


出现安全漏洞的唯一方法是程序作者添加一个安全漏洞

再想一想,您的使用似乎很好,因为您只需计算定义为变量的局部变量,但字符串仍然必须使用特殊字符,而不是像“System.exit(-1)”这样的字符,因为它会一直将其视为字符串,除非${}在字符串中围绕它

最好的做法似乎是从字符串中删除所有特殊字符,如“${}”,因为您不必在代码中使用这些字符就容易受到攻击。


但是,如果它从不以嵌套的方式求值字符串,那么就可以了,所以我不是100%确定。

我相当确定作为参数传入的对象(在控制器中)是纯字符串,因此它们不会在运行时得到求值(就像gstring那样)。此外,我做了一些实验,似乎要把这些变成GString,你需要做一些相当粗糙的工作。这是可行的,但需要很多技巧

简而言之,这可能不是一个安全漏洞


去掉特殊字符仍然是一个非常非常好的主意,至少在不需要它们的字符串中是这样。。。尽管这是“留给读者的练习”。但是,只要您意识到所有用户生成的数据(从web或DB中提取的数据)都是可疑的,您就会安全得多。

上述代码中可能存在跨站点脚本漏洞-请确保调用.encodeAsHTML(),否则坏人会捣乱您。

否,GString机制不会带来任何新问题,因为GString的形成是一种“编译时”现象。虽然可以在运行时确定(和更改)它们的值,但它们的形式不是


另一种看待它的方式:你可以用gstring做的任何事情都可以用闭包和字符串连接来完成,语义完全相同;gstring只是语法上的糖。除非您担心闭包(或者,但愿如此,字符串连接),否则您不应该担心gstring。

谢谢您的回答!你能举个例子说明“由攻击者控制的SomePropertyField”的不安全getter是什么样子的吗?我不确定我是否明白你回答的那一部分。显然,运行“evaluate(userInput)”是不安全的,但我想这不是你的意思。但是${}标记对字符串进行求值以获得一个对象,然后对其进行ToString,因此,无论它在ToString的过程中做什么都是极不安全的?我对答案感兴趣,乍一看,正如你所指出的,它看起来非常脆弱。这将需要一个测试,您可以更全面地模拟XSS攻击或无效输入攻击!您有一个观点,但是问题是关于服务器端的代码执行。我在问题中添加了一个更新,以使问题更清楚。无论是谁,为什么?据我所知,这是对这个问题的一个明确而正确的回答。