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)) This script demonstrates how to use the Eris Lua API to customize
return prefix .. "_" .. token .. "_" .. suffix 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 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
return result 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 enhanced
end end