|
description = "Authenticated AWS RDS Vulnerability Scanning" |
|
author = "Austin Songer" |
|
license = "https://nmap.org/book/man-legal.html" |
|
categories = {"safe", "vuln"} |
|
|
|
-- Import necessary NSE libraries |
|
local stdnse = require "stdnse" |
|
local shortport = require "shortport" |
|
local http = require "http" |
|
|
|
-- Define the port rule |
|
portrule = shortport.port_or_service({5432, 3306}, {"postgresql", "mysql"}) |
|
|
|
-- Helper functions for AWS Signature Version 4 |
|
local openssl = require "openssl" |
|
-- Might need Implement the cryptographic operations in an external script or program in a language that has the necessary cryptographic libraries (e.g., Python), and then call this script from your NSE script using io.popen or similar to capture the output. |
|
-- Need to Check if NSE provides any built-in libraries for cryptographic operations that can be used instead of external ones. As of my last update, direct cryptographic functions like these weren't available in NSE's standard libraries. |
|
|
|
function sha256(str) |
|
return openssl.digest("sha256", str, true) -- The 'true' parameter indicates raw output; use false or omit for hexadecimal output. |
|
end |
|
|
|
function hmac_sha256(key, data) |
|
return openssl.hmac.digest("sha256", data, key, true) -- Assuming raw output; set to false or omit for hex output. |
|
end |
|
|
|
function createCanonicalRequest(method, uri, querystring, headers, payload) |
|
local canonicalHeaders = "" |
|
local signedHeaders = "" |
|
for k, v in pairs(headers) do |
|
canonicalHeaders = canonicalHeaders .. k:lower() .. ":" .. v:trim() .. "\n" |
|
signedHeaders = signedHeaders .. k:lower() .. ";" |
|
end |
|
signedHeaders = signedHeaders:sub(1, -2) -- Remove last semicolon |
|
local payloadHash = aws.sha256(payload) |
|
local canonicalRequest = method .. "\n" .. uri .. "\n" .. querystring .. "\n" .. canonicalHeaders .. "\n" .. signedHeaders .. "\n" .. payloadHash |
|
return canonicalRequest, signedHeaders |
|
end |
|
|
|
|
|
function createStringToSign(datetime, region, service, canonicalRequest) |
|
local algorithm = "AWS4-HMAC-SHA256" |
|
local credentialScope = datetime:sub(1, 8) .. "/" .. region .. "/" .. service .. "/aws4_request" |
|
local stringToSign = algorithm .. "\n" .. datetime .. "\n" .. credentialScope .. "\n" .. aws.sha256(canonicalRequest) |
|
return stringToSign, credentialScope |
|
end |
|
|
|
|
|
function getSignatureKey(key, dateStamp, regionName, serviceName) |
|
local kDate = aws.hmac_sha256("AWS4" .. key, dateStamp) |
|
local kRegion = aws.hmac_sha256(kDate, regionName) |
|
local kService = aws.hmac_sha256(kRegion, serviceName) |
|
local kSigning = aws.hmac_sha256(kService, "aws4_request") |
|
return kSigning |
|
end |
|
|
|
function calculateSignature(secretKey, datetime, region, service, stringToSign) |
|
local signingKey = getSignatureKey(secretKey, datetime:sub(1, 8), region, service) |
|
local signature = aws.hmac_sha256(signingKey, stringToSign, true) -- true for hex output |
|
return signature |
|
end |
|
|
|
function addAuthorizationHeader(headers, accessKey, region, service, datetime, signedHeaders, signature, credentialScope) |
|
local algorithm = "AWS4-HMAC-SHA256" |
|
headers["Authorization"] = algorithm .. " Credential=" .. accessKey .. "/" .. credentialScope .. ", SignedHeaders=" .. signedHeaders .. ", Signature=" .. signature |
|
end |
|
|
|
|
|
-- Script action function |
|
action = function(host, port) |
|
local report = {} |
|
local method = "GET" -- or "POST", depending on your request |
|
local uri = "/" -- The URI for the AWS service endpoint |
|
local querystring = "" -- Any query parameters |
|
local headers = {} -- Initial headers |
|
local payload = "" -- Request payload, if any |
|
|
|
-- AWS Access Key and Secret Key |
|
local aws_access_key = "YOUR_AWS_ACCESS_KEY" |
|
local aws_secret_key = "YOUR_AWS_SECRET_KEY" |
|
|
|
-- Timestamp and region for the AWS request |
|
local datetime = os.date("!%Y%m%dT%H%M%SZ") |
|
local region = "us-east-1" -- Example AWS region |
|
local service = "rds" -- AWS service name |
|
|
|
-- Generate the canonical request |
|
local canonicalRequest, signedHeaders = createCanonicalRequest(method, uri, querystring, headers, payload) |
|
local stringToSign, credentialScope = createStringToSign(datetime, region, service, canonicalRequest) |
|
local signature = calculateSignature(aws_secret_key, datetime, region, service, stringToSign) |
|
|
|
-- Add the authorization header |
|
addAuthorizationHeader(headers, aws_access_key, region, service, datetime, signedHeaders, signature, credentialScope) |
|
|
|
-- Attempt to connect to the RDS instance |
|
-- This is a placeholder; actual connection logic will vary |
|
-- Need to replace this with actual code to make a request to AWS |
|
local aws_credentials = {accessKey = aws_access_key, secretKey = aws_secret_key} |
|
local db_connection = connect_to_rds(host.ip, port.number, aws_credentials) |
|
if not db_connection then |
|
return stdnse.format_output(false, "Failed to connect to RDS instance") |
|
end |
|
|
|
-- Placeholder for vulnerability scanning logic |
|
table.insert(report, "Vulnerability checks completed successfully") |
|
|
|
-- Return the scan results |
|
return stdnse.format_output(true, report) |
|
end |