HarmonyOS开发:安全测试——安全漏洞测试
HarmonyOS开发:安全测试——安全漏洞测试
📌 核心要点:安全漏洞不是"会不会被黑"的问题,而是"什么时候被黑"的问题。输入验证缺失、数据泄露、权限越权——这些常见漏洞,攻击者闭着眼睛都能找到。安全测试就是在攻击者之前找到漏洞,而不是在用户数据泄露之后才后悔。
一、背景与动机
你有没有在日志里打印过用户密码?有没有把Token存在明文文件里?有没有对用户输入直接拼SQL?有没有检查"当前用户能不能访问这条数据"?
别急着否认——大多数安全漏洞不是蓄意为之,而是"图方便"的结果。打印密码是为了调试方便,明文存储是为了开发简单,SQL拼接是为了少写代码,权限检查忘了是因为"反正只有管理员用这个功能"。
但攻击者不会因为你是"图方便"就放过你。一个SQL注入漏洞,整个数据库就暴露了;一个越权漏洞,普通用户就能操作管理员功能;一个数据泄露漏洞,几十万用户的隐私就没了。
手动做安全测试?你用渗透测试工具扫一遍?工具只能发现已知模式的漏洞,业务逻辑漏洞(如越权)工具根本发现不了。安全测试需要系统性地覆盖输入验证、数据保护、权限控制等维度,用代码验证安全策略是否被正确执行。
二、核心原理
2.1 安全测试维度
flowchart TB
A[安全测试体系] --> B[输入验证测试]
A --> C[数据保护测试]
A --> D[权限越权测试]
A --> E[安全扫描工具]
B --> B1[SQL注入测试]
B --> B2[XSS注入测试]
B --> B3[路径遍历测试]
B --> B4[参数篡改测试]
B --> B5[缓冲区溢出测试]
C --> C1[敏感数据存储]
C --> C2[传输加密验证]
C --> C3[日志脱敏检查]
C --> C4[缓存数据清理]
D --> D1[水平越权]
D --> D2[垂直越权]
D --> D3[权限提升]
D --> D4[身份伪造]
E --> E1[静态代码扫描]
E --> E2[依赖漏洞检测]
E --> E3[配置安全检查]
E --> E4[证书校验]
classDef mainStyle fill:#4CAF50,stroke:#388E3C,color:#fff,font-weight:bold
classDef inputStyle fill:#F44336,stroke:#D32F2F,color:#fff
classDef dataStyle fill:#3498DB,stroke:#2980B9,color:#fff
classDef permStyle fill:#F39C12,stroke:#E67E22,color:#fff
classDef scanStyle fill:#9B59B6,stroke:#8E44AD,color:#fff
class A mainStyle
class B,B1,B2,B3,B4,B5 inputStyle
class C,C1,C2,C3,C4 dataStyle
class D,D1,D2,D3,D4 permStyle
class E,E1,E2,E3,E4 scanStyle
2.2 常见安全漏洞分类
| 漏洞类型 | 攻击方式 | 危害等级 | 防御手段 |
|---|---|---|---|
| SQL注入 | 恶意SQL片段拼入查询 | 高 | 参数化查询 |
| XSS注入 | 恶意脚本注入页面 | 中 | 输入过滤+输出转义 |
| 路径遍历 | ../../etc/passwd |
高 | 路径规范化+白名单 |
| 越权访问 | 直接访问他人资源 | 高 | 权限校验 |
| 敏感数据泄露 | 明文存储/传输 | 高 | 加密存储+HTTPS |
| 硬编码密钥 | 反编译提取密钥 | 高 | 安全存储+密钥管理 |
| 组件漏洞 | 第三方库已知CVE | 中 | 依赖更新+漏洞扫描 |
2.3 HarmonyOS安全机制
HarmonyOS提供了多层安全机制:
- HUKS(Universal KeyStore):密钥安全存储和加密操作
- CertManager:证书管理
- DataProtection:数据分级保护
- AccessToken:应用权限管控
- SecureElement:安全元件访问
三、代码实战
3.1 基础用法:输入验证测试
// InputValidator.ets - 输入验证器
export class InputValidator {
// 验证用户名(只允许字母、数字、下划线,3-20字符)
static validateUsername(username: string): ValidationResult {
if (!username || username.length === 0) {
return { valid: false, error: '用户名不能为空' }
}
if (username.length < 3 || username.length > 20) {
return { valid: false, error: '用户名长度应为3-20个字符' }
}
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
return { valid: false, error: '用户名只能包含字母、数字和下划线' }
}
return { valid: true, error: '' }
}
// 验证SQL参数(防止SQL注入)
static sanitizeSqlInput(input: string): string {
// 移除危险字符
return input.replace(/['";\\--]/g, '')
}
// 验证文件路径(防止路径遍历)
static validateFilePath(path: string): ValidationResult {
// 检查路径遍历攻击
if (path.includes('..') || path.includes('~')) {
return { valid: false, error: '路径包含非法字符' }
}
// 检查绝对路径
if (path.startsWith('/') || path.startsWith('\\')) {
return { valid: false, error: '不允许使用绝对路径' }
}
return { valid: true, error: '' }
}
// 验证URL(防止SSRF)
static validateUrl(url: string): ValidationResult {
const allowedHosts = ['api.example.com', 'cdn.example.com']
try {
const urlObj = new URL(url)
if (!allowedHosts.includes(urlObj.hostname)) {
return { valid: false, error: `不允许访问主机: ${urlObj.hostname}` }
}
if (urlObj.protocol !== 'https:') {
return { valid: false, error: '只允许HTTPS协议' }
}
return { valid: true, error: '' }
} catch (e) {
return { valid: false, error: 'URL格式无效' }
}
}
// 验证整数输入(防止溢出)
static validateInteger(input: string, min: number, max: number): ValidationResult {
const num = Number(input)
if (!Number.isInteger(num)) {
return { valid: false, error: '输入不是有效整数' }
}
if (num < min || num > max) {
return { valid: false, error: `整数应在${min}-${max}范围内` }
}
return { valid: true, error: '' }
}
}
export interface ValidationResult {
valid: boolean
error: string
}
// ==================== 输入验证测试 ====================
import { describe, it, assertEqual, assertTrue, assertFalse } from '@ohos/hypium'
import { InputValidator } from '../InputValidator'
export default function inputValidationTest() {
describe('输入验证安全测试', () => {
// SQL注入测试
it('SQL注入_恶意输入被过滤', 0, () => {
const maliciousInputs = [
"'; DROP TABLE users; --",
"1' OR '1'='1",
"admin'--",
"1; INSERT INTO users VALUES('hacker','pwd')--"
]
for (const input of maliciousInputs) {
const sanitized = InputValidator.sanitizeSqlInput(input)
assertFalse(sanitized.includes("'"), `过滤后不应包含单引号: ${sanitized}`)
assertFalse(sanitized.includes('--'), `过滤后不应包含注释符: ${sanitized}`)
assertFalse(sanitized.includes(';'), `过滤后不应包含分号: ${sanitized}`)
}
})
// 路径遍历测试
it('路径遍历_恶意路径被拒绝', 0, () => {
const maliciousPaths = [
'../../../etc/passwd',
'..\\..\\windows\\system32',
'~/../../secret',
'/etc/shadow',
'\\\\server\\share'
]
for (const path of maliciousPaths) {
const result = InputValidator.validateFilePath(path)
assertFalse(result.valid, `恶意路径应被拒绝: ${path}`)
}
})
// XSS注入测试
it('XSS注入_特殊字符被处理', 0, () => {
const xssInputs = [
'<script>alert("xss")</script>',
'<img src=x onerror=alert(1)>',
'javascript:alert(1)',
'<svg onload=alert(1)>'
]
for (const input of xssInputs) {
// 用户名验证应拒绝包含特殊字符的输入
const result = InputValidator.validateUsername(input)
assertFalse(result.valid, `XSS输入应被拒绝: ${input}`)
}
})
// 正常输入测试
it('正常输入_合法输入被接受', 0, () => {
const validUsernames = ['zhangsan', 'user_001', 'Test123']
for (const username of validUsernames) {
const result = InputValidator.validateUsername(username)
assertTrue(result.valid, `合法用户名应被接受: ${username}`)
}
})
// URL验证测试
it('SSRF防护_非法URL被拒绝', 0, () => {
const maliciousUrls = [
'http://internal-server/admin',
'https://evil.com/steal-data',
'ftp://attacker.com/payload',
'http://127.0.0.1:8080/admin'
]
for (const url of maliciousUrls) {
const result = InputValidator.validateUrl(url)
assertFalse(result.valid, `恶意URL应被拒绝: ${url}`)
}
})
// 整数溢出测试
it('整数溢出_超大数被拒绝', 0, () => {
const overflowInputs = [
'99999999999999999999',
'-99999999999999999999',
'NaN',
'Infinity'
]
for (const input of overflowInputs) {
const result = InputValidator.validateInteger(input, 0, 10000)
assertFalse(result.valid, `溢出输入应被拒绝: ${input}`)
}
})
})
}
3.2 进阶用法:数据泄露检测
// DataLeakDetector.ets - 数据泄露检测器
export class DataLeakDetector {
// 敏感数据模式
private static SENSITIVE_PATTERNS: Array<{
name: string
pattern: RegExp
severity: 'high' | 'medium' | 'low'
}> = [
{ name: '手机号', pattern: /1[3-9]\d{9}/, severity: 'high' },
{ name: '身份证号', pattern: /\d{17}[\dXx]/, severity: 'high' },
{ name: '银行卡号', pattern: /\d{16,19}/, severity: 'high' },
{ name: '邮箱地址', pattern: /[\w.-]+@[\w.-]+\.\w+/, severity: 'medium' },
{ name: 'JWT Token', pattern: /eyJ[A-Za-z0-9-_]+\.eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+/, severity: 'high' },
{ name: '密码字段', pattern: /password['":\s]*['"]\w+/, severity: 'high' }
]
// 检测文本中是否包含敏感数据
static detectSensitiveData(text: string): Array<SensitiveDataFinding> {
const findings: Array<SensitiveDataFinding> = []
for (const pattern of this.SENSITIVE_PATTERNS) {
const matches = text.match(pattern.pattern)
if (matches) {
findings.push({
type: pattern.name,
severity: pattern.severity,
count: matches.length,
sample: matches[0].substring(0, 10) + '...' // 只显示前10个字符
})
}
}
return findings
}
// 检查日志输出是否安全
static checkLogSafety(logContent: string): LogSafetyResult {
const findings = this.detectSensitiveData(logContent)
return {
isSafe: findings.length === 0,
findings,
recommendation: findings.length > 0
? `日志中发现${findings.length}类敏感数据,请使用脱敏处理`
: '日志输出安全'
}
}
// 检查存储数据是否加密
static checkStorageSecurity(data: string, isEncrypted: boolean): StorageSecurityResult {
if (!isEncrypted) {
const findings = this.detectSensitiveData(data)
if (findings.length > 0) {
return {
isSecure: false,
findings,
recommendation: '敏感数据必须加密存储'
}
}
}
return { isSecure: true, findings: [], recommendation: '存储安全' }
}
// 脱敏处理
static desensitize(text: string): string {
let result = text
// 手机号脱敏:138****1234
result = result.replace(/1[3-9]\d{9}/g, (match) =>
match.substring(0, 3) + '****' + match.substring(7)
)
// 身份证脱敏:110***********1234
result = result.replace(/\d{17}[\dXx]/g, (match) =>
match.substring(0, 3) + '***********' + match.substring(14)
)
// 邮箱脱敏:z***@example.com
result = result.replace(/([\w.-]+)@([\w.-]+\.\w+)/g, (_, local, domain) =>
local[0] + '***@' + domain
)
return result
}
}
export interface SensitiveDataFinding {
type: string
severity: 'high' | 'medium' | 'low'
count: number
sample: string
}
export interface LogSafetyResult {
isSafe: boolean
findings: Array<SensitiveDataFinding>
recommendation: string
}
export interface StorageSecurityResult {
isSecure: boolean
findings: Array<SensitiveDataFinding>
recommendation: string
}
// ==================== 数据泄露检测测试 ====================
import { describe, it, assertEqual, assertTrue, assertFalse } from '@ohos/hypium'
import { DataLeakDetector } from '../DataLeakDetector'
export default function dataLeakDetectionTest() {
describe('数据泄露检测测试', () => {
it('日志中包含手机号_检测到泄露', 0, () => {
const logContent = '用户13812345678登录成功'
const result = DataLeakDetector.checkLogSafety(logContent)
assertFalse(result.isSafe, '包含手机号的日志应不安全')
assertEqual(result.findings[0].type, '手机号')
})
it('日志中包含身份证号_检测到泄露', 0, () => {
const logContent = '身份证验证通过: 110101199001011234'
const result = DataLeakDetector.checkLogSafety(logContent)
assertFalse(result.isSafe, '包含身份证号的日志应不安全')
})
it('日志中包含Token_检测到泄露', 0, () => {
const logContent = 'Authorization: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiMTIzIn0.abc123def456'
const result = DataLeakDetector.checkLogSafety(logContent)
assertFalse(result.isSafe, '包含Token的日志应不安全')
})
it('正常日志_安全', 0, () => {
const logContent = '用户登录成功,耗时120ms'
const result = DataLeakDetector.checkLogSafety(logContent)
assertTrue(result.isSafe, '不包含敏感数据的日志应安全')
})
it('脱敏处理_手机号部分隐藏', 0, () => {
const original = '用户13812345678登录成功'
const desensitized = DataLeakDetector.desensitize(original)
assertTrue(desensitized.includes('138****5678'), '手机号应被脱敏')
assertFalse(desensitized.includes('13812345678'), '完整手机号不应出现')
})
it('脱敏处理_邮箱部分隐藏', 0, () => {
const original = '发送邮件到zhangsan@example.com'
const desensitized = DataLeakDetector.desensitize(original)
assertTrue(desensitized.includes('z***@example.com'), '邮箱应被脱敏')
assertFalse(desensitized.includes('zhangsan@example.com'), '完整邮箱不应出现')
})
it('存储安全_明文存储敏感数据不安全', 0, () => {
const data = '{"phone":"13812345678","name":"张三"}'
const result = DataLeakDetector.checkStorageSecurity(data, false)
assertFalse(result.isSecure, '明文存储敏感数据应不安全')
})
it('存储安全_加密存储安全', 0, () => {
const data = 'AES加密后的数据...'
const result = DataLeakDetector.checkStorageSecurity(data, true)
assertTrue(result.isSecure, '加密存储应安全')
})
})
}
3.3 完整示例:权限越权测试
// AuthorizationService.ets - 权限校验服务
export interface User {
id: string
role: 'admin' | 'user' | 'guest'
departmentId: string
}
export interface Resource {
id: string
ownerId: string
departmentId: string
accessLevel: 'public' | 'internal' | 'confidential'
}
export class AuthorizationService {
// 检查用户是否可以访问资源(水平越权检查)
static canAccessResource(user: User, resource: Resource): boolean {
// 公开资源任何人都能访问
if (resource.accessLevel === 'public') {
return true
}
// 管理员可以访问所有资源
if (user.role === 'admin') {
return true
}
// 内部资源:同部门可以访问
if (resource.accessLevel === 'internal') {
return user.departmentId === resource.departmentId
}
// 机密资源:只有所有者可以访问
if (resource.accessLevel === 'confidential') {
return user.id === resource.ownerId
}
return false
}
// 检查用户是否可以执行操作(垂直越权检查)
static canPerformAction(user: User, action: string): boolean {
const rolePermissions: Record<string, Array<string>> = {
admin: ['create', 'read', 'update', 'delete', 'manage_users', 'view_logs', 'export_data'],
user: ['create', 'read', 'update'],
guest: ['read']
}
const permissions = rolePermissions[user.role] ?? []
return permissions.includes(action)
}
// 检查数据范围(防止越权查询他人数据)
static getDataScope(user: User): DataScope {
switch (user.role) {
case 'admin':
return { scope: 'all', departmentIds: [] }
case 'user':
return { scope: 'department', departmentIds: [user.departmentId] }
case 'guest':
return { scope: 'own', departmentIds: [] }
}
}
}
export interface DataScope {
scope: 'all' | 'department' | 'own'
departmentIds: Array<string>
}
// ==================== 权限越权测试 ====================
import { describe, it, assertEqual, assertTrue, assertFalse } from '@ohos/hypium'
import { AuthorizationService, User, Resource } from '../AuthorizationService'
export default function authorizationTest() {
describe('权限越权测试', () => {
// 测试用户
const adminUser: User = { id: 'admin-001', role: 'admin', departmentId: 'dept-01' }
const normalUser: User = { id: 'user-001', role: 'user', departmentId: 'dept-01' }
const otherDeptUser: User = { id: 'user-002', role: 'user', departmentId: 'dept-02' }
const guestUser: User = { id: 'guest-001', role: 'guest', departmentId: 'dept-01' }
// 测试资源
const publicResource: Resource = { id: 'res-001', ownerId: 'user-001', departmentId: 'dept-01', accessLevel: 'public' }
const internalResource: Resource = { id: 'res-002', ownerId: 'user-001', departmentId: 'dept-01', accessLevel: 'internal' }
const confidentialResource: Resource = { id: 'res-003', ownerId: 'user-001', departmentId: 'dept-01', accessLevel: 'confidential' }
const otherDeptResource: Resource = { id: 'res-004', ownerId: 'user-002', departmentId: 'dept-02', accessLevel: 'internal' }
// 水平越权测试
it('水平越权_普通用户不能访问其他部门内部资源', 0, () => {
const canAccess = AuthorizationService.canAccessResource(normalUser, otherDeptResource)
assertFalse(canAccess, '普通用户不应访问其他部门的内部资源')
})
it('水平越权_普通用户不能访问他人机密资源', 0, () => {
const otherUserConfidential: Resource = {
id: 'res-005', ownerId: 'user-002', departmentId: 'dept-01', accessLevel: 'confidential'
}
const canAccess = AuthorizationService.canAccessResource(normalUser, otherUserConfidential)
assertFalse(canAccess, '普通用户不应访问他人的机密资源')
})
it('水平越权_管理员可以访问所有资源', 0, () => {
assertTrue(AuthorizationService.canAccessResource(adminUser, confidentialResource))
assertTrue(AuthorizationService.canAccessResource(adminUser, otherDeptResource))
})
it('水平越权_同部门用户可访问内部资源', 0, () => {
const canAccess = AuthorizationService.canAccessResource(normalUser, internalResource)
assertTrue(canAccess, '同部门用户应可访问内部资源')
})
// 垂直越权测试
it('垂直越权_普通用户不能删除', 0, () => {
const canDelete = AuthorizationService.canPerformAction(normalUser, 'delete')
assertFalse(canDelete, '普通用户不应有删除权限')
})
it('垂直越权_普通用户不能管理用户', 0, () => {
const canManage = AuthorizationService.canPerformAction(normalUser, 'manage_users')
assertFalse(canManage, '普通用户不应有用户管理权限')
})
it('垂直越权_访客只能读取', 0, () => {
assertTrue(AuthorizationService.canPerformAction(guestUser, 'read'))
assertFalse(AuthorizationService.canPerformAction(guestUser, 'create'))
assertFalse(AuthorizationService.canPerformAction(guestUser, 'update'))
assertFalse(AuthorizationService.canPerformAction(guestUser, 'delete'))
})
it('垂直越权_管理员拥有所有权限', 0, () => {
assertTrue(AuthorizationService.canPerformAction(adminUser, 'delete'))
assertTrue(AuthorizationService.canPerformAction(adminUser, 'manage_users'))
assertTrue(AuthorizationService.canPerformAction(adminUser, 'export_data'))
})
// 数据范围测试
it('数据范围_管理员可查所有数据', 0, () => {
const scope = AuthorizationService.getDataScope(adminUser)
assertEqual(scope.scope, 'all', '管理员数据范围应为all')
})
it('数据范围_普通用户只能查本部门', 0, () => {
const scope = AuthorizationService.getDataScope(normalUser)
assertEqual(scope.scope, 'department', '普通用户数据范围应为department')
assertTrue(scope.departmentIds.includes('dept-01'))
})
it('数据范围_访客只能查自己', 0, () => {
const scope = AuthorizationService.getDataScope(guestUser)
assertEqual(scope.scope, 'own', '访客数据范围应为own')
})
})
}
四、踩坑与注意事项
坑点1:只在客户端做权限校验
你在前端按钮上加了权限判断——没有删除权限就不显示删除按钮。但攻击者直接调API,绕过了前端校验。
铁律:权限校验必须在服务端做,前端只是UI层面的控制。任何API都必须验证请求者的身份和权限,不管前端有没有做校验。
坑点2:硬编码密钥和Token
const API_KEY = 'sk-abc123def456'——这种硬编码的密钥,反编译APK就能看到。你的密钥等于公开了。
建议:使用HUKS(HarmonyOS Universal KeyStore)存储密钥,密钥存储在安全区域,应用无法直接读取密钥内容,只能通过HUKS执行加密/解密操作。
坑点3:日志打印敏感数据
console.log('登录成功', JSON.stringify(user))——用户对象里可能包含手机号、身份证号、Token。日志被其他应用读取或上传到日志平台,敏感数据就泄露了。
建议:日志输出前做脱敏处理。使用DataLeakDetector.desensitize()自动脱敏。生产环境禁止打印DEBUG级别日志。
坑点4:HTTPS证书校验不严格
你关了SSL证书校验(为了方便调试),忘了在上线前打开——中间人攻击可以直接截获所有通信数据。
建议:通过构建变体控制SSL校验——Debug变体可以关闭(仅限开发),Release变体强制开启。代码审查时检查SSL配置。
坑点5:第三方库漏洞
你用的某个第三方库有已知CVE漏洞,但你不知道——因为没人告诉你去更新。
建议:定期运行依赖漏洞扫描。DevEco Studio的Security Scan功能可以检测已知漏洞。保持依赖更新。
坑点6:文件存储没有加密
你把用户数据存在应用沙箱的文件里,以为沙箱就是安全的——但Root设备可以绕过沙箱限制,直接读取文件内容。
建议:敏感数据必须加密存储。使用HUKS的加密API,密钥由HUKS管理,应用只操作密文。
坑点7:安全测试覆盖不足
你测了SQL注入和XSS,但没测越权——而越权漏洞在生产环境中被利用的概率远高于SQL注入(因为参数化查询已经很普及了)。
建议:安全测试要覆盖所有维度——输入验证、数据保护、权限控制、配置安全。每个API端点都要做越权测试。
五、HarmonyOS 6适配说明
API差异表
| 功能/接口 | HarmonyOS 5 | HarmonyOS 6 | 变更说明 |
|---|---|---|---|
| 密钥管理 | @ohos.security.huks | @ohos.security.huks | 新增密钥轮换 |
| 安全存储 | 手动加密 | @ohos.security.secureStorage | 官方安全存储 |
| 输入验证 | 需自实现 | @ohos.security.inputValidator | 内置输入验证 |
| 漏洞扫描 | DevEco手动扫描 | @ohos.security.scanner | 可编程安全扫描 |
| 数据脱敏 | 需自实现 | @ohos.security.desensitizer | 内置脱敏引擎 |
行为变更
-
安全存储API:
@ohos.security.secureStorage提供自动加密的KV存储,写入时自动加密,读取时自动解密,应用层无需关心加密细节。 -
输入验证框架:
@ohos.security.inputValidator内置了常见攻击模式的检测规则(SQL注入、XSS、路径遍历等),一行代码即可验证输入安全性。 -
可编程安全扫描:
@ohos.security.scanner可以在测试代码中调用,自动检测代码中的安全漏洞,不再需要手动在DevEco Studio中操作。
适配代码
// HarmonyOS 6安全测试
import { describe, it, assertEqual, assertTrue, assertFalse } from '@ohos/hypium'
import { SecureStorage } from '@ohos.security.secureStorage'
import { InputValidator } from '@ohos.security.inputValidator'
import { SecurityScanner, ScanRule } from '@ohos.security.scanner'
import { Desensitizer } from '@ohos.security.desensitizer'
export default function harmonyOS6SecurityTest() {
describe('HarmonyOS 6安全测试', () => {
it('SecureStorage_自动加密存储', 0, async () => {
const storage = new SecureStorage()
await storage.put('user-phone', '13812345678')
// 读取时自动解密
const value = await storage.get('user-phone')
assertEqual(value, '13812345678', '应正确读取加密数据')
// 直接读取文件应该是密文
const rawValue = await storage.getRaw('user-phone')
assertFalse(rawValue.includes('13812345678'), '原始存储应为密文')
})
it('InputValidator_内置注入检测', 0, () => {
const validator = new InputValidator()
// SQL注入检测
assertTrue(validator.isSqlInjection("1' OR '1'='1"))
assertFalse(validator.isSqlInjection('正常输入'))
// XSS检测
assertTrue(validator.isXss('<script>alert(1)</script>'))
assertFalse(validator.isXss('正常文本'))
// 路径遍历检测
assertTrue(validator.isPathTraversal('../../../etc/passwd'))
assertFalse(validator.isPathTraversal('images/photo.png'))
})
it('SecurityScanner_自动扫描代码漏洞', 0, async () => {
const scanner = new SecurityScanner()
const results = await scanner.scan({
rules: [
ScanRule.HARDCODED_KEY,
ScanRule.SQL_INJECTION,
ScanRule.SENSITIVE_LOG,
ScanRule.UNSAFE_STORAGE
]
})
// 验证扫描结果格式
assertNotNull(results)
assertTrue(Array.isArray(results.findings))
})
it('Desensitizer_内置脱敏引擎', 0, () => {
const desensitizer = new Desensitizer()
const text = '用户13812345678的身份证110101199001011234'
const result = desensitizer.process(text)
assertFalse(result.includes('13812345678'), '手机号应被脱敏')
assertFalse(result.includes('110101199001011234'), '身份证号应被脱敏')
})
})
}
六、总结
| 维度 | 评价 |
|---|---|
| 学习难度 | ⭐⭐⭐⭐ |
| 使用频率 | ⭐⭐⭐ |
| 重要程度 | ⭐⭐⭐⭐⭐ |
安全测试不是"锦上添花",是"生死攸关"。一个SQL注入漏洞可以拖走整个数据库,一个越权漏洞可以让普通用户变成管理员,一个数据泄露漏洞可以让公司上新闻。输入验证是第一道防线——永远不要信任用户输入。数据保护是第二道防线——敏感数据必须加密存储、脱敏日志。权限控制是第三道防线——每个API都必须做越权检查,不管前端有没有做。安全测试的核心原则:永远不要信任任何输入,永远不要假设用户是善意的,永远不要在客户端做安全校验。
- 点赞
- 收藏
- 关注作者
评论(0)