-
Notifications
You must be signed in to change notification settings - Fork 1
Home
#Tasks WL = WhiteList BL = BlackList
Name | Description | Status | Link |
---|---|---|---|
testMethodInScript | Method in script WL/BL : a method defined in a script | DONE | testMethodInScript |
testMethodInsideMethod | Method inside another method WL/BL : imbrication of methods | DONE | testMethodInsideMethod |
testMethodAsArguments | Method as argument of another method WL/BL : Imbrication of methods | DONE | testMethodAsArguments |
testMethodAsARightBinaryExpression | Method within a Binary exp WL/BL like: a.add(new ArrayList().clear() + "") | DONE | testMethodAsARightBinaryExpression |
testMethodAsLeftBinaryExpression | Method within a Binary exp WL/BL like: a.add(new ArrayList().clear() + "") | DONE | testMethodAsLeftBinaryExpression |
testMethodDefinedInScript | Method defined within script but not in white list should not throw exception | DONE | testMethodDefinedInScript |
testClosureDefinedInScript | Closure within script but not in white list | TODO | testClosureDefinedInScript |
testStaticMethodDefinedInScript | Static method defined within script but not in white list should not throw exception | DONE | testStaticMethodDefinedInScript |
testStaticMethodInBlackList | Test we're going into StaticMethodCallExpression as Math.random goes through MethodCallExpression. This BL doesn't make any sense | DONE | testStaticMethodInBlackList |
testForNameSecurity | Test WL BL with different ways of instantiate an object @Newify, introspection | DONE | testForNameSecurity |
testForNameSecurityNewify | Test WL BL with different ways of instantiate an object @Newify, introspection | DONE | testForNameSecurityNewify |
testForNameSecurityFromInt | Test WL BL with different ways of instantiate an object @Newify, introspection | DONE | testForNameSecurityFromInt |
testMethodCallInClassDefinedInScript | Defined a class in script, within its method, BL/WL method call | DONE | testMethodCallInClassDefinedInScript |
testConstructorWithClassForName | Introspection, blacklist forName | TODO | testConstructorWithClassForName |
testConstructorWithClass ForNameComingFromAnotherClass | Introspection, blacklist forName where class comes from an obeject | TODO | testConstructorWithClass ForNameComingFromAnotherClass |
testSimpleConstructor | Introspection, blacklist forName where class comes from an obeject | DONE | testSimpleConstructor |
testConstructorWithNewify | Construction with annotation newify | TODO | testConstructorWithNewify |
testIfStatementForRuntime | Blacklist method call in if statement | DONE | testIfStatementForRuntime |
testReturnStatementForRuntime | Blacklist method call in return statement | DONE | testReturnStatementForRuntime |
testMethodCallAsString | Method call as a string | DONE | testMethodCallAsString |
testMethodInArrayInititalization | Method call in array initialization | DONE | testMethodInArrayInititalization |
testAlias | alias | DONE | testAlias |
testMethodChain | Chaining method call | #2 | testMethodChain |
testStaticImport | Method call with static import | DONE | testStaticImport |
testClassGetName | BL/WL getCLass() | On Going | testClassGetName |
testClassGetName2 | BL/WL getCLass().getName() | On Going | testClassGetName2 |
testPropertyDirectGet | Direct property get with @ | TODO | testPropertyDirectGet |
testPropertySet | Property set | TODO | testPropertySet |
testAttributeSet | Direct attribute set with @ | TODO | testAttributeSet |
testSpreadOperator | Spread operator | DONE | testSpreadOperator |
testArrayGet | Access array with bracket | TODO | testArrayGet |
testArraySet | Access array with bracket | TODO | testArraySet |
testInnerClass | BL WL method call within an inner Class | DONE | testInnerClass |
testStaticInitializationBlock | Static init block | DONE | testStaticInitializationBlock |
testInitializationBlock | Init block | DONE | testInitializationBlock |
testFieldInitialization | Inline initialization of attribute | DONE | testFieldInitialization |
testStaticFieldInitialization | Inline initialization of static attribute | DONE | testStaticFieldInitialization |
testNestedClass | Anonymous class | FABRICE | testNestedClass |
testCompoundAssignmentOnArray | intArray[1] <<= 3 (compound assignment) | TODO | testCompoundAssignmentOnArray |
testComparisonPrimitives | 7==7 | #3 | testComparisonPrimitives |
testComparisonObject | compare object | TODO | testComparisonObject |
testNullBehavior | Null?? | TODO | testNullBehavior |
list different class construction forNames @newify etc... | .. | TODO | .. |
groovyAccessControl | groovyAccessControl defines in all scripts classes, how to define it one time only | .. | .. |
Documentation | .. | TODO | .. |
CompileTime no specific test | Compile time method granularity: instead of having methodsWhiteList defined in SecureRuntimeASTCustomizer move it to its based class SecureASTCustomizer | Ongoing | branch compiletime |
Constant | Anything to do?? | TODO | .. |
Custom Checker | Let the user defines is own class to validate a method call. Extendable interface. | Ongoing | branch checker2 |
Constant | Anything to do?? | TODO | .. |
Hierarchy | BL like Object.toString() | TODO | .. |
setSource in all transformation | Take all 'DONE' test | DONE | .. |
Replace new ClassNode by ClassHelper.make | See Cedric workshop for best practise | DONE | .. |
#Design for the HackenGarten How to secure your Groovy script?
##Using SecureASTCustomizer at compile time ###What is it? When evaluating a script in Groovy you have the option to use AST to transform your script. You can do it using Customizer. As the name said it all, it allows you to customize your script. Among well know existing Customizer you may have used ImportCustomizer, etc.. To secure your script at compile time you can use SecureASTCustomizer as shown below:
import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.customizers.SecureASTCustomizer
def configuration = new CompilerConfiguration()
def customizer = new SecureASTCustomizer()
customizer.with {
setReceiversBlackList(["java.lang.System"])
}
configuration.addCompilationCustomizers(customizer)
new GroovyShell(configuration).evaluate('''
System.exit(-1)
''')
This will throw a SecurityException at compile time telling you that you are not authorised to use System.
###Limitations:
This has a huge limitation : Groovy is a dynamic language
import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.customizers.SecureASTCustomizer
def configuration = new CompilerConfiguration()
def customizer = new SecureASTCustomizer()
customizer.with {
setReceiversBlackList(["java.lang.System"])
}
configuration.addCompilationCustomizers(customizer)
new GroovyShell(configuration).evaluate('''
((Object)System).exit(-1)
''')
This will run and exit !
##Securing runtime solutions
There are already a few implementations that provide runtime security check either at skin level (only checking that a call inside your script is accepted) or deep level (checking that the call stack is accepted)
This ones involved Security Manager implementation for deep level security.
##What we want to add ###SecureRuntimeASTCustomizer
This solution is highly inspired from Groovy Sandbox and Simon's solution but will wrap the intercepted call inside a closure to be as Groovy as possible and will be forward compatible with evolution.
The existing solutions are great but they are too intrusive (especially on the Groovy way to invoke a method). The Groovy sandbox is the most advanced one but is also the most intrusive by trying to replicate call site caching mechanism and probably using class and method that could be modified or deleted in the future.
The solution we propose is to wrap the intercepted call within a closure. It has the advantage to be more compatible with call site, static typing or invoke dynamic.
Intercepting Groovy calls, however, have a performance impact on script execution. ###SecureRuntimeASTCustomizer with Checker module
A variant of the SecureRuntimeASTCustomizer (see checker2 branch) could be to let the user decide which Checker he wants to use or even better let him add as many Checkers he wants. In order to achieve this design, the challenge is how to inject those at compile time and use them at runtime.
This is the reason why we define 2 interfaces: Checker and MethodChecker (other will be implemented). GroovyAccessControl is responsible to create the Checker using the injectCheckerASTConstructor method using getConfigurationList from the interface.
At runtime, we wrap the expression within a groovyAccessControl.checkMethodCall(object, method, args, closure). GroovyAccessControl has a list of all checkers and call isAllowed on each of them.
#References