Skip to content

Instantly share code, notes, and snippets.

@kentatogashi
Last active March 23, 2018 07:53
Show Gist options
  • Save kentatogashi/451f34476ed57a241cbcae69afa43a05 to your computer and use it in GitHub Desktop.
Save kentatogashi/451f34476ed57a241cbcae69afa43a05 to your computer and use it in GitHub Desktop.
#!/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