2014-09-24 2 views
6

मैं जावा में आम तौर पर पटकथा बहुत ग्रूवी के लिए नया हूँ, और, और मैं वास्तव में आशा वहाँ मेरी समस्या के लिए एक सरल उपाय है। हमारे आवेदन में, उपयोगकर्ताओं को ग्रूवी स्क्रिप्ट जो वे खुद को लिखने निष्पादित कर सकते हैं, और हम नियंत्रित करने के लिए उन स्क्रिप्ट और ऐसा नहीं कर सकते कर सकते हैं क्या जरूरत है। मैं ग्रूवी सैंडबॉक्सिंग के बारे में सामान का एक बहुत पढ़ा है, लेकिन या तो मैं गलत स्थानों से देख रहा हूँ या मैं स्पष्ट अनदेखी कर रहा हूँ। इसे आसान बनाने के लिए, मेरे पास एक छोटा सा उदाहरण है जो समस्या का प्रदर्शन करता है।जावा से ग्रोवी स्क्रिप्ट निष्पादित करते समय, कुछ वर्गों तक पहुंच को कैसे अवरुद्ध करें?

public class MyClassLoader extends ClassLoader { 

    @Override 
    public Class<?> loadClass(String name) throws ClassNotFoundException { 
     if (name.startsWith("java.lang.System")) { 
      throw new ClassNotFoundException("Class not found: " + name); 
     } 
     return super.loadClass(name); 
    } 
} 

और यह एक साधारण प्रोग्राम कॉल करने के लिए System.currentTimeMillis() की कोशिश करता है:

public static void main(String[] args) { 
    String code = "java.lang.System.currentTimeMillis();"; 
    ClassLoader classLoader = new MyClassLoader(); 
    Thread.currentThread().setContextClassLoader(classLoader); 

    GroovyShell shell = new GroovyShell(); 
    Script script = shell.parse(code); 
    Object result = script.run(); 
    log.debug(result); 
} 

MyClassLoaderjava.lang.SystemBeanInfo के लिए अपवाद फेंकता यह मेरी कक्षा लोडर जो भरी हुई और स्क्रिप्ट पर उपलब्ध होने से java.lang.System रोकने चाहिए है और java.lang.SystemCustomizer, लेकिन कोड निष्पादित करता है। अगर मैं javax.script कक्षाओं का उपयोग यही बात होता है:

ScriptEngineManager factory = new ScriptEngineManager(); 
ScriptEngine engine = factory.getEngineByName("Groovy"); 
Object o = engine.eval(code); 
log.debug(o); 

और अगर मैं JavaScript इंजन के साथ प्रयास करें, यह उम्मीद के रूप में ("JavaScript" ऊपर के उदाहरण में से सिर्फ "ग्रूवी" की जगह) काम करता है।

किसी को भी इस के साथ मेरी मदद कर सकते हैं? बीटीडब्ल्यू, मैं jdk1.7.0_55 के साथ groovy-all-1.8.8.jar का उपयोग कर रहा हूं।

धन्यवाद

+0

यह ग्रोवी v.2.3.6 और जावा 1.8.0_05 के साथ समान काम करता है। 'java.lang.System' को इस क्लासलोडर से भी लोड नहीं किया गया है। – Opal

+0

@Opal यह क्लासलोडर 'java.lang.SystemBeanInfo' और' java.lang.SystemCustomizer 'लोड करने का प्रयास करता है, जो मुझे लगता है, gavaovy' java.lang.System 'को लपेटने के लिए उपयोग करता है। लेकिन यह समझ में आता है कि एक और क्लासलोडर उपयोग में है, भले ही 'MyClassLoader' को पैरेंट क्लासलोडर न हो, मुझे नहीं पता कि यह कैसे काम करता है और उस व्यवहार को कैसे अनुकूलित किया जाए। –

उत्तर

3

मैं इस उद्देश्य के लिए Groovy Sandbox की सिफारिश कर सकता हूं। SecureASTCustomizer के विपरीत यह जांच करेगा कि रनटाइम पर गतिशील रूप से निष्पादन की अनुमति है या नहीं। यह प्रत्येक विधि कॉल, ऑब्जेक्ट आवंटन, संपत्ति/विशेषता पहुंच, सरणी पहुंच आदि को रोकता है - और इस प्रकार आप जो भी अनुमति देते हैं उस पर बहुत अच्छा अनाज नियंत्रण होता है (सफेद-सूची)।

स्वाभाविक रूप से अनुमति देने की अनुमति बहुत महत्वपूर्ण है। उदाहरण के लिए आप String एस का उपयोग करने और substring जैसे विधियों का उपयोग करने की अनुमति दे सकते हैं, लेकिन शायद पर विधि नहीं है, जिसका उपयोग 'rm -R ~/*'.execute() जैसे कुछ के साथ किया जा सकता है। एक कॉन्फ़िगरेशन बनाना जो वास्तव में सुरक्षित है एक चुनौती है, और जितना अधिक आप अनुमति देते हैं उतना ही मुश्किल है।

ग्रोवी सैंडबॉक्स के डाउनसाइड यह है कि कोड पंजीकृत इंटरसेप्टर के साथ चलाना चाहिए और आपके पास निष्पादन के दौरान प्रदर्शन दंड होगा।

यह छवि [1] एक परियोजना से एक उदाहरण दिखाती है जहां हमने उपयोगकर्ता द्वारा दर्ज ग्रोवी कोड के लिए ग्रोवी सैंडबॉक्स का उपयोग किया था।कोड स्क्रिप्ट Valide को चलाया जाता है - तो बयान वहाँ वास्तव में यह के भाग के रूप क्रियान्वित किया जा चाहते हैं, आवेदन करने से पहले मैं स्क्रीनशॉट कर सकता से बाहर निकल गया है |;)

Example from a project where we used Groovy Sandbox

+0

मैंने ग्रोवी सैंडबॉक्स के बारे में पढ़ा लेकिन कभी कोशिश नहीं की, मैं इसे देख लूंगा। हालांकि, जैसा कि मैंने एक अलग टिप्पणी में कहा था, हमारे पास पहले से ही एक कस्टम क्लासलोडर है जो हमारे द्वारा समर्थित अन्य स्क्रिप्ट इंजनों के लिए काम करता है, इसलिए पसंदीदा समाधान होगा यदि हम इसे ग्रोवी के लिए भी पुन: उपयोग कर सकते हैं। –

+1

हो सकता है कि आपके कस्टम क्लास लोडर की कॉन्फ़िगरेशन, जो कक्षाओं को अनुमति देता है/प्रतिबंधित करता है, को ग्रोवी सैंडबॉक्स कॉन्फ़िगरेशन के भीतर पुन: उपयोग किया जा सकता है। ग्रोवी को विशेष उपचार की आवश्यकता हो सकती है क्योंकि यह जेडीके कक्षाओं को अतिरिक्त कार्यक्षमता के साथ बढ़ाता है जो कक्षाओं पर सुरक्षा समस्याओं को उत्पन्न कर सकता है जावा में सुरक्षित होने की अनुमति है (String.execute केवल एक उदाहरण है) – stempler

+0

मैं सहमत हूं, मैं उसी पंक्ति के साथ सोच रहा था, कोड को पहले ही संशोधित कर रहा हूं। मेरे पास क्लास लोडर के साथ एक और प्रयोग है, और यदि यह विफल रहता है तो मैं इस जवाब को स्वीकार करूंगा। –

2

शायद आप एक CompilerConfiguration साथ संयोजन के रूप में एक SecureASTCustomizer उपयोग करने में रुचि होगी। यदि आप सुरक्षा से चिंतित हैं, तो एक काला सूची की तुलना में एक स्पष्ट सफेद सूची बेहतर हो सकती है।

def s = new SecureASTCustomizer() 
s.importsWhiteList = [ 'a.legal.Klass', 'other.legal.Klass' ] 

def c = new CompilerConfiguration() 
c.addCompilationCustomizers(s) 

def sh = new GroovyShell(c) 

उस कक्षा को देखें, इसमें बहुत सारे विकल्प हैं जो उपयोग करने के लिए तैयार हैं।

+0

यह निश्चित रूप से मदद करता है, लेकिन इसमें मेरी सभी ज़रूरतें शामिल नहीं हैं। उदाहरण के लिए, मैं 'java.lang.System' को उपरोक्त उदाहरण में 'आयात्स ब्लैकलिस्ट' और 'c.setIndirectImportCheckEnabled (true) 'का उपयोग करके उपयोग करने से रोक सकता हूं, लेकिन यह अभी भी काम करेगा: ' Class.forName ("जावा .lang.System ")। getMethod (" currentTimeMillis ", null) .invoke (null)'। एक और बात, हमारे पास पहले से ही हमारे कस्टम क्लासलोडर हैं जो अन्य स्क्रिप्ट इंजनों (जावास्क्रिप्ट और पायथन) का समर्थन करते हैं (और काम करता है), इसलिए मैं कस्टम क्लासलोडर का उपयोग करके इसे हासिल करना संभव होगा। –

+0

यहां एक सुराग है, अगर मैं इसे निष्पादित करता हूं: 'def cl = this.class.classLoader; def threadCl = Thread.currentThread()। ContextClassLoader; ' मुझे क्रमशः' groovy.lang.GroovyClassLoader' और 'my.package.MyClassLoader' मिलेगा। तो मुझे लगता है कि ग्रोवी क्लासलोडर सिस्टम क्लास लोड कर रहा है, मुझे नहीं पता कि मैं इसे कैसे और कैसे प्रभावित कर सकता हूं। –

+1

@PredragMaric अरे, मैं आपका बिंदु देखता हूं। दुर्भाग्य से मुझे ग्रोवी के क्लासलोडर्स (अभी तक) के बारे में बहुत कुछ पता नहीं है .. – emesx

0
import groovy.lang.GroovyClassLoader; 
import groovy.lang.GroovyShell; 
import groovy.lang.Script; 

public class SandboxGroovyClassLoader extends ClassLoader { 

public SandboxGroovyClassLoader(ClassLoader parent) { 
    super(parent); 
} 

@Override 
public Class<?> loadClass(String name) throws ClassNotFoundException { 
    if (name.startsWith("java.lang.System")) 
     return null; 
    return super.loadClass(name); 
} 

@Override 
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 
    if (name.startsWith("java.lang.System")) 
     return null; 
    return super.loadClass(name, resolve); 
} 

static void runWithGroovyClassLoader() throws Exception { 
    System.out.println("Begin runWithGroovyClassLoader"); 

    String code = "def hello_world() { java.lang.System.currentTimeMillis(); };"; 

    GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); 
    Class<?> scriptClass = groovyClassLoader.parseClass(code); 
    Object scriptInstance = scriptClass.newInstance(); 
    Object result = scriptClass.getDeclaredMethod("hello_world", new Class[] {}).invoke(scriptInstance, new Object[] {}); 
    System.out.println(result); 
    groovyClassLoader.close(); 
    System.out.println("End runWithGroovyClassLoader"); 
} 

static void runWithSandboxGroovyClassLoader() throws Exception { 
    System.out.println("Begin runWithSandboxGroovyClassLoader"); 
    ClassLoader parentClassLoader = SandboxGroovyClassLoader.class.getClassLoader(); 
    SandboxGroovyClassLoader classLoader = new SandboxGroovyClassLoader(parentClassLoader); 

    String code = "def hello_world() { java.lang.System.currentTimeMillis(); };"; 

    GroovyClassLoader groovyClassLoader = new GroovyClassLoader(classLoader); 
    Class<?> scriptClass = groovyClassLoader.parseClass(code); 
    Object scriptInstance = scriptClass.newInstance(); 
    Object result = scriptClass.getDeclaredMethod("hello_world", new Class[] {}).invoke(scriptInstance, new Object[] {}); 
    System.out.println(result); 
    groovyClassLoader.close(); 
    System.out.println("End runWithSandboxGroovyClassLoader"); 
} 

static void runWithSandboxGroovyShellClassLoader() throws Exception { 
    System.out.println("Begin runWithSandboxGroovyShellClassLoader"); 

    String code = "java.lang.System.currentTimeMillis();"; 

    ClassLoader parentClassLoader = SandboxGroovyClassLoader.class.getClassLoader(); 
    SandboxGroovyClassLoader classLoader = new SandboxGroovyClassLoader(parentClassLoader); 
    Thread.currentThread().setContextClassLoader(classLoader); 

    GroovyShell shell = new GroovyShell(); 
    Script script = shell.parse(code); 
    Object result = script.run(); 
    System.out.println(result); 
    System.out.println("End runWithSandboxGroovyShellClassLoader"); 
} 

public static void main(String[] args) throws Exception { 

    runWithGroovyClassLoader(); 
    runWithSandboxGroovyClassLoader(); 
    runWithSandboxGroovyShellClassLoader(); 

} 
} 

यह है आपको क्या चाहिए ?

संबंधित मुद्दे

 संबंधित मुद्दे