Last active
March 23, 2018 07:53
-
-
Save kentatogashi/451f34476ed57a241cbcae69afa43a05 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/python | |
# coding: utf-8 | |
import sys | |
import os | |
import subprocess | |
LOG = '/home/webuser/scanner.log' | |
class Scanner: | |
def __init__(self, target): | |
self.threshold_cnt = 66 | |
self.target = target | |
self.keywords = ['base64_decode', 'eval', 'create_function', '$_POST'] | |
self.whitelist = ['ionCube Loader', 'Google+ embeds'] | |
self.debug_ = 1 | |
self.logged = False | |
self.is_suspect = False | |
self.logfile = LOG | |
self.log_fh = open(self.logfile, 'a') | |
def __call__(self): | |
pass | |
def run(self): | |
self.check_word_frequency() | |
if self.is_suspect: | |
self.check_keyword() | |
def check_word_frequency(self): | |
wtb = {} | |
is_include_pattern=False | |
with open(self.target) as f: | |
linenum = 0 | |
for line in f: | |
if linenum == 10: | |
break | |
line = line.rstrip() | |
if ('@include' in line) and ('.ico";' in line or '\\x69co";' in line \ | |
or 'i\\x63o";' in line or '\\x69c\\x6f";' in line or 'ic\\x6f";' in line ): | |
is_include_pattern=True | |
if any(list(map(lambda w: w in line, self.whitelist))): | |
break | |
if self.is_multibyte(line): | |
continue | |
for chr_ in line: | |
if chr_ == " ": continue | |
if not chr_ in wtb.keys(): | |
wtb[chr_] = 0 | |
else: | |
wtb[chr_] += 1 | |
linenum += 1 | |
if len(wtb) > self.threshold_cnt: | |
self.is_suspect = True | |
self.logger() | |
self.debug("SUSPICIOUS : %s has %d ascii characters" % (self.target, len(wtb))) | |
if is_include_pattern: | |
self.debug("SUSPICIOUS : %s matched include pattern" % self.target) | |
def check_keyword(self): | |
for keyword in self.keywords: | |
p = subprocess.Popen(['grep', '-q', keyword, self.target]) | |
p.communicate() | |
if p.returncode == 0: self.debug("SUSPICIOUS : %s has %s" % (self.target, keyword)) | |
def is_multibyte(self, string): | |
try: | |
for ch in string: | |
ch.encode('ascii', 'strict') | |
except UnicodeDecodeError: | |
return True | |
return False | |
def debug(self, message): | |
if self.debug_: | |
print(message) | |
def logger(self): | |
cmd1 = 'ls -lc {}'.format(self.target) | |
p1=subprocess.Popen(cmd1, stdout=subprocess.PIPE, shell=True) | |
out1, _ = p1.communicate() | |
cmd2 = 'head -10 {}'.format(self.target) | |
p2=subprocess.Popen(cmd2, stdout=subprocess.PIPE, shell=True) | |
out2, _ = p2.communicate() | |
self.log_fh.write("###START SCAN\n") | |
self.log_fh.write("###FILE\n") | |
self.log_fh.write("{}\n".format(self.target)) | |
self.log_fh.write("###STAT\n") | |
self.log_fh.write(out1.split("\n")[0] + "\n") | |
self.log_fh.write("###HEAD\n") | |
self.log_fh.write(out2 + "\n") | |
self.log_fh.write("###END SCAN\n") | |
self.log_fh.close() | |
self.logged = True | |
if __name__ == '__main__': | |
try: | |
if os.path.exists(LOG): | |
os.unlink(LOG) | |
for line in sys.stdin: | |
line = line.rstrip('\r\n') | |
scanner = Scanner(line) | |
scanner.run() | |
except: | |
print(sys.exc_info()) | |
quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment