PrivHunterAI/index.html
2025-04-22 12:40:00 +08:00

492 lines
16 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PrivHunterAI</title>
<!-- 引入 Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<!-- 引入 Font Awesome 图标库 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<style>
body {
padding: 20px;
background: linear-gradient(135deg, #f8f9fa, #e9ecef);
font-family: 'Roboto', sans-serif;
}
.header {
background: linear-gradient(135deg, #4a90e2, #1f78d1);
border-radius: 10px;
padding: 30px;
color: white;
position: relative;
overflow: hidden;
}
.header::after {
content: "";
position: absolute;
bottom: -50px;
right: -50px;
width: 300px;
height: 300px;
background: rgba(255,255,255,0.1);
border-radius: 50%;
}
.header h1 {
font-size: 2.5rem;
font-weight: bold;
margin-bottom: 5px;
}
.header p {
font-size: 1rem;
opacity: 0.9;
}
.refresh-btn {
background: white;
color: #4a90e2;
border-radius: 5px;
padding: 8px 20px;
border: none;
font-size: 0.9rem;
cursor: pointer;
margin-top: 20px;
transition: all 0.3s ease;
}
.refresh-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.stats-container {
display: flex;
gap: 20px;
margin-top: 20px;
}
.stat-card {
flex: 1;
background: white;
border-radius: 10px;
padding: 25px 20px;
text-align: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
transition: all 0.3s ease;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 6px 12px rgba(0,0,0,0.08);
}
.stat-number {
font-size: 2.5rem;
font-weight: bold;
margin-bottom: 10px;
}
.total .stat-number { color: #4a90e2; }
.vulnerable .stat-number { color: #e74c3c; }
.unknown .stat-number { color: #f39c12; }
.safe .stat-number { color: #2ecc71; }
.stat-label {
font-size: 0.9rem;
color: #666;
}
.results-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-top: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.results-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.filter-select {
padding: 8px 15px;
border-radius: 5px;
border: 1px solid #ddd;
margin-right: 10px;
outline: none;
transition: all 0.3s ease;
}
.filter-select:focus {
border-color: #4a90e2;
box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2);
}
.filter-btn {
background: #4a90e2;
color: white;
border: none;
border-radius: 5px;
padding: 8px 20px;
cursor: pointer;
transition: all 0.3s ease;
}
.filter-btn:hover {
background: #3a7bc8;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(74, 144, 226, 0.3);
}
.empty-state {
text-align: center;
padding: 50px 20px;
color: #666;
}
.empty-state i {
font-size: 50px;
color: #f39c12;
margin-bottom: 20px;
}
footer {
text-align: center;
padding: 20px 0;
color: #666;
font-size: 0.9rem;
margin-top: 30px;
}
/* 表格样式 */
.data-table {
width: 100%;
border-collapse: collapse;
}
.data-table th {
padding: 1.5rem;
text-align: center;
vertical-align: middle;
max-width: 150px;
word-wrap: break-word;
border-bottom: 0.1rem solid #e0e0e0;
}
.data-table td {
padding: 1.5rem;
text-align: center;
vertical-align: middle;
max-width: 150px;
word-wrap: break-word;
border-bottom: 0.1rem solid #e0e0e0;
}
.data-table tr:hover {
background-color: rgba(0,0,0,0.02);
}
.vulnerable-row {
background-color: rgba(231, 76, 60, 0.1);
}
.unknown-row {
background-color: rgba(243, 156, 18, 0.1);
}
.safe-row {
background-color: rgba(46, 204, 113, 0.1);
}
/* 分页样式 */
.pagination {
display: flex;
justify-content: center;
margin-top: 20px;
}
.pagination button {
background: #f8f9fa;
border: 1px solid #dee2e6;
padding: 8px 15px;
margin: 0 5px;
cursor: pointer;
border-radius: 5px;
transition: all 0.3s ease;
}
.pagination button:hover {
background: #e9ecef;
}
.pagination button.active {
background: #4a90e2;
color: white;
border-color: #4a90e2;
}
.pagination button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.page-info {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
color: #666;
}
.page-info select {
margin: 0 10px;
padding: 5px 10px;
border-radius: 5px;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<div class="container">
<!-- Header Section -->
<div class="header">
<h1>PrivHunterAI <small>v1.0.0</small></h1>
<p>高级API安全扫描工具智能检测未授权访问和越权漏洞</p>
<button class="refresh-btn" onclick="fetchData()">刷新数据</button>
</div>
<!-- Statistics Cards -->
<div class="stats-container">
<div class="stat-card total">
<div class="stat-number" id="total-requests">0</div>
<div class="stat-label">总扫描请求</div>
</div>
<div class="stat-card vulnerable">
<div class="stat-number" id="vulnerable-requests">0</div>
<div class="stat-label">漏洞请求</div>
</div>
<div class="stat-card unknown">
<div class="stat-number" id="unknown-requests">0</div>
<div class="stat-label">未知状态</div>
</div>
<div class="stat-card safe">
<div class="stat-number" id="safe-requests">0</div>
<div class="stat-label">安全请求</div>
</div>
</div>
<!-- Results Section -->
<div class="results-section">
<div class="results-header">
<h3>漏洞扫描结果</h3>
<div class="filters">
<select class="filter-select" id="filter-type">
<option value="all">所有漏洞类型</option>
<option value="true">漏洞请求</option>
<option value="unknown">未知状态</option>
<option value="false">安全请求</option>
</select>
<select class="filter-select" id="filter-result">
<option value="all">所有检测结果</option>
<option value="true">漏洞请求</option>
<option value="unknown">未知状态</option>
<option value="false">安全请求</option>
</select>
<button class="filter-btn" onclick="filterData()">筛选</button>
</div>
</div>
<table class="data-table">
<thead>
<tr>
<th>Method</th>
<th>URL</th>
<th>Reqbody</th>
<th>RespBodyA</th>
<th>RespBodyB</th>
<th>Result</th>
<th>Reason</th>
<th>Confidence</th>
</tr>
</thead>
<tbody id="data-body">
<!-- 表格数据将通过 JavaScript 动态添加 -->
</tbody>
</table>
<!-- 分页控制 -->
<div class="pagination" id="pagination">
<button onclick="prevPage()" id="prev-btn" disabled>上一页</button>
<span id="page-info">第 1 页,共 1 页</span>
<button onclick="nextPage()" id="next-btn" disabled>下一页</button>
</div>
</div>
</div>
<footer>
© 2025 PrivHunterAI - 高级API安全扫描工具 | 面向未来的安全检测
</footer>
<script>
// 原始数据存储
let originalData = [];
// 当前显示的数据
let currentData = [];
// 分页相关变量
let currentPage = 1;
let itemsPerPage = 10;
let totalPages = 1;
async function fetchData() {
try {
// 从你的接口获取数据
const response = await fetch('/data');
if (!response.ok) throw new Error('Network response was not ok');
originalData = await response.json();
currentData = [...originalData];
// 更新统计信息
updateStatistics();
// 更新分页信息
updatePagination();
// 更新表格数据
updateTableData();
} catch (error) {
console.error('Failed to fetch data:', error);
alert('加载数据失败,请重试');
// 清空表格
document.getElementById('data-body').innerHTML = '';
}
}
function updateStatistics() {
// 更新总数据统计
document.getElementById('total-requests').textContent = originalData.length;
// 计算漏洞请求 (Result为true)
const vulnerableRequests = originalData.filter(item => item.result === "true").length;
document.getElementById('vulnerable-requests').textContent = vulnerableRequests;
// 计算未知状态 (Result为unknown)
const unknownRequests = originalData.filter(item => item.result === 'unknown').length;
document.getElementById('unknown-requests').textContent = unknownRequests;
// 计算安全请求 (Result为false)
const safeRequests = originalData.filter(item => item.result === "false").length;
document.getElementById('safe-requests').textContent = safeRequests;
}
function updateTableData() {
const tableBody = document.getElementById('data-body');
tableBody.innerHTML = '';
// 计算当前页面的数据范围
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = Math.min(startIndex + itemsPerPage, currentData.length);
const paginatedData = currentData.slice(startIndex, endIndex);
// 如果没有数据,显示空状态
if (paginatedData.length === 0) {
const emptyRow = document.createElement('tr');
emptyRow.innerHTML = `
<td colspan="8" class="empty-state">
<i class="fas fa-search"></i>
<p>没有找到符合条件的数据</p>
</td>
`;
tableBody.appendChild(emptyRow);
return;
}
// 渲染当前页面的数据
paginatedData.forEach(item => {
const row = document.createElement('tr');
// 根据结果类型设置行样式
if (item.result === true) {
row.className = 'vulnerable-row';
} else if (item.result === 'unknown') {
row.className = 'unknown-row';
} else if (item.result === false) {
row.className = 'safe-row';
}
row.innerHTML = `
<td>${item.method || '-'}</td>
<td>${item.url || '-'}</td>
<td>${item.reqbody || '-'}</td>
<td>${item.respBodyA || '-'}</td>
<td>${item.respBodyB || '-'}</td>
<td>${item.result === 'unknown' ? '未知' : item.result=== 'false' ? '安全' : '漏洞'}</td>
<td>${item.reason || '-'}</td>
<td>${item.confidence || '-'}</td>
`;
tableBody.appendChild(row);
});
}
function updatePagination() {
// 计算总页数
totalPages = Math.ceil(currentData.length / itemsPerPage);
// 更新页码显示
document.getElementById('page-info').textContent =
`${currentPage} 页,共 ${totalPages}`;
// 更新按钮状态
document.getElementById('prev-btn').disabled = currentPage === 1;
document.getElementById('next-btn').disabled = currentPage === totalPages;
}
function prevPage() {
if (currentPage > 1) {
currentPage--;
updateTableData();
updatePagination();
}
}
function nextPage() {
if (currentPage < totalPages) {
currentPage++;
updateTableData();
updatePagination();
}
}
function filterData() {
const filterType = document.getElementById('filter-type').value;
const filterResult = document.getElementById('filter-result').value;
// 根据筛选条件过滤数据
if (filterType !== 'all') {
if (filterType === 'true') {
currentData = originalData.filter(item => item.result === 'true');
} else if (filterType === 'unknown') {
currentData = originalData.filter(item => item.result === 'unknown');
} else if (filterType === 'false') {
currentData = originalData.filter(item => item.result === 'false');
}
} else if (filterResult !== 'all') {
if (filterResult === 'true') {
currentData = originalData.filter(item => item.result === 'true');
} else if (filterResult === 'unknown') {
currentData = originalData.filter(item => item.result === 'unknown');
} else if (filterResult === 'false') {
currentData = originalData.filter(item => item.result === 'false');
}
} else {
currentData = [...originalData];
}
// 重置页码
currentPage = 1;
// 更新表格数据和分页信息
updateTableData();
updatePagination();
}
// 初始化时尝试获取数据
document.addEventListener('DOMContentLoaded', () => {
fetchData();
});
</script>
</body>
</html>