CVE-2022-37298: Improper Authentication (CWE-287)
value: Shinken Solutions Shinken Monitoring Version 2.4.3 affected is vulnerable to Incorrect Access Control. The SafeUnpickler class found in shinken/safepickle.py implements a weak authentication scheme when unserializing objects passed from monitoring nodes to the Shinken monitoring server.
CWE description: When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.
CVSS v3 base score: 9.8
Published: 2022-10-20T11:15Z
Repository: https://github.com/naparuba/shinken
Language: Python
Files changed: Changelog, THANKS, setup.py, shinken/safepickle.py, test/test_safe_pickle.py
Commit date: 2022-02-03 11:42:24 +0100
Commit message: Fix: Dailymotion team (Nicolas Perraud) found a way to bypass pickle.loads protection and execute code from daemon if you can exchange with it's internal port. Now we whitelist allowed class only :)

Bonus: update the changelog, Thanks & setup.py so we can release soon :)

Diff: diff --git a/Changelog b/Changelog
index d4ffc3d5a..84d69e09f 100644
--- a/Changelog
+++ b/Changelog
@@ -1,18 +1,64 @@
 ########################
 Shinken ChangeLog
 ########################
 
 
-3.0.03 - X/X/2017
+2.4.4 - XX/02/2022
 -----------------
         CORE ENHANCEMENT
         Enh: (backport from Enterprise, internal ref #SEF-202) Big boost for the broker daemons, especially for very large setups and slow modules (yes Graphite, I'm looking at you).
         Enh: (backport from Enterprise ref:#SEF-103) Slight boost of startup time by remiving useless hash computation.
+        Enh: (Christophe Simon) Force problem/impact evaluation
+        Enh: (Christophe Simon) added strict object name conflict policy
+        Enh: (Christophe Simon) better objects balancing between schedulers (#1999)
+        Enh: (Christophe Simon) Maintenance checks (#1929)
+        Enh: (Nicolas DUPEUX) Add an option to dump configuration as build by shinken to a json file (#1954)
+        Enh: (Lionel Sausin) Add instructions to use --install-scripts in pip (#1890)
+        Enh: (Christophe Simon) extend duplicate_foreach to host/hostgroups (#1905)
+        Enh: (Christophe Simon) Made memory free an opt-in option
+        Enh: (Christophe Simon) Explicitly frees memory when receiving new conf
+        Enh: (Christophe Simon) Harmonized graceful restart
+        Enh: (David Durieux) Add support of proxy socks5 for shinken cli (#1583)
+        Enh: (Mateusz Korniak) Add info about exit error code when check finished with error/was signalled. (#1766)
 
         CORE FIXES
         Fix: (backport from Enterprise ref:#SEF-76) In some case, we can have "negative" value for downtime depth, and then the element will never exit from downtime.
+        Fix: Dailymotion team (Nicolas Perraud) found a way to bypass pickle.loads protection and execute code from daemon if you can exchange with it's internal port. Now we whitelist allowed class only :)
+        Fix: (Christophe Simon) Enforced downtime state after retention load
+        Fix: (V. D'AGOSTINO) Update about.rst to fix a typo
+        Fix: (Flavien Peyre) multiple notification way when using a contact template (#1867)
+        Fix: (Dani Rodríguez) Update typographic errors and explain things in the help messages (#1968)
+        Fix: (Dani Rodríguez) brok queues not producing broks (#1971)
+        Fix: (David Gil) Pin CherryPy dependpency < 9.0.0 (#1983)
+        Fix: (Vladimir Kazarin) Update dmz-monitoring.rst (#1980)
+        Fix: (Muhammad Zeeshan Qazi) #1961 : Replace #!/usr/bin/python to #!/usr/bin/python2 (#1979)
+        Fix: (Dani Rodríguez) Fixes calls to cProfile in shinken binaries (#1967)
+        Fix: (wilfriedroset) shinken typo (#1974)
+        Fix: (efficks) CherryPy >= 3 required (#1943)
+        Fix: (David Gil) osmatch in nmap discovery process (#1944)
+        Fix: (Konstantin Shalygin) modules_manager: ignore '.git' dir when load modules. (#1883)
+        Fix: (Christophe Simon) http_client exceptions management
+        Fix: (Christophe Simon) OSX (darwin) platform detection
+        Fix: (Christophe Simon) unicode string parisng in shinken cmdline
+        Fix: (Olivier Hanesse) missing ini file for shinken.io
+        Fix: (Olivier Hanesse) #1857 Set default value for proxy/proxy_socks5 for shinken cli
+        Fix: (Olivier Hanesse) #1845 Add missing paramter for statsd
+        Fix: (Nicolas Le Manchet) Improve systemd units reliability
+        Fix: (Frédéric MOHIER) Iterate correctly in the Services object (#1842)
+
+
+        MISC FIXES
+        Fix: (Yann 'Ze' Richard) missing email header to prevent "Out Of Office" messages (#2014)
+        Fix: (se4598*) #1951: Email notification in text mode (#1986)
+        Enh: (Arthur Lutz) starttls and username/password for SMTP
+        Fix: (George Shuklin) trace on sening smtp messages
+        Doc: (rdmo) than -> as
+        Doc: (dodofox) specify host inheritance for contact/contactgroup (#1872)
+        Doc: (Elliott Peay) Fix default reactionner port in docs
+        Fix: (Konstantin Shalygin) Encode attachment. (#1817)
+        Fix: (Marc Remy) Typo: Update some doc files. (#1821)
 
 
 2.4.3 - 10/03/2016
 -------------------
         CORE ENHANCEMENT
diff --git a/THANKS b/THANKS
index 03cc5c557..c71f81057 100644
--- a/THANKS
+++ b/THANKS
@@ -109,5 +109,6 @@ To Robin Gloster for his bug fix about bad wmi ini dir
 To Samuel Milette-Lacombe for his patch about core configuration export on broker
 To Mathieu Parent for his patch about Thruk doc
 To Aina Rakotoson for his bug report about reactionner_tag logic fail, and his patch to fix about it
 To jylenhofgfi for his bug report about shinken cli problems and | grep
 To Alexandre Viau for his patch about passive unmanaged host broks generation
+To Nicolas Perraud for his warn about a RCE in the daemon exchange
diff --git a/setup.py b/setup.py
index 375e27fe4..a46ec0ca4 100644
--- a/setup.py
+++ b/setup.py
@@ -409,11 +409,11 @@ for o in not_allowed_options:
         sys.argv.remove(o)
 
 required_pkgs = ['pycurl']
 setup(
     name="Shinken",
-    version="2.4.3",
+    version="2.4.4",
     packages=find_packages(),
     package_data={'': package_data},
     description="Shinken is a monitoring framework compatible with Nagios configuration and plugins",
     long_description=read('README.rst'),
     author="Gabes Jean",
diff --git a/shinken/safepickle.py b/shinken/safepickle.py
index c573fd1d7..3d088c6c5 100644
--- a/shinken/safepickle.py
+++ b/shinken/safepickle.py
@@ -24,33 +24,100 @@
 import sys
 import cPickle
 from cStringIO import StringIO
 
 
-
-# Unpickle but strip and remove all __reduce__ things
-# so we don't allow external code to be executed
+# Unpickle but strip and remove all __reduce__ things so we don't allow external code to be executed
 # Code from Graphite::carbon project
 class SafeUnpickler(object):
     PICKLE_SAFE = {
-        'copy_reg': set(['_reconstructor']),
-        '__builtin__': set(['object', 'set']),
+        'copy_reg'                                : set(['_reconstructor']),
+        '__builtin__'                             : set(['object', 'set']),
+        
+        # Be sure to white list all we need to pickle.loads so user cannot exploit other modules (like bottle ^^)
+        'shinken.acknowledge'                     : set(['Acknowledge']),
+        'shinken.basemodule'                      : set(['BaseModule']),
+        'shinken.borg'                            : set(['Borg']),
+        'shinken.check'                           : set(['Check']),
+        'shinken.brok'                            : set(['Brok']),
+        'shinken.commandcall'                     : set(['CommandCall']),
+        'shinken.comment'                         : set(['Comment']),
+        'shinken.complexexpression'               : set(['ComplexExpressionNode']),
+        'shinken.contactdowntime'                 : set(['ContactDowntime']),
+        'shinken.daterange'                       : set(['Timerange',
+                                                         'Daterange',
+                                                         'CalendarDaterange',
+                                                         'StandardDaterange',
+                                                         'MonthWeekDayDaterange',
+                                                         'MonthDateDaterange',
+                                                         'WeekDayDaterange',
+                                                         'MonthDayDaterange',
+                                                         ]),
+        'shinken.dependencynode'                  : set(['DependencyNode']),
+        'shinken.downtime'                        : set(['Downtime']),
+        'shinken.discovery.discoverymanager'      : set(['DiscoveredHost']),
+        'shinken.eventhandler'                    : set(['EventHandler']),
+        'shinken.external_command'                : set(['ExternalCommand']),
+        'shinken.graph'                           : set(['Graph']),
+        'shinken.message'                         : set(['Message']),
+        'shinken.modulesctx'                      : set(['ModulesContext']),
+        'shinken.modulesmanager'                  : set(['ModulesManager']),
+        'shinken.notification'                    : set(['Notification']),
+        'shinken.objects.command'                 : set(['DummyCommand', 'Command', 'Commands']),
+        'shinken.objects.arbiterlink'             : set(['ArbiterLink', 'ArbiterLinks']),
+        'shinken.objects.businessimpactmodulation': set(['Businessimpactmodulation', 'Businessimpactmodulations']),
+        'shinken.objects.brokerlink'              : set(['BrokerLink', 'BrokerLinks']),
+        'shinken.objects.checkmodulation'         : set(['CheckModulation', 'CheckModulations']),
+        'shinken.objects.config'                  : set(['Config']),
+        'shinken.objects.contact'                 : set(['Contact', 'Contacts']),
+        'shinken.objects.contactgroup'            : set(['Contactgroup', 'Contactgroups']),
+        'shinken.objects.discoveryrule'           : set(['Discoveryrule', 'Discoveryrules']),
+        'shinken.objects.discoveryrun'            : set(['Discoveryrun', 'Discoveryruns']),
+        'shinken.objects.escalation'              : set(['Escalation', 'Escalations']),
+        'shinken.objects.hostdependency'          : set(['Hostdependency', 'Hostdependencies']),
+        'shinken.objects.host'                    : set(['Host', 'Hosts']),
+        'shinken.objects.hostescalation'          : set(['Hostescalation', 'Hostescalations']),
+        'shinken.objects.itemgroup'               : set(['Itemgroup', 'Itemgroups']),
+        'shinken.objects.hostgroup'               : set(['Hostgroup', 'Hostgroups']),
+        'shinken.objects.hostextinfo'             : set(['HostExtInfo', 'HostsExtInfo']),
+        'shinken.objects.item'                    : set(['Item', 'Items']),
+        'shinken.objects.macromodulation'         : set(['MacroModulation', 'MacroModulations']),
+        'shinken.objects.matchingitem'            : set(['MatchingItem']),
+        'shinken.objects.pack'                    : set(['Pack', 'Packs']),
+        'shinken.objects.notificationway'         : set(['NotificationWay', 'NotificationWays']),
+        'shinken.objects.module'                  : set(['Module', 'Modules']),
+        'shinken.objects.pollerlink'              : set(['PollerLink', 'PollerLinks']),
+        'shinken.objects.reactionnerlink'         : set(['ReactionnerLink', 'ReactionnerLinks']),
+        'shinken.objects.realm'                   : set(['Realm', 'Realms']),
+        'shinken.objects.receiverlink'            : set(['ReceiverLink', 'ReceiverLinks']),
+        'shinken.objects.resultmodulation'        : set(['Resultmodulation', 'Resultmodulations']),
+        'shinken.objects.satellitelink'           : set(['SatelliteLink', 'SatelliteLinks']),
+        'shinken.objects.schedulingitem'          : set(['SchedulingItem']),
+        'shinken.objects.schedulerlink'           : set(['SchedulerLink', 'SchedulerLinks']),
+        'shinken.objects.service'                 : set(['Service', 'Services']),
+        'shinken.objects.servicedependency'       : set(['Servicedependency', 'Servicedependencies']),
+        'shinken.objects.serviceescalation'       : set(['Serviceescalation', 'Serviceescalations']),
+        'shinken.objects.serviceextinfo'          : set(['ServiceExtInfo', 'ServicesExtInfo']),
+        'shinken.objects.servicegroup'            : set(['Servicegroup', 'Servicegroups']),
+        'shinken.objects.timeperiod'              : set(['Timeperiod', 'Timeperiods']),
+        'shinken.objects.trigger'                 : set(['Trigger', 'Triggers']),
+        
     }
-
-
+    
+    
     @classmethod
     def find_class(cls, module, name):
-        if module not in cls.PICKLE_SAFE and not module.startswith('shinken.'):
+        if module not in cls.PICKLE_SAFE:
             raise ValueError('Attempting to unpickle unsafe module %s' % module)
         __import__(module)
         mod = sys.modules[module]
-        if not module.startswith('shinken.') and name not in cls.PICKLE_SAFE[module]:
+        if name not in cls.PICKLE_SAFE[module]:
             raise ValueError('Attempting to unpickle unsafe class %s/%s' %
                              (module, name))
         return getattr(mod, name)
-
-
+    
+    
     @classmethod
     def loads(cls, pickle_string):
         pickle_obj = cPickle.Unpickler(StringIO(pickle_string))
         pickle_obj.find_global = cls.find_class
         return pickle_obj.load()
diff --git a/test/test_safe_pickle.py b/test/test_safe_pickle.py
index fb9c4e5c1..8fd4c4d30 100644
--- a/test/test_safe_pickle.py
+++ b/test/test_safe_pickle.py
@@ -22,16 +22,19 @@
 # This file is used to test reading and processing of config files
 #
 
 
 import cPickle as pickle
+import sys
+
 from shinken_test import *
 
 from shinken.safepickle import SafeUnpickler
 
-
 should_not_change = False
+
+
 def fff(b):
     global should_not_change
     should_not_change = b
 
 
@@ -39,39 +42,100 @@ class SadPanda(object):
     def __reduce__(self):
         return (fff, (True,))
 
 
 class TestSafePickle(ShinkenTest):
-
+    
     def setUp(self):
         pass
-
-
+    
+    
     def launch_safe_pickle(self, buf):
         SafeUnpickler.loads(buf)
-        
-        
+    
+    
     def test_safe_pickle(self):
         global should_not_change
-
-        print "Creating payload"
+        
+        print("Creating payload")
         buf = pickle.dumps(SadPanda(), 0)
         should_not_change = False
-        print "Payload", buf
-        #self.assertEqual('HARD', host.state_type)
-        print "Now loading payload"
+        print("Payload", buf)
+        # self.assertEqual('HARD', host.state_type)
+        print("Now loading payload")
         pickle.loads(buf)
         print should_not_change
         self.assertTrue(should_not_change)
         
         # reset and try our fix
         should_not_change = False
-        #SafeUnpickler.loads(buf)
+        
+        
+        # SafeUnpickler.loads(buf)
         def launch_safe_pickle():
             SafeUnpickler.loads(buf)
+        
+        
         self.assertRaises(ValueError, launch_safe_pickle)
-        print should_not_change
+        print (should_not_change)
         self.assertFalse(should_not_change)
+    
+    
+    # Thanks to security team @Dailymotion, we did have a RCE that ook like a return into libc
+    # exploit: they are using the bottle._load code (that blindly __import__) so the injected
+    # code will finally be executed. And as it's shinken.webui.bottle, it's ok with the
+    # safe_pickle filter. Smart ^^
+    def test_safe_pickle_exploit_rce(self):
+        ###### Phase 1: can be exploited
+        # Arrange
+        rce_path = '/rce_exploited'
+        if rce_path in sys.path:
+            sys.path.remove(rce_path)
+        
+        payload = b"""cshinken.webui.bottlewebui
+_load
+(S'sys:path.append("%s")'
+tR.""" % rce_path
+        
+        # Act
+        print("Now loading payload")
+        pickle.loads(payload)
+        
+        # Assert
+        self.assertTrue(rce_path in sys.path)
+        
+        ##### Phase 2: no more exploitable by calling the good one
+        # Arrange
+        sys.path.remove(rce_path)
+        
+        
+        # SafeUnpickler.loads(buf)
+        def launch_safe_pickle():
+            SafeUnpickler.loads(payload)
         
         
+        # Act
+        self.assertRaises(ValueError, launch_safe_pickle)
+        
+        # Assert
+        self.assertTrue(rce_path not in sys.path)
+    
+    
+    # Thanks to security team @Dailymotion, we did have a RCE that ook like a return into libc
+    # exploit: they are using the bottle._load code (that blindly __import__) so the injected
+    # code will finally be executed. And as it's shinken.webui.bottle, it's ok with the
+    # safe_pickle filter. Smart ^^
+    def test_safe_pickle_exploit_rce_can_load(self):
+        ###### Phase 1: can be exploited
+        # Arrange
+        
+        payload = pickle.dumps(Brok('void', {}))
+        
+        # Act
+        b = SafeUnpickler.loads(payload)
+        
+        # Assert
+        self.assertTrue(isinstance(b, Brok))
+
+
 if __name__ == '__main__':
     unittest.main()

Vulnerable code: 3.0.03 - X/X/2017
    version="2.4.3",

# Unpickle but strip and remove all __reduce__ things
# so we don't allow external code to be executed
        'copy_reg': set(['_reconstructor']),
        '__builtin__': set(['object', 'set']),


        if module not in cls.PICKLE_SAFE and not module.startswith('shinken.'):
        if not module.startswith('shinken.') and name not in cls.PICKLE_SAFE[module]:






        
        

        print "Creating payload"
        print "Payload", buf
        #self.assertEqual('HARD', host.state_type)
        print "Now loading payload"
        #SafeUnpickler.loads(buf)
        print should_not_change
Fixed code: 2.4.4 - XX/02/2022
        Enh: (Christophe Simon) Force problem/impact evaluation
        Enh: (Christophe Simon) added strict object name conflict policy
        Enh: (Christophe Simon) better objects balancing between schedulers (#1999)
        Enh: (Christophe Simon) Maintenance checks (#1929)
        Enh: (Nicolas DUPEUX) Add an option to dump configuration as build by shinken to a json file (#1954)
        Enh: (Lionel Sausin) Add instructions to use --install-scripts in pip (#1890)
        Enh: (Christophe Simon) extend duplicate_foreach to host/hostgroups (#1905)
        Enh: (Christophe Simon) Made memory free an opt-in option
        Enh: (Christophe Simon) Explicitly frees memory when receiving new conf
        Enh: (Christophe Simon) Harmonized graceful restart
        Enh: (David Durieux) Add support of proxy socks5 for shinken cli (#1583)
        Enh: (Mateusz Korniak) Add info about exit error code when check finished with error/was signalled. (#1766)
        Fix: Dailymotion team (Nicolas Perraud) found a way to bypass pickle.loads protection and execute code from daemon if you can exchange with it's internal port. Now we whitelist allowed class only :)
        Fix: (Christophe Simon) Enforced downtime state after retention load
        Fix: (V. D'AGOSTINO) Update about.rst to fix a typo
        Fix: (Flavien Peyre) multiple notification way when using a contact template (#1867)
        Fix: (Dani Rodríguez) Update typographic errors and explain things in the help messages (#1968)
        Fix: (Dani Rodríguez) brok queues not producing broks (#1971)
        Fix: (David Gil) Pin CherryPy dependpency < 9.0.0 (#1983)
        Fix: (Vladimir Kazarin) Update dmz-monitoring.rst (#1980)
        Fix: (Muhammad Zeeshan Qazi) #1961 : Replace #!/usr/bin/python to #!/usr/bin/python2 (#1979)
        Fix: (Dani Rodríguez) Fixes calls to cProfile in shinken binaries (#1967)
        Fix: (wilfriedroset) shinken typo (#1974)
        Fix: (efficks) CherryPy >= 3 required (#1943)
        Fix: (David Gil) osmatch in nmap discovery process (#1944)
        Fix: (Konstantin Shalygin) modules_manager: ignore '.git' dir when load modules. (#1883)
        Fix: (Christophe Simon) http_client exceptions management
        Fix: (Christophe Simon) OSX (darwin) platform detection
        Fix: (Christophe Simon) unicode string parisng in shinken cmdline
        Fix: (Olivier Hanesse) missing ini file for shinken.io
        Fix: (Olivier Hanesse) #1857 Set default value for proxy/proxy_socks5 for shinken cli
        Fix: (Olivier Hanesse) #1845 Add missing paramter for statsd
        Fix: (Nicolas Le Manchet) Improve systemd units reliability
        Fix: (Frédéric MOHIER) Iterate correctly in the Services object (#1842)


        MISC FIXES
        Fix: (Yann 'Ze' Richard) missing email header to prevent "Out Of Office" messages (#2014)
        Fix: (se4598*) #1951: Email notification in text mode (#1986)
        Enh: (Arthur Lutz) starttls and username/password for SMTP
        Fix: (George Shuklin) trace on sening smtp messages
        Doc: (rdmo) than -> as
        Doc: (dodofox) specify host inheritance for contact/contactgroup (#1872)
        Doc: (Elliott Peay) Fix default reactionner port in docs
        Fix: (Konstantin Shalygin) Encode attachment. (#1817)
        Fix: (Marc Remy) Typo: Update some doc files. (#1821)
To Nicolas Perraud for his warn about a RCE in the daemon exchange
    version="2.4.4",
# Unpickle but strip and remove all __reduce__ things so we don't allow external code to be executed
        'copy_reg'                                : set(['_reconstructor']),
        '__builtin__'                             : set(['object', 'set']),
        
        # Be sure to white list all we need to pickle.loads so user cannot exploit other modules (like bottle ^^)
        'shinken.acknowledge'                     : set(['Acknowledge']),
        'shinken.basemodule'                      : set(['BaseModule']),
        'shinken.borg'                            : set(['Borg']),
        'shinken.check'                           : set(['Check']),
        'shinken.brok'                            : set(['Brok']),
        'shinken.commandcall'                     : set(['CommandCall']),
        'shinken.comment'                         : set(['Comment']),
        'shinken.complexexpression'               : set(['ComplexExpressionNode']),
        'shinken.contactdowntime'                 : set(['ContactDowntime']),
        'shinken.daterange'                       : set(['Timerange',
                                                         'Daterange',
                                                         'CalendarDaterange',
                                                         'StandardDaterange',
                                                         'MonthWeekDayDaterange',
                                                         'MonthDateDaterange',
                                                         'WeekDayDaterange',
                                                         'MonthDayDaterange',
                                                         ]),
        'shinken.dependencynode'                  : set(['DependencyNode']),
        'shinken.downtime'                        : set(['Downtime']),
        'shinken.discovery.discoverymanager'      : set(['DiscoveredHost']),
        'shinken.eventhandler'                    : set(['EventHandler']),
        'shinken.external_command'                : set(['ExternalCommand']),
        'shinken.graph'                           : set(['Graph']),
        'shinken.message'                         : set(['Message']),
        'shinken.modulesctx'                      : set(['ModulesContext']),
        'shinken.modulesmanager'                  : set(['ModulesManager']),
        'shinken.notification'                    : set(['Notification']),
        'shinken.objects.command'                 : set(['DummyCommand', 'Command', 'Commands']),
        'shinken.objects.arbiterlink'             : set(['ArbiterLink', 'ArbiterLinks']),
        'shinken.objects.businessimpactmodulation': set(['Businessimpactmodulation', 'Businessimpactmodulations']),
        'shinken.objects.brokerlink'              : set(['BrokerLink', 'BrokerLinks']),
        'shinken.objects.checkmodulation'         : set(['CheckModulation', 'CheckModulations']),
        'shinken.objects.config'                  : set(['Config']),
        'shinken.objects.contact'                 : set(['Contact', 'Contacts']),
        'shinken.objects.contactgroup'            : set(['Contactgroup', 'Contactgroups']),
        'shinken.objects.discoveryrule'           : set(['Discoveryrule', 'Discoveryrules']),
        'shinken.objects.discoveryrun'            : set(['Discoveryrun', 'Discoveryruns']),
        'shinken.objects.escalation'              : set(['Escalation', 'Escalations']),
        'shinken.objects.hostdependency'          : set(['Hostdependency', 'Hostdependencies']),
        'shinken.objects.host'                    : set(['Host', 'Hosts']),
        'shinken.objects.hostescalation'          : set(['Hostescalation', 'Hostescalations']),
        'shinken.objects.itemgroup'               : set(['Itemgroup', 'Itemgroups']),
        'shinken.objects.hostgroup'               : set(['Hostgroup', 'Hostgroups']),
        'shinken.objects.hostextinfo'             : set(['HostExtInfo', 'HostsExtInfo']),
        'shinken.objects.item'                    : set(['Item', 'Items']),
        'shinken.objects.macromodulation'         : set(['MacroModulation', 'MacroModulations']),
        'shinken.objects.matchingitem'            : set(['MatchingItem']),
        'shinken.objects.pack'                    : set(['Pack', 'Packs']),
        'shinken.objects.notificationway'         : set(['NotificationWay', 'NotificationWays']),
        'shinken.objects.module'                  : set(['Module', 'Modules']),
        'shinken.objects.pollerlink'              : set(['PollerLink', 'PollerLinks']),
        'shinken.objects.reactionnerlink'         : set(['ReactionnerLink', 'ReactionnerLinks']),
        'shinken.objects.realm'                   : set(['Realm', 'Realms']),
        'shinken.objects.receiverlink'            : set(['ReceiverLink', 'ReceiverLinks']),
        'shinken.objects.resultmodulation'        : set(['Resultmodulation', 'Resultmodulations']),
        'shinken.objects.satellitelink'           : set(['SatelliteLink', 'SatelliteLinks']),
        'shinken.objects.schedulingitem'          : set(['SchedulingItem']),
        'shinken.objects.schedulerlink'           : set(['SchedulerLink', 'SchedulerLinks']),
        'shinken.objects.service'                 : set(['Service', 'Services']),
        'shinken.objects.servicedependency'       : set(['Servicedependency', 'Servicedependencies']),
        'shinken.objects.serviceescalation'       : set(['Serviceescalation', 'Serviceescalations']),
        'shinken.objects.serviceextinfo'          : set(['ServiceExtInfo', 'ServicesExtInfo']),
        'shinken.objects.servicegroup'            : set(['Servicegroup', 'Servicegroups']),
        'shinken.objects.timeperiod'              : set(['Timeperiod', 'Timeperiods']),
        'shinken.objects.trigger'                 : set(['Trigger', 'Triggers']),
        
    
    
        if module not in cls.PICKLE_SAFE:
        if name not in cls.PICKLE_SAFE[module]:
    
    
import sys



    
    
    
    
    
        
        print("Creating payload")
        print("Payload", buf)
        # self.assertEqual('HARD', host.state_type)
        print("Now loading payload")
        
        
        # SafeUnpickler.loads(buf)
        
        
        print (should_not_change)
    
    
    # Thanks to security team @Dailymotion, we did have a RCE that ook like a return into libc
    # exploit: they are using the bottle._load code (that blindly __import__) so the injected
    # code will finally be executed. And as it's shinken.webui.bottle, it's ok with the
    # safe_pickle filter. Smart ^^
    def test_safe_pickle_exploit_rce(self):
        ###### Phase 1: can be exploited
        # Arrange
        rce_path = '/rce_exploited'
        if rce_path in sys.path:
            sys.path.remove(rce_path)
        
        payload = b"""cshinken.webui.bottlewebui
_load
(S'sys:path.append("%s")'
tR.""" % rce_path
        
        # Act
        print("Now loading payload")
        pickle.loads(payload)
        
        # Assert
        self.assertTrue(rce_path in sys.path)
        
        ##### Phase 2: no more exploitable by calling the good one
        # Arrange
        sys.path.remove(rce_path)
        
        
        # SafeUnpickler.loads(buf)
        def launch_safe_pickle():
            SafeUnpickler.loads(payload)
        # Act
        self.assertRaises(ValueError, launch_safe_pickle)
        
        # Assert
        self.assertTrue(rce_path not in sys.path)
    
    
    # Thanks to security team @Dailymotion, we did have a RCE that ook like a return into libc
    # exploit: they are using the bottle._load code (that blindly __import__) so the injected
    # code will finally be executed. And as it's shinken.webui.bottle, it's ok with the
    # safe_pickle filter. Smart ^^
    def test_safe_pickle_exploit_rce_can_load(self):
        ###### Phase 1: can be exploited
        # Arrange
        
        payload = pickle.dumps(Brok('void', {}))
        
        # Act
        b = SafeUnpickler.loads(payload)
        
        # Assert
        self.assertTrue(isinstance(b, Brok))