EnrichIP V1.0: Automated Threat Intelligence Reporting for IP Addresses

Alexander
4 min readAug 30, 2023

--

Introduction

Welcome to EnrichIP, a Python-based tool designed to give you quick, enriched threat intelligence reports for IP addresses. Developed using Streamlit, GreyNoise, and OpenAI, EnrichIP aims to be an essential asset for security professionals.

Why EnrichIP?

Traditional threat intelligence platforms may offer a wealth of data, but interpreting this information often requires specialized skills and a lot of time. EnrichIP streamlines this process, not only fetching data from GreyNoise but also using OpenAI to generate easy-to-understand, contextual reports. Here are the practical applications:

  • Security Assessment: Quick and thorough analysis of the risk associated with an IP address.
  • Incident Response: Faster decision-making when an incident involves a suspicious IP.
  • Automated Reporting: Save man-hours by automatically generating detailed reports.
  • Bulk Analysis: Conduct mass scans of IPs saved in a “.csv” file formats.
  • Most of all, you can edit the prompt for OpenAI’s GPT model to fit your reporting needs and style! All you need to do is edit the code below.
st.subheader(f'Threat Intel for IP: {ip}')
with st.expander("See report"):
formatted_intel = json.dumps(threat_intel, indent=2)
prompt = f"Write a threat intel report for this paragraph:\n{formatted_intel}\n"
report = generate_report(prompt)
st.write("\nGenerated Threat Intel Report:\n", report)

A Closer Look at The Code

Api Keys

We start by importing all necessary modules and setting up API keys from an external apikey.py file. This keeps sensitive information separate from the main code.

from apikey import openai_api_key, greynoise_api_key
api_key = greynoise_api_key
openai.api_key = openai_api_key

Validating IP addresses

The function is_valid_ip() uses the ipaddress library to validate that the entered IP is a proper, routable IP address.

def is_valid_ip(ip):
try:
return ipaddress.ip_address(ip).is_global
except ValueError:
return False

Fetching Threat Intel

The get_threat_intel() function fetches data from GreyNoise. It uses the requests library to send an API request and then filters the received data into a more readable format.

def get_threat_intel(ip_address):
headers = {
'Accept': 'application/json',
'key': api_key,
}
url = f'https://api.greynoise.io/v2/noise/context/{ip_address}'
response = requests.get(url, headers=headers)

if response.status_code == 200:
data = json.loads(response.text)
# Extract specific fields
intel = {
'classification': data.get('classification'),
'actor': data.get('actor'),
'metadata': data.get('metadata'),
'last_seen': data.get('last_seen'),
'analysis': data.get('analysis'),
'cve': data.get('cve')
}
return intel
else:
raise Exception(f"Error: {response.status_code}, {response.text}")

Generate the reports

We use OpenAI’s GPT-3 to generate a readable report based on the raw threat data. The generate_report() function is responsible for this.

Stream-lit UI

Finally, Streamlit provides a simple yet powerful way to create a user interface where users can either type in a single IP address or upload a CSV file for bulk analysis

# Application Framework
st.title('☠️ Threat ☠️ Information Finder: ')

single_ip = st.text_input("Enter a single IP address to check threat intel: ")
uploaded_file = st.file_uploader("Or upload a CSV file", type=['csv'])

# Counter for IPs with no data
no_data_count = 0

if single_ip:
try:
threat_intel = get_threat_intel(single_ip)
if not any(threat_intel.values()):
no_data_count += 1
else:
st.subheader(f'Threat Intel for IP: {single_ip}')
with st.expander("See report"):
formatted_intel = json.dumps(threat_intel, indent=2)
prompt = f"Write a threat intel report for this paragraph:\n{formatted_intel}\n"
report = generate_report(prompt)
st.write("\nGenerated Threat Intel Report:\n", report)
except Exception as e:
st.write(e)

elif uploaded_file is not None:
df = pd.read_csv(uploaded_file)
if 'IP' in df.columns:
for ip in df['IP']:
if is_valid_ip():
try:
threat_intel = get_threat_intel(ip)
if not any(threat_intel.values()):
no_data_count += 1
else:
st.subheader(f'Threat Intel for IP: {ip}')
with st.expander("See report"):
formatted_intel = json.dumps(threat_intel, indent=2)
prompt = f"Write a threat intel report for this paragraph:\n{formatted_intel}\n"
report = generate_report(prompt)
st.write("\nGenerated Threat Intel Report:\n", report)
except Exception as e:
st.write(e)
else:
st.write(f'{ip} is not a valid, routable IP address.')
else:
st.error("No 'IP' column in CSV file.")

# Display the count of IPs with no data
st.write(f'Number of IPs with no data: {no_data_count}')

Getting Started

To get EnrichIP up and running, you’ll need:

  • Python 3.6 or newer.
  • Streamlit, pandas, requests, openai, and ipaddress Python libraries.
  • GreyNoise and OpenAI API keys.

Then, clone my Github repository that contains the necessary code:

After cloning the repository, place your API keys in the apikey.py file.

openai_api_key = "Your_OpenAI_API_Key_Here"
greynoise_api_key = "Your_GreyNoise_API_Key_Here"

To launch EnrichIP, navigate to the directory where you’ve saved the project and run:

python3 -m streamlit run Main.py

Usage

The application interface is simple. You can either input a single IP address or upload a CSV file containing a list of IPs. Here’s how to go about it:

  1. Single IP: Enter an IP address and click “Submit”.
  2. Bulk IPs: Upload a CSV file that has a column named “IP” containing all the IP addresses you wish to check.

The application then provides a short and quick information report for each IP, which you can expand to view.

--

--