Skip to content

Commit

Permalink
Search-Vulns, Vulners, CPEGuess
Browse files Browse the repository at this point in the history
  • Loading branch information
lmsecure committed Sep 27, 2024
1 parent c71318d commit 7793e9c
Show file tree
Hide file tree
Showing 50 changed files with 1,812 additions and 914 deletions.
2 changes: 1 addition & 1 deletion debian/changelog
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
setezor (0.8.0b) kali-dev; urgency=medium
setezor (0.9.0b) kali-dev; urgency=medium

* Initial release

Expand Down
1 change: 1 addition & 0 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Build-Depends:
debhelper-compat (= 13),
dh-python,
dh-virtualenv (>=1.0),
git,
python3-all,
python3-venv,
python3-requests,
Expand Down
4 changes: 3 additions & 1 deletion setezor/app_routes/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .port import PortView
from .project import ProjectView
from .screenshot import ScreenshotView
from .pivot import PivotView
from .pivot import PivotView, PivotIPMacPort,PivotDomainIP,PivotSoftwareVulnerabilityLink
from .task import TaskView
from .report import ReportsView
from .websocket import WebSocketView
Expand All @@ -16,6 +16,8 @@
from .agent import AgentView
from .route import RouteView
from .acunetix.acunetix import AcunetixView
from .vulnerability import VulnerabilityView


from aiohttp.web import UrlDispatcher

Expand Down
3 changes: 1 addition & 2 deletions setezor/app_routes/api/base_web_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,7 @@ async def get_all(self, request: PMRequest) -> Response:
res = db_entity.get_all(page=page, limit=size, sort_by=sort_by, direction=direction, filters=filters)

res = [{k: v for k,v in i.items()} for i in res]
total = db_entity.get_records_count()
res = orjson.dumps({'data': res, 'last_page': int(total / size) + 1})
res = orjson.dumps(res)
return Response(body=res)

async def get_db_queries(self, request: PMRequest) -> BaseQueries:
Expand Down
15 changes: 14 additions & 1 deletion setezor/app_routes/api/pivot.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,17 @@ async def get_node_info(self, request: PMRequest):
node_id = request.rel_url.query.get('ip_id')
db = await get_db_by_session(request=request)
data = db.pivot.get_info_about_node(ip_id=node_id)
return json_response(status=200, data=data)
return json_response(status=200, data=data)


class PivotIPMacPort(BaseView):
endpoint='/pivot_ip_mac_port'
queries_path = 'pivot_ip_mac_port'

class PivotDomainIP(BaseView):
endpoint='/pivot_domain_ip'
queries_path = 'pivot_domain_ip'

class PivotSoftwareVulnerabilityLink(BaseView):
endpoint='/pivot_software_vulnerability_link'
queries_path = 'pivot_software_vulnerability_link'
1 change: 1 addition & 0 deletions setezor/app_routes/api/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ async def create(self, request: PMRequest) -> Response:
db_agent = db.agent.create(agent=project.configs.variables.default_agent)
project.configs.variables.default_interface = default_system_iface.model_dump()
project.configs.variables.default_agent.id = db_agent.id
project.configs.variables.search_vulns_token = ""
project.configs.variables.default_agent = project.configs.variables.default_agent.model_dump()
project.configs.save_config_file()
except Exception as e:
Expand Down
9 changes: 4 additions & 5 deletions setezor/app_routes/api/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@ async def download_csv_report(self, request: PMRequest) -> Response:
db = await get_db_by_session(request=request)
query = request.rel_url.query
filters: dict = json.loads(query.get('filters'))
rows = db.port.get_all(filters=filters, result_format=None)
ses = db.port.session_maker()
rows = db.pivot.get_all(filters=filters, result_format=None)
file = StringIO()
writer = csv.writer(file)
writer.writerow(['id', 'ip', 'port'])
if rows:
writer.writerow(rows[0].keys())
for row in rows:
ses.add(row)
writer.writerow([row.id, row._ip.ip, row.port])
writer.writerow(row.values())
return Response(body=file.getvalue(), headers= {
'Content-Type': 'text/csv; charset=UTF-8',
'CONTENT-DISPOSITION': 'attachment;filename=ip_port.csv'
Expand Down
72 changes: 72 additions & 0 deletions setezor/app_routes/api/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@
from setezor.tasks.whois_task import WhoisTask
from setezor.tasks.cert_task import CertInfoTask
from setezor.tasks.wappalyzer_task import Wappalyzer
from setezor.tasks.cve_refresh_task import CVERefresher
from setezor.tasks.cve_task import Cve

from setezor.tasks.screenshot_by_ip_task import ScreenshotFromIPTask
from setezor.tasks.task_status import TaskStatus
from setezor.app_routes.api.base_web_view import BaseView
from setezor.modules.application import PMRequest
from setezor.modules.project_manager.manager import ProjectManager
from setezor.tools.ip_tools import get_ipv4, get_mac
from sqlalchemy import desc
import datetime

class TaskView(BaseView):
endpoint = '/task'
Expand Down Expand Up @@ -278,4 +282,72 @@ async def create_wappalyzer_task(self, request: PMRequest):
await scheduler.spawn_job(Wappalyzer(observer=project.observer, scheduler=scheduler, name=f'Task {task_id}',
task_id=task_id, db=db, data=json_file, groups=groups))
return Response(status=201)


@BaseView.route('POST', '/cve_task')
@project_require
async def create_cve_task(self, request: PMRequest):
project = await get_project(request=request)
source = 'vulners'
db = project.db
session = db.db.create_session()
list_soft_obj = session.query(db.software.model).where(db.software.model.cpe23 != None).all()
for soft_obj in list_soft_obj:
list_cpe = (soft_obj.cpe23 or '').split(', ')
for cpe in list_cpe:
if cpe[:7] == "cpe:2.3":
params = json.dumps({'source' : source, 'cpe' : cpe}, ensure_ascii=False)
task = session.query(db.task.model).filter(db.task.model.params == json.dumps(params),
db.task.model.status == "FINISHED")\
.order_by(desc(db.task.model.started)).first()
if task:
val = datetime.datetime.now() - task.started
if val.seconds < 3600: # проверка, что для данного cpe23 повторный запуск был не раньше часа
await notify_client(request=request, queue_type='message',
message={'title': f'Warning', 'type': 'warning',
'text': f'Retry after {(3600 - val.seconds) // 60 + 1} minutes. cpe = {cpe}'})
continue
task_id = db.task.write(status=TaskStatus.in_queue, params=params, ret='id')
scheduler = project.schedulers.get('cve_vulners')
await scheduler.spawn_job(Cve(observer=project.observer, scheduler=scheduler, name=f'Task {task_id}', db=db,
task_id=task_id, log_path=project.configs.folders.cve_logs, cpe=cpe, source=source, list_res_id=[obj.id for obj in soft_obj._resource]))
return Response(status=201)


@BaseView.route('POST','/refresh_cve')
@project_require
async def refresh_cve_task(self, request: PMRequest):
project = await get_project(request=request)
if not (token := project.configs.variables.search_vulns_token):
return json_response(status=500)
db = project.db
scheduler = project.schedulers.get('search-vulns')
session = db.db.create_session()
softwares = session.query(db.software.model).filter(db.software.model.cpe23 != None).all()

for soft in softwares:
cpe_list = soft.cpe23.split(", ")
for cpe23 in cpe_list:
params = json.dumps({"source":"search-vulns","cpe":cpe23}, ensure_ascii=False)
task = session.query(db.task.model).filter(db.task.model.params == json.dumps(params),
db.task.model.status == "FINISHED")\
.order_by(desc(db.task.model.started)).first()
if task:
val = datetime.datetime.now() - task.started
if val.seconds < 3600: # проверка, что для данного cpe23 повторный запуск был не раньше часа
await notify_client(request=request, queue_type='message',
message={'title': f'Warning', 'type': 'warning',
'text': f'Retry after {(3600 - val.seconds) // 60 + 1} minutes. cpe = {cpe23}'})
continue
resource_softwares = [obj.id for obj in soft._resource]
if not resource_softwares:
await notify_client(request=request, queue_type='message',
message={'title': f'Error"', 'type': 'error',
'text': f'No resources found for cpe="{cpe23}'})
continue
task_id = db.task.write(status=TaskStatus.in_queue, params=params, ret='id')
await scheduler.spawn_job(CVERefresher(observer=project.observer,scheduler=scheduler,
name=f'Task {task_id}',task_id=task_id,
db=db,token=token,cpe23=cpe23,res_softs_ids = resource_softwares))
return Response(status=201)

73 changes: 73 additions & 0 deletions setezor/app_routes/api/vulnerability.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from aiohttp.web import Request, Response, json_response
from setezor.app_routes.session import project_require, get_db_by_session, get_project
from setezor.app_routes.api.base_web_view import BaseView
from setezor.modules.application import PMRequest
from setezor.modules.search_vulns.search_vulns import SearchVulns
try:
from cpeguess.cpeguess import CPEGuess
except:
pass

class VulnerabilityView(BaseView):
endpoint = '/vulnerability'
queries_path = 'vulnerability'

@BaseView.route('GET', '/cpe/')
@project_require
async def get_cpe_by_name_and_version(self, request: PMRequest) -> Response:
"""Метод получения cpe по product/vendor + version
Args:
request (Request): объект http запроса
Returns:
Response: json ответ
"""
query = request.query
product, vendor, version, exact = query.get("product", ""), \
query.get("vendor", ""), \
query.get("version", ""), \
query.get("mode","off") == "on"
guesser = CPEGuess.search(
product=product, vendor=vendor, version=version, exact=exact)
return json_response(status=200, data=guesser)

@BaseView.route('PUT', '/search_vulns/token/')
@project_require
async def set_search_vulns_token(self, request: PMRequest) -> Response:
project = await get_project(request=request)
payload = await request.json()
new_token = payload.get("token")
if not (await SearchVulns.check_token(token=new_token)):
return json_response(status=500, data={"error": "Invalid token"})
project.configs.variables.search_vulns_token = new_token
project.configs.save_config_file()
return json_response(status=200)

@BaseView.route('GET', '/search_vulns/')
@project_require
async def search_vulns(self, request: PMRequest) -> Response:
"""Метод получения cpe по product/vendor + version
Args:
request (Request): объект http запроса
Returns:
Response: json ответ
"""
project = await get_project(request=request)
query = request.query
query_string = query["query"]
if not (token := project.configs.variables.search_vulns_token):
return json_response(status=500, data={"error": "No token provided"})
result = await SearchVulns.find(token=token, query_string=query_string)

for k in result.keys():
data = result.get(k, [])
vulns = data.get("vulns")
result_vulns = dict()
for key in vulns.keys():
if vulns[key].get("exploits"):
result_vulns.update({key: vulns[key]})
data["vulns"] = result_vulns
return json_response(status=200, data=result)
17 changes: 11 additions & 6 deletions setezor/app_routes/pages/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

info_routes = RouteTableDef()


@info_routes.get('/info/')
@project_require
async def info_page(request: PMRequest) -> Response:
Expand All @@ -18,15 +19,19 @@ async def info_page(request: PMRequest) -> Response:
Returns:
Response: отрендеренный шаблон страницы
"""
"""
db = await get_db_by_session(request)
project = await get_project(request=request)
project_name = project.configs.variables.project_name
project_id = project.configs.variables.project_id
context = {'tabs': [{'name': i.model.__name__.lower(),
context = {'tabs': [{'name': i.model.get_name().lower(),
'base_url': f'/api/{i.model.__name__.lower()}',
'columns': i.model.get_headers_for_table()} for i in [db.object, db.ip, db.mac, db.port, db.task, db.pivot]], #! Добавить db.network как будет готово
'current_project': project_name, 'current_project_id': project_id,
'interfaces': [i for i in get_interfaces() if i.ip_address]}

# ! Добавить db.network как будет готово
'columns': i.model.get_headers_for_table()} for i in [db.ip, db.mac, db.port, db.task,
db.pivot, db.pivot_ip_mac_port,
db.pivot_domain_ip,
db.pivot_software_vulnerability_link]],
'current_project': project_name, 'current_project_id': project_id,
'interfaces': [i for i in get_interfaces() if i.ip_address]}

return aiohttp_jinja2.render_template('info_tables.html', request=request, context=context)
Loading

0 comments on commit 7793e9c

Please sign in to comment.