“This is the ninth day of my participation in the First Challenge 2022. For details: First Challenge 2022”
The Tidal open source version is made use of fOFA’s banner
First, tidal defines a CMS list of CMS_finger_list, which is the same as the data in the SQllite data table.
And then when the following thing, temporarily did not understand what is dry
self.W = '\033[0m'
self.G = '\033[1;32m'
self.R = '\033[1;31m'
self.O = '\033[1;33m'
self.B = '\033[1;34m'
Copy the code
And this tidal fingerprinting is based on THE HTTP protocol, rather than a host port scan. Although the current analysis of the code is I rewrite again, but basically nothing changed, now to analyze.
cms = Cmsscanner(target_url, self.request_timeout, self.pwd)
fofa_finger = cms.run()
Copy the code
Let’s see Cmsscanner
def __init__(self, *params) :
self.target, self.request_timeout, self.pwd = params
self.start = time.time()
self.finger = []
self.agent = {'UserAgent': 'the Mozilla / 5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))'}
self.rtitle = re.compile(r'title="(.*)"')
self.rheader = re.compile(r'header="(.*)"')
self.rbody = re.compile(r'body="(.*)"')
self.rbracket = re.compile(r'\((.*)\)')
Copy the code
The run method is called as follows
def run(self) :
try:
header, body, title = self.get_info()
for _id in range(1.int(self.count())):
try:
self.handle(_id, header, body, title)
except Exception as e:
pass
except Exception as e:
print(e)
finally:
return self.finger
Copy the code
It calls the git_info method, so let’s see what it does
def get_info(self) :
""" Get information on the Web. ""
try:
r = requests.get(url=self.target, headers=self.agent,
timeout=self.request_timeout, verify=False)
content = r.text
try:
title = BS(content, 'lxml').title.text.strip()
return str(r.headers), content, title.strip('\n')
except:
return str(r.headers), content, ' '
except Exception as e:
pass
Copy the code
Use the GET method to make a normal request to the target and get the result, mainly containing the content, title and response header. Then the run method iterates through each fingerprint in the database again for processing. Take a closer look at the Handle method
def handle(self, _id, header, body, title) :
""" Retrieve database key to match """ "
name, key = self.check(_id)
# a situation where only one condition is satisfied
if '| |' in key and '&' not in key and '(' not in key:
for rule in key.split('| |') :if self.check_rule(rule, header, body, title):
self.finger.append(name)
# print '%s[+] %s %s%s' % (G, self.target, name, W)
break
# Only one condition
elif '| |' not in key and '&' not in key and '(' not in key:
if self.check_rule(key, header, body, title):
self.finger.append(name)
# print '%s[+] %s %s%s' % (G, self.target, name, W)
# Condition where both conditions need to be met
elif '&' in key and '| |' not in key and '(' not in key:
num = 0
for rule in key.split('&') :if self.check_rule(rule, header, body, title):
num += 1
if num == len(key.split('&')):
self.finger.append(name)
# print '%s[+] %s %s%s' % (G, self.target, name, W)
else:
# and under the condition of existence and condition: 1 | | 2 | | (3 & 4)
if '&' in re.findall(self.rbracket, key)[0] :for rule in key.split('| |') :if '&' in rule:
num = 0
for _rule in rule.split('&') :if self.check_rule(_rule, header, body, title):
num += 1
if num == len(rule.split('&')):
self.finger.append(name)
# print '%s[+] %s %s%s' % (G, self.target, name, W)
break
else:
if self.check_rule(rule, header, body, title):
self.finger.append(name)
# print '%s[+] %s %s%s' % (G, self.target, name, W)
break
else:
And under the condition of existence and conditions: # 1 & 2 && (3 | | 4)
for rule in key.split('&'):
num = 0
if '| |' in rule:
for _rule in rule.split('| |') :if self.check_rule(_rule, title, body, header):
num += 1
break
else:
if self.check_rule(rule, title, body, header):
num += 1
if num == len(key.split('&')):
self.finger.append(name)
# print '%s[+] %s %s%s' % (G, self.target, name, W)
Copy the code
What about the check_rule function for each rule
def check_rule(self, key, header, body, title) :
""" fingerprint Identification """
try:
if 'title="' in key:
if re.findall(self.rtitle, key)[0].lower() in title.lower():
return True
elif 'body="' in key:
if re.findall(self.rbody, key)[0] in body: return True
else:
if re.findall(self.rheader, key)[0] in header: return True
except Exception as e:
pass
Copy the code
This essentially means looking for a regular expression rule in the title/header and body sections of the home page, and if so, finding one.