Skip to content

stefan1anuby/Web-Vulnerability-Alerting

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

39 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation


πŸ“” Table of Contents

🌟 About the Project

A system designed to provide real-time alerts about new security vulnerabilities affecting specific classes of software, such as operating systems, web servers, databases, applications, browsers, etc. The vulnerabilities are identified by parsing open-source databases containing relevant information. This data will be available for consumption in multiple formats, including HTML + RDFa, JSON-LD, Kafka messaging, and SPARQL queries.

πŸ“· Screenshots

Main menu Main menu

πŸ‘Ύ Tech Stack

Client
Server
  • Java
  • Spring Boot
  • Apache Kafka
  • Python
Database
Infrastructure
  • Docker
  • Cloud Run
  • Google Filestore NFS
  • Google Managed Kafka
  • Google Compute Engine VM

🎯 Features

  • Search and Query Interface - Provide a web interface to allow users to search and filter vulnerabilities based on various criteria (e.g., software type, severity, CVE ID).
  • Real-Time Alerts – Implement a publish/subscribe mechanism using Kafka to notify users of new security issues in real-time.
  • SPARQL Endpoint - Offer a queryable SPARQL endpoint
  • Multi-Format Data Representation - Provide vulnerability details in HTML + RDFa and JSON-LD.

🧰 Getting Started

‼️ Prerequisites

This project uses Docker

Check this for downloading it.

πŸƒ Run Locally

Clone the project

  git clone https://github.com/stefan1anuby/Web-Vulnerability-Alerting.git

Go to the project directory

  cd Web-Vulnerability-Alerting

Start the project

  docker-compose -f server/compose.yaml up --build

Add vulnerabilities to the database

  python scraper/main.py

(be sure to point to the correct domain by looking in the script)

Go to the http://localhost:8088/views/menu

🚩 Google Cloud Platform Instructions

  1. Create a New Project in GCP
    Start by creating a new project in Google Cloud Platform (GCP) to isolate resources and manage them independently.

  2. Create a New VPC and Firewall Rules
    Set up a new Virtual Private Cloud (VPC) and define firewall rules to allow traffic from Cloud Run to:

    • NFS Filestore
    • Kafka
  3. Create an NFS Filestore in the VPC
    Deploy an NFS Filestore instance in the previously created VPC to serve as the shared storage.

  4. Create a Kafka Cluster in the VPC
    Deploy a Kafka cluster in the same VPC for message brokering and communication.

  5. Deploy a Google Cloud Run Service

    • Deploy a Cloud Run service in the same VPC, pointing it to the /server directory in your project.
    • You can use a GitHub repository link, a Docker image registry, or the Google Cloud IDE for this deployment.
    • Set the required environment variables, including:
      • The NFS volume path.
      • The Kafka URL for communication.
    • Ensure the IAM role assigned to the service has the necessary permissions to interact with Kafka and Filestore.
  6. [OPTIONAL] Create a Compute Engine VM for External Scraper Jobs

    • Deploy a Compute Engine VM with internet access by either assigning a temporary external IP or using Cloud NAT.
    • SSH into the VM and set up the scraper script to run as a scheduled job (e.g., every X hours/days/months).
    • Update the script's URL to point to the Cloud Run app.

πŸ‘€ Usage

The main page contains selection buttons and text areas where you can select or write specific data for a vulnerability (year, affected software, version, etc.). The specified data will be used to make filters (if it is the case) in the SPARQL query, which will extract the desired vulnerabilities (if there are any that meet the criteria). The vulnerabilities are described in HTML + RDFa or JSON-LD format. There is a button that, when pressed, it shows the user the SPARQL query that is sent to the server based on the selected options.

The SPARQL query is predefined based on the STIX ontology.

let query = 
  `PREFIX stix: <http://purl.org/cyber/stix#>
   PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
   PREFIX schema: <https://schema.org/SoftwareApplication#>
   PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

   SELECT ?vulnerability ?description ?solution
   WHERE {
      ?vulnerability rdf:type stix:Vulnerability .
      ?vulnerability stix:description ?description .
      ?vulnerability stix:published ?published .
      ?vulnerability stix:severity ?severity .
      ?vulnerability stix:ExternalReference ?application .
      ?application schema:applicationCategory ?topic .
      ?application schema:applicationSubCategory ?product .
      ?application schema:softwareVersion ?version .
      ?vulnerability stix:mitigatedBy ?solutionId .
      ?solutionId stix:description ?solution .`;
query += '\n';

Based on the options selected, a filter is added to the query.

if(category !== 'All') query += `FILTER(lcase(?topic) = "${categoryLowercase}") .` + '\n';
if(product !== 'All' && product !== '') query += `FILTER(lcase(?product) = "${productLowercase}") .` + '\n';
if(version !== 'All' && version !== '') query += `FILTER(lcase(STR(?version)) = "${versionLowercase}") .` + '\n';
if(severity !== 'All') query += `FILTER(lcase(?severity) = "${severityLowercase}") .` + '\n';
if(date !== 'All') query += `FILTER(YEAR(STRDT(?published, xsd:dateTime)) = ${date}) .` + '\n';
query += `}`;

The user can also write a specific id (the format is CVE-\d{4}-\d{4,7}) in a search bar and extract the associated vulnerability in the database. The result can be in HTML + RDFa or JSON-LD format.

Formats Formats

Another way to use the app is through ingesting Kafka messages. You can ingest them by creating a consumer using their library.

package org.laborator;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;

import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

public class Main {
    // docker run --rm --network server_default confluentinc/cp-kafka kafka-console-consumer --bootstrap-server kafka:9092 --topic General --from-beginning
    public static void main(String[] args) {
        // Kafka consumer configuration settings
        String topicName = "General"; // Replace with your topic name
        String bootstrapServers = "kafka:9092"; // Replace with your Kafka broker address
        String groupId = "example-group"; // Consumer group ID

        // Consumer configuration properties
        Properties props = new Properties();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); // Start from the earliest message if no offset is committed

        // Create Kafka consumer
        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);

        // Subscribe to the topic
        consumer.subscribe(Collections.singletonList(topicName));

        System.out.println("Kafka Consumer is now listening for messages...");

        try {
            while (true) {
                // Poll for records (messages) from Kafka
                ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
                for (ConsumerRecord<String, String> record : records) {
                    System.out.printf("Consumed message: Key = %s, Value = %s, Partition = %d, Offset = %d%n",
                            record.key(), record.value(), record.partition(), record.offset());
                }
            }
        } catch (Exception e) {
            System.err.println("Error in Kafka consumer: " + e.getMessage());
        } finally {
            consumer.close();
        }
    }
}

and an example of ingesting logs could be this:

image

🀝 Contact

Google Drive Link containing the other deliverables:

https://drive.google.com/drive/u/0/folders/1SO7nJIG3HXhj3JQYjCDbimzQRsEUzGOs