resources: simplify default script; document API better

This commit is contained in:
raf 2025-05-02 07:40:28 +03:00
commit 1b77c0daa6
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF

View file

@ -1,17 +1,210 @@
function generate_honeytoken(token) --[[
local token_types = { "API_KEY", "AUTH_TOKEN", "SESSION_ID", "SECRET_KEY" } Eris Default Script
local prefix = token_types[math.random(#token_types)]
local suffix = string.format("%08x", math.random(0xffffff))
return prefix .. "_" .. token .. "_" .. suffix
end
This script demonstrates how to use the Eris Lua API to customize
the tarpit's behavior, and will be loaded by default if no other
scripts are loaded.
Available events:
- connection: When a new connection is established
- request: When a request is received
- response_gen: When generating a response
- response_chunk: Before sending each response chunk
- disconnection: When a connection is closed
- block_ip: When an IP is being considered for blocking
- startup: When the application starts
- shutdown: When the application is shutting down
- periodic: Called periodically
API Functions:
- eris.debug(message): Log a debug message
- eris.info(message): Log an info message
- eris.warn(message): Log a warning message
- eris.error(message): Log an error message
- eris.set_state(key, value): Store persistent state
- eris.get_state(key): Retrieve persistent state
- eris.inc_counter(key, [amount]): Increment a counter
- eris.get_counter(key): Get a counter value
- eris.gen_token([prefix]): Generate a unique token
- eris.timestamp(): Get current Unix timestamp
--]]
-- Called when the application starts
eris.on("startup", function(ctx)
eris.info("Initializing default script")
-- Initialize counters
eris.inc_counter("total_connections", 0)
eris.inc_counter("total_responses", 0)
eris.inc_counter("blocked_ips", 0)
-- Initialize banned keywords
eris.set_state("banned_keywords", "eval,exec,system,shell,<?php,/bin/bash")
end)
-- Called for each new connection
eris.on("connection", function(ctx)
eris.inc_counter("total_connections")
eris.debug("New connection from " .. ctx.ip)
-- You can reject connections by returning false
-- This example checks a blocklist
local blocklist = eris.get_state("manual_blocklist") or ""
if blocklist:find(ctx.ip) then
eris.info("Rejecting connection from manually blocked IP: " .. ctx.ip)
return false
end
return true -- accept the connection
end)
-- Called when generating a response
eris.on("response_gen", function(ctx)
eris.inc_counter("total_responses")
-- Generate a unique traceable token for this request
local token = eris.gen_token("ERIS-")
-- Add some believable but fake honeytokens based on the request path
local enhanced_content = ctx.content
if ctx.path:find("wp%-") then
-- For WordPress paths
enhanced_content = enhanced_content
.. "\n<!-- WordPress Debug: "
.. token
.. " -->"
.. "\n<!-- WP_HOME: http://stop.crawlingmysite.com/wordpress -->"
.. "\n<!-- DB_USER: wp_user_"
.. math.random(1000, 9999)
.. " -->"
elseif ctx.path:find("phpunit") or ctx.path:find("eval") then
-- For PHP exploit attempts
-- Turns out you can just google "PHP error log" and search random online forums where people
-- dump their service logs in full.
enhanced_content = enhanced_content
.. "\nPHP Notice: Undefined variable: _SESSION in /var/www/html/includes/core.php on line 58\n"
.. "Warning: file_get_contents(): Filename cannot be empty in /var/www/html/vendor/autoload.php on line 23\n"
.. "Token: "
.. token
.. "\n"
elseif ctx.path:find("api") then
-- For API requests
local fake_api_key =
string.format("ak_%x%x%x", math.random(1000, 9999), math.random(1000, 9999), math.random(1000, 9999))
enhanced_content = enhanced_content
.. "{\n"
.. ' "status": "warning",\n'
.. ' "message": "Test API environment detected",\n'
.. ' "debug_token": "'
.. token
.. '",\n'
.. ' "api_key": "'
.. fake_api_key
.. '"\n'
.. "}\n"
else
-- For other requests
enhanced_content = enhanced_content
.. "\n<!-- Server: Apache/2.4.41 (Ubuntu) -->"
.. "\n<!-- Debug-Token: "
.. token
.. " -->"
.. "\n<!-- Environment: staging -->"
end
-- Track which honeytokens were sent to which IP
local honeytokens = eris.get_state("honeytokens") or "{}"
local ht_table = {}
-- This is a simplistic approach - in a real script, you'd want to use
-- a proper JSON library to handle this correctly
if honeytokens ~= "{}" then
-- Simple parsing of the stored data
for ip, tok in honeytokens:gmatch('"([^"]+)":"([^"]+)"') do
ht_table[ip] = tok
end
end
ht_table[ctx.ip] = token
-- Convert back to a simple JSON-like string
local new_tokens = "{"
for ip, tok in pairs(ht_table) do
if new_tokens ~= "{" then
new_tokens = new_tokens .. ","
end
new_tokens = new_tokens .. '"' .. ip .. '":"' .. tok .. '"'
end
new_tokens = new_tokens .. "}"
eris.set_state("honeytokens", new_tokens)
return enhanced_content
end)
-- Called before sending each chunk of a response
eris.on("response_chunk", function(ctx)
-- This can be used to alter individual chunks for more deceptive behavior
-- For example, to simulate a slow, unreliable server
-- 5% chance of "corrupting" a chunk to confuse scanners
if math.random(1, 100) <= 5 then
local chunk = ctx.content
if #chunk > 10 then
local pos = math.random(1, #chunk - 5)
chunk = chunk:sub(1, pos) .. string.char(math.random(32, 126)) .. chunk:sub(pos + 2)
end
return chunk
end
return ctx.content
end)
-- Called when deciding whether to block an IP
eris.on("block_ip", function(ctx)
-- You can override the default blocking logic
-- Check for potential attackers using specific patterns
local banned_keywords = eris.get_state("banned_keywords") or ""
local user_agent = ctx.user_agent or ""
-- Check if user agent contains highly suspicious patterns
for keyword in banned_keywords:gmatch("[^,]+") do
if user_agent:lower():find(keyword:lower()) then
eris.info("Blocking IP " .. ctx.ip .. " due to suspicious user agent: " .. keyword)
eris.inc_counter("blocked_ips")
return true -- Force block
end
end
-- For demonstration, we'll be more lenient with 10.x IPs
if ctx.ip:match("^10%.") then
-- Only block if they've hit us many times
return ctx.hit_count >= 5
end
-- Default to the system's threshold-based decision
return nil
end)
-- The enhance_response is now legacy, and I never liked it anyway. Though let's add it here
-- for the sake of backwards compatibility.
function enhance_response(text, response_type, path, token) function enhance_response(text, response_type, path, token)
local result = text local enhanced = text
local honeytoken = generate_honeytoken(token)
-- Add some fake sensitive data -- Add token as a comment
result = result .. "\n<!-- DEBUG: " .. honeytoken .. " -->" if response_type == "php_exploit" then
result = result .. "\n<div style='display:none'>Server ID: " .. token .. "</div>" enhanced = enhanced .. "\n/* Token: " .. token .. " */\n"
elseif response_type == "wordpress" then
enhanced = enhanced .. "\n<!-- WordPress Debug Token: " .. token .. " -->\n"
elseif response_type == "api" then
enhanced = enhanced:gsub('"status": "[^"]+"', '"status": "warning"')
enhanced = enhanced:gsub('"message": "[^"]+"', '"message": "API token: ' .. token .. '"')
else
enhanced = enhanced .. "\n<!-- Debug token: " .. token .. " -->\n"
end
return result return enhanced
end end