modified krawl template for single page visualization
This commit is contained in:
@@ -156,11 +156,35 @@ def generate_dashboard(stats: dict) -> str:
|
||||
background: #1c1917;
|
||||
border-left: 4px solid #f85149;
|
||||
}}
|
||||
th.sortable {{
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
padding-right: 24px;
|
||||
}}
|
||||
th.sortable:hover {{
|
||||
background: #1c2128;
|
||||
}}
|
||||
th.sortable::after {{
|
||||
content: '⇅';
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
opacity: 0.5;
|
||||
font-size: 12px;
|
||||
}}
|
||||
th.sortable.asc::after {{
|
||||
content: '▲';
|
||||
opacity: 1;
|
||||
}}
|
||||
th.sortable.desc::after {{
|
||||
content: '▼';
|
||||
opacity: 1;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🕷️ Krawl Dashboard</h1>
|
||||
<h1>Krawl Dashboard</h1>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
@@ -190,13 +214,13 @@ def generate_dashboard(stats: dict) -> str:
|
||||
</div>
|
||||
|
||||
<div class="table-container alert-section">
|
||||
<h2>🍯 Honeypot Triggers by IP</h2>
|
||||
<table>
|
||||
<h2>Honeypot Triggers by IP</h2>
|
||||
<table id="honeypot-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>IP Address</th>
|
||||
<th class="sortable" data-sort="ip">IP Address</th>
|
||||
<th>Accessed Paths</th>
|
||||
<th>Count</th>
|
||||
<th class="sortable" data-sort="count">Count</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -206,7 +230,7 @@ def generate_dashboard(stats: dict) -> str:
|
||||
</div>
|
||||
|
||||
<div class="table-container alert-section">
|
||||
<h2>⚠️ Recent Suspicious Activity</h2>
|
||||
<h2>Recent Suspicious Activity</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -223,7 +247,7 @@ def generate_dashboard(stats: dict) -> str:
|
||||
</div>
|
||||
|
||||
<div class="table-container alert-section">
|
||||
<h2>🔑 Captured Credentials</h2>
|
||||
<h2>Captured Credentials</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -241,7 +265,7 @@ def generate_dashboard(stats: dict) -> str:
|
||||
</div>
|
||||
|
||||
<div class="table-container alert-section">
|
||||
<h2>😈 Detected Attack Types</h2>
|
||||
<h2>Detected Attack Types</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -306,6 +330,64 @@ def generate_dashboard(stats: dict) -> str:
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// Add sorting functionality to tables
|
||||
document.querySelectorAll('th.sortable').forEach(header => {{
|
||||
header.addEventListener('click', function() {{
|
||||
const table = this.closest('table');
|
||||
const tbody = table.querySelector('tbody');
|
||||
const rows = Array.from(tbody.querySelectorAll('tr'));
|
||||
const sortType = this.getAttribute('data-sort');
|
||||
const columnIndex = Array.from(this.parentElement.children).indexOf(this);
|
||||
|
||||
// Determine sort direction
|
||||
const isAscending = this.classList.contains('asc');
|
||||
|
||||
// Remove sort classes from all headers in this table
|
||||
table.querySelectorAll('th.sortable').forEach(th => {{
|
||||
th.classList.remove('asc', 'desc');
|
||||
}});
|
||||
|
||||
// Add appropriate class to clicked header
|
||||
this.classList.add(isAscending ? 'desc' : 'asc');
|
||||
|
||||
// Sort rows
|
||||
rows.sort((a, b) => {{
|
||||
let aValue = a.cells[columnIndex].textContent.trim();
|
||||
let bValue = b.cells[columnIndex].textContent.trim();
|
||||
|
||||
// Handle numeric sorting
|
||||
if (sortType === 'count') {{
|
||||
aValue = parseInt(aValue) || 0;
|
||||
bValue = parseInt(bValue) || 0;
|
||||
return isAscending ? bValue - aValue : aValue - bValue;
|
||||
}}
|
||||
|
||||
// Handle IP address sorting
|
||||
if (sortType === 'ip') {{
|
||||
const ipToNum = ip => {{
|
||||
const parts = ip.split('.');
|
||||
if (parts.length !== 4) return 0;
|
||||
return parts.reduce((acc, part, i) => acc + (parseInt(part) || 0) * Math.pow(256, 3 - i), 0);
|
||||
}};
|
||||
const aNum = ipToNum(aValue);
|
||||
const bNum = ipToNum(bValue);
|
||||
return isAscending ? bNum - aNum : aNum - bNum;
|
||||
}}
|
||||
|
||||
// Default string sorting
|
||||
if (isAscending) {{
|
||||
return bValue.localeCompare(aValue);
|
||||
}} else {{
|
||||
return aValue.localeCompare(bValue);
|
||||
}}
|
||||
}});
|
||||
|
||||
// Re-append sorted rows
|
||||
rows.forEach(row => tbody.appendChild(row));
|
||||
}});
|
||||
}});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
@@ -9,40 +9,64 @@
|
||||
background-color: #0d1117;
|
||||
color: #c9d1d9;
|
||||
margin: 0;
|
||||
padding: 40px 20px;
|
||||
min-height: 100vh;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}}
|
||||
.container {{
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}}
|
||||
h1 {{
|
||||
color: #f85149;
|
||||
text-align: center;
|
||||
font-size: 48px;
|
||||
margin: 60px 0 30px;
|
||||
font-size: 36px;
|
||||
margin: 40px 0 20px 0;
|
||||
flex-shrink: 0;
|
||||
}}
|
||||
.counter {{
|
||||
color: #f85149;
|
||||
text-align: center;
|
||||
font-size: 56px;
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 60px;
|
||||
margin: 0 0 30px 0;
|
||||
flex-shrink: 0;
|
||||
}}
|
||||
.links-container {{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
padding-top: 10px;
|
||||
}}
|
||||
.links-container::-webkit-scrollbar {{
|
||||
width: 8px;
|
||||
}}
|
||||
.links-container::-webkit-scrollbar-track {{
|
||||
background: #0d1117;
|
||||
}}
|
||||
.links-container::-webkit-scrollbar-thumb {{
|
||||
background: #30363d;
|
||||
border-radius: 4px;
|
||||
}}
|
||||
.links-container::-webkit-scrollbar-thumb:hover {{
|
||||
background: #484f58;
|
||||
}}
|
||||
.link-box {{
|
||||
background: #161b22;
|
||||
border: 1px solid #30363d;
|
||||
border-radius: 6px;
|
||||
padding: 15px 30px;
|
||||
padding: 10px 20px;
|
||||
min-width: 300px;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
@@ -56,7 +80,7 @@
|
||||
a {{
|
||||
color: #58a6ff;
|
||||
text-decoration: none;
|
||||
font-size: 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}}
|
||||
a:hover {{
|
||||
@@ -66,21 +90,21 @@
|
||||
background: #1c1917;
|
||||
border: 2px solid #f85149;
|
||||
border-radius: 8px;
|
||||
padding: 30px 50px;
|
||||
margin: 40px auto;
|
||||
padding: 20px 30px;
|
||||
margin: 20px auto;
|
||||
max-width: 800px;
|
||||
overflow-x: auto;
|
||||
}}
|
||||
.canary-token a {{
|
||||
color: #f85149;
|
||||
font-size: 18px;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Krawl me! 🕸</h1>
|
||||
<h1>Krawl me!</h1>
|
||||
<div class="counter">{counter}</div>
|
||||
|
||||
<div class="links-container">
|
||||
|
||||
@@ -125,6 +125,7 @@ class Wordlists:
|
||||
def server_errors(self):
|
||||
return self._data.get("server_errors", {})
|
||||
|
||||
@property
|
||||
def server_headers(self):
|
||||
return self._data.get("server_headers", [])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user