Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the project for adding some features #14

Merged
merged 9 commits into from
Dec 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.pyc
nmaper/static/results/
.DS_Store
.env
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#CHANGELOG
* [10/06/2019]
* Compatible with Python 3 (Tested on Python 3.7.4)
* Move out the configuration from source code to environment file (use the [python-dotenv](https://github.com/theskumar/python-dotenv) library)
* Add more variables for application
* Add the setup.sh for simplifying the setup [GH#3]
* [09/29/2016] Fixes bug with nmaper-cronjob.py not finding Nmap. [GH#8]
* [09/17/2016] Added checkboxes to enable/disable DNS resolution and host discovery. [GH#2]

34 changes: 0 additions & 34 deletions INSTALL.md

This file was deleted.

32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Unlike it's predecessor [1], Rainmap-lite does not require special services (Rab
* Dozens of scanning profiles to choose from.
* Easy to install/set up.
* Share results with your team.
* Compatible with Python 3 (Tested on Python 3.7.4)

This project is still in beta version. Any feedback, bug reports and PRs are greatly appreciated!

Expand All @@ -23,7 +24,38 @@ https://youtu.be/3oNegHPBd3o
## Documentation
You can find all the documentation related to this project on the [Wiki](https://github.com/cldrn/rainmap-lite/wiki/ "Rainmap Lite Documentation")

## Installation

1. Make sure the **python3**, **pip3**, **nmap**, **nmap-scripts** and **cron** installed on system
2. git clone this project
3. Rename/Copy the .env.sample to .env
4. Prepare the environment file (.env)
5. sh setup.sh

## Environment variables (.env.sample file)

### Configuration for setup.sh

- APP_ROOT_PATH="/opt/rainmap-lite/"
- HTTP_PORT="8000"
- LOG_PATH="/var/log/nmaper.log"
- ADMIN_USER="admin"
- ADMIN_PASS="admin"
- ADMIN_EMAIL="user@domain.org"

### Config for namper-cronjob.py

#### Please follow the format that described in [python-dotenv](https://github.com/theskumar/python-dotenv)

- BASE_URL="[http://127.0.0.1:${HTTP_PORT}](http://127.0.0.1:${HTTP_PORT}/)"
- SMTP_USER="SMTP_USER"
- SMTP_PASS="SMTP_PASS"
- SMTP_SERVER="SMTP_SERVER"
- SMTP_PORT="SMTP_PORT"
- SMTP_DOMAIN_NAME="SMTP_DOMAIN_NAME"

## Screenshots

* Responsive interface
<img style="float:center;width:80%" src="https://raw.githubusercontent.com/cldrn/rainmap-lite/master/rainmap-lite-1.png" />
* Customizable
Expand Down
15 changes: 15 additions & 0 deletions rainmap-lite/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Config for setup.sh
APP_ROOT_PATH="/opt/rainmap-lite/"
HTTP_PORT="8000"
LOG_PATH="/var/log/nmaper.log"
ADMIN_USER="admin"
ADMIN_PASS="admin"
ADMIN_EMAIL="freebooters@gmail.com"

# Config for namper-cronjob.py
BASE_URL="http://127.0.0.1:${HTTP_PORT}"
SMTP_USER="SMTP_USER"
SMTP_PASS="SMTP_PASS"
SMTP_SERVER="SMTP_SERVER"
SMTP_PORT="SMTP_PORT"
SMTP_DOMAIN_NAME="SMTP_DOMAIN_NAME"
6 changes: 3 additions & 3 deletions rainmap-lite/NmapOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ def setdefault(self, key, default):
return self.d.setdefault(self.canonicalize_name(key), default)

def handle_result(self, result):
if isinstance(result, basestring):
if isinstance(result, str):
# A positional argument.
self.target_specs.append(result)
return
Expand Down Expand Up @@ -768,7 +768,7 @@ def render(self):
opt_list.append("-T%s" % str(self["-T"]))

if self["-O"] is not None:
if isinstance(self["-O"], basestring):
if isinstance(self["-O"], str):
opt_list.append("-O%s" % self["-O"])
elif self["-O"]:
opt_list.append("-O")
Expand Down Expand Up @@ -818,7 +818,7 @@ def render(self):
if self[ping_option] is not None:
opt_list.append(ping_option + self[ping_option])
if self["-PB"] is not None:
if isinstance(self["-PB"], basestring):
if isinstance(self["-PB"], str):
opt_list.append("-PB" + self["-PB"])
elif self["-PB"]:
opt_list.append("-PB")
Expand Down
3 changes: 3 additions & 0 deletions rainmap-lite/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import os
import sys

from dotenv import load_dotenv
load_dotenv()

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "scandere.settings")

Expand Down
126 changes: 95 additions & 31 deletions rainmap-lite/nmaper-cronjob.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/python
#Cronjob script that executes Nmap scans on the background
#!/usr/bin/python3
# Cronjob script that executes Nmap scans on the background
import sqlite3
import os
import subprocess
Expand All @@ -9,89 +9,146 @@
import lxml.etree as ET
import distutils.spawn

from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from NmapOptions import NmapOptions

#<CONFIGURATION>
BASE_URL = "http://127.0.0.1:8000"
SMTP_USER = "youremail@gmail.com"
SMTP_PASS = "yourpassword"
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 587
#</CONFIGURATION>
from dotenv import load_dotenv
load_dotenv()

BASE_URL = os.getenv('BASE_URL')
SMTP_USER = os.getenv('SMTP_USER')
SMTP_PASS = os.getenv('SMTP_PASS')
SMTP_SERVER = os.getenv('SMTP_SERVER')
SMTP_PORT = os.getenv('SMTP_PORT')
SMTP_DOMAIN_NAME = os.getenv('SMTP_DOMAIN_NAME')

OUTPUT_PATH = os.path.normpath(
"%s/nmaper/static/results" % os.getcwd()
).replace("\\", "/")

OUTPUT_PATH = os.path.normpath("%s/nmaper/static/results" % os.getcwd()).replace("\\", "/")

def find_nmap():
if os.name == "nt":
nmap_path = distutils.spawn.find_executable("nmap.exe", os.environ["PROGRAMFILES(X86)"]+"\Nmap")
nmap_path = distutils.spawn.find_executable(
"nmap.exe", f"{os.environ['PROGRAMFILES(X86)']}\\Nmap"
)

if not(nmap_path):
nmap_path = distutils.spawn.find_executable("nmap.exe", os.environ["PROGRAMFILES"]+"\Nmap")
nmap_path = distutils.spawn.find_executable(
"nmap.exe", f"{os.environ['PROGRAMFILES']}\\Nmap"
)
else:
nmap_path = distutils.spawn.find_executable("nmap","/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin")
nmap_path = distutils.spawn.find_executable(
"nmap", "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
)

return nmap_path


def notify(id_, email, cmd):
print('[%s] Sending report %s to %s' % (datetime.datetime.now(), id_, email))
print(
'[%s] Sending report %s to %s' % (datetime.datetime.now(), id_, email)
)

msg = MIMEMultipart()
msg['From'] = SMTP_USER
email_from_address = f'{SMTP_USER}@{SMTP_DOMAIN_NAME}'
msg['From'] = email_from_address
msg['To'] = email
msg['Subject'] = "Your scan results are ready"
body = "{2}\n\nView online:\n{0}/static/results/{1}.html\n\nDownload:\n{0}/static/results/{1}.nmap\n{0}/static/results/{1}.xml\n{0}/static/results/{1}.gnmap".format(BASE_URL, id_, cmd)
body = (
"{2}\n\n"
"View online:\n{0}/static/results/{1}.html\n\n"
"Download:\n"
"{0}/static/results/{1}.nmap\n"
"{0}/static/results/{1}.xml\n"
"{0}/static/results/{1}.gnmap"
).format(BASE_URL, id_, cmd)
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
server.ehlo()
server.starttls()
server.ehlo()
server.login(SMTP_USER, SMTP_PASS)
text = msg.as_string()
server.sendmail(SMTP_USER, email, text)
server.sendmail(email_from_address, email, text)


def update_status(id_, status, cursor, db):
cursor.execute('''UPDATE nmaper_nmapscan SET status_text = ? WHERE id = ? ''', (status, id_))
cursor.execute(
'''UPDATE nmaper_nmapscan SET status_text = ? WHERE id = ? ''',
(status, id_)
)
db.commit()
print("[%s] Job #%s status changed to '%s'" % (datetime.datetime.now(), id_, status))
print(
"[%s] Job #%s status changed to '%s'" % (
datetime.datetime.now(), id_, status
)
)


def set_random_id(id_, cursor, db):
rid = uuid.uuid4()
cursor.execute('''UPDATE nmaper_nmapscan SET uuid = ? WHERE id = ? ''', (rid.hex, id_))
cursor.execute(
'''UPDATE nmaper_nmapscan SET uuid = ? WHERE id = ? ''',
(rid.hex, id_)
)
db.commit()
return rid.hex


def set_endtime(id_, cursor, db):
cursor.execute('''UPDATE nmaper_nmapscan SET end_date = ? WHERE id = ? ''', (datetime.datetime.now(), id_))
cursor.execute(
'''UPDATE nmaper_nmapscan SET end_date = ? WHERE id = ? ''',
(datetime.datetime.now(), id_)
)
db.commit()


def execute(path, cmd, uuid):
filename = "%s/%s" % (OUTPUT_PATH, uuid)
filename = "%s/%s" % (OUTPUT_PATH, uuid)
nmap_cmd = '%s %s -oA %s' % (path, cmd, filename)
ops = NmapOptions()
ops.parse_string(nmap_cmd)
proc = subprocess.Popen(ops.render(), shell=False)
proc.wait()

print('\n[%s] Finished execution of command "%s"' % (datetime.datetime.now(), cmd))
print(
'\n[%s] Finished execution of command "%s"' % (
datetime.datetime.now(), cmd
)
)

dom = ET.parse("%s.xml" % filename)
xsl_filename = dom.getroot().getprevious().getprevious().parseXSL() # need to add error checking
# need to add error checking
xsl_filename = dom.getroot().getprevious().getprevious().parseXSL()
transform = ET.XSLT(xsl_filename)
html = transform(dom)
html_file = open('%s.html' % filename, 'w')
html_file = open('%s.html' % filename, 'wb')
html.write(html_file)

print('[%s] HTML report generated (%s.html)' % (datetime.datetime.now(), filename))
print(
'[%s] HTML report generated (%s.html)' % (
datetime.datetime.now(), filename
)
)


def main():
path = find_nmap()

if not path:
print("[%s] Could not find path for nmap. Quitting!" % datetime.datetime.now())
print(
"[%s] Could not find path for nmap. Quitting!" %
datetime.datetime.now()
)
exit()

db = sqlite3.connect('scandere.sqlite3')
cursor = db.cursor()
cursor.execute('''SELECT * FROM nmaper_nmapscan WHERE status_text="waiting"''')
cursor.execute(
r'SELECT * FROM nmaper_nmapscan WHERE status_text="waiting"'
)
all_rows = cursor.fetchall()
print('[%s] Listing pending nmap scans...' % datetime.datetime.now())

Expand All @@ -105,8 +162,15 @@ def main():
execute(path, cmd, rid)
update_status(jid, "finished", cursor, db)
set_endtime(jid, cursor, db)
print("[%s] Job #%d finished. Notifying '%s'" % (datetime.datetime.now(), jid, email))
print(
"[%s] Job #%d finished. Notifying '%s'" % (
datetime.datetime.now(),
jid,
email
)
)
notify(rid, email, cmd)


if __name__ == "__main__":
main()
4 changes: 4 additions & 0 deletions rainmap-lite/requirement.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Django==1.11.25
lxml==4.4.1
python-dotenv==0.10.3
pytz==2019.2
5 changes: 4 additions & 1 deletion rainmap-lite/scandere/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
LOGIN_REDIRECT_URL = '/'
ALLOWED_HOSTS = []

ALLOWED_HOSTS = [
os.getenv('BASE_URL').split(':')[1].replace('/', '')
]


# Application definition
Expand Down
Loading