261c45b4d9
阶段五:性能和安全测试 - 创建负载测试脚本:模拟正常用户访问模式 - 创建压力测试脚本:测试系统极限性能 - 创建SQL注入测试脚本:验证SQL注入防护 - 创建XSS防护测试脚本:验证XSS防护 - 添加测试脚本到package.json 阶段六:文档和培训 - 更新README.md:添加监控和告警文档 - 添加性能测试文档和命令 - 添加安全测试文档和命令 - 添加Docker部署文档 - 添加生产环境配置文档 - 添加备份和恢复文档
99 lines
3.1 KiB
JavaScript
99 lines
3.1 KiB
JavaScript
import http from 'k6/http';
|
|
import { check } from 'k6';
|
|
|
|
export const options = {
|
|
thresholds: {
|
|
checks: ['rate==1.0'], // 所有安全检查必须通过
|
|
},
|
|
};
|
|
|
|
const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000';
|
|
|
|
const xssPayloads = [
|
|
'<script>alert("XSS")</script>',
|
|
'<img src=x onerror=alert("XSS")>',
|
|
'<svg onload=alert("XSS")>',
|
|
'<body onload=alert("XSS")>',
|
|
'<input onfocus=alert("XSS") autofocus>',
|
|
'<select onfocus=alert("XSS") autofocus>',
|
|
'<textarea onfocus=alert("XSS") autofocus>',
|
|
'<keygen onfocus=alert("XSS") autofocus>',
|
|
'<video><source onerror=alert("XSS")>',
|
|
'<audio src=x onerror=alert("XSS")>',
|
|
'<iframe src="javascript:alert("XSS")">',
|
|
'<details open ontoggle=alert("XSS")>',
|
|
'<marquee onstart=alert("XSS")>',
|
|
'<isindex action="javascript:alert("XSS")">',
|
|
'<form><button formaction="javascript:alert("XSS")">X</button></form>',
|
|
'javascript:alert("XSS")',
|
|
'<script>document.location="http://evil.com"</script>',
|
|
'<img src=x onerror="document.location=\'http://evil.com\'">',
|
|
'<svg><script>document.location="http://evil.com"</script></svg>',
|
|
'<script src="http://evil.com/xss.js"></script>',
|
|
'<link rel="stylesheet" href="javascript:alert("XSS")">',
|
|
];
|
|
|
|
export default function () {
|
|
let allPassed = true;
|
|
|
|
xssPayloads.forEach((payload) => {
|
|
const testCases = [
|
|
{
|
|
name: 'Contact Form - XSS',
|
|
url: `${BASE_URL}/api/contact`,
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
name: payload,
|
|
email: 'test@example.com',
|
|
phone: '13800138000',
|
|
message: payload,
|
|
}),
|
|
},
|
|
{
|
|
name: 'Search - XSS',
|
|
url: `${BASE_URL}/api/search?q=${encodeURIComponent(payload)}`,
|
|
method: 'GET',
|
|
},
|
|
];
|
|
|
|
testCases.forEach((testCase) => {
|
|
let res;
|
|
if (testCase.method === 'POST') {
|
|
res = http.post(testCase.url, testCase.body, {
|
|
headers: { 'Content-Type': 'application/json' },
|
|
tags: { name: testCase.name },
|
|
});
|
|
} else {
|
|
res = http.get(testCase.url, {
|
|
tags: { name: testCase.name },
|
|
});
|
|
}
|
|
|
|
const passed = check(res, {
|
|
'status is 200 or 400 or 422': (r) => [200, 400, 422].includes(r.status),
|
|
'XSS payload not reflected in response': (r) => {
|
|
const lowerBody = r.body.toLowerCase();
|
|
return !lowerBody.includes('<script>') &&
|
|
!lowerBody.includes('onerror=') &&
|
|
!lowerBody.includes('onload=') &&
|
|
!lowerBody.includes('onfocus=') &&
|
|
!lowerBody.includes('javascript:') &&
|
|
!lowerBody.includes('document.location');
|
|
},
|
|
'no alert in response': (r) => !r.body.includes('alert('),
|
|
'no iframe in response': (r) => !r.body.includes('<iframe'),
|
|
'no external script in response': (r) => !r.body.includes('http://evil.com'),
|
|
});
|
|
|
|
if (!passed) {
|
|
allPassed = false;
|
|
console.error(`XSS test failed for payload: ${payload}`);
|
|
}
|
|
});
|
|
});
|
|
|
|
if (!allPassed) {
|
|
throw new Error('XSS tests failed');
|
|
}
|
|
}
|