常见WEB安全漏洞及防护措施

在Web应用开发中,安全防护是至关重要的环节。下面我们将详细探讨在java开发中如何防范常见的Web安全漏洞,包括SQL注入、XSS攻击、防盗链、CSRF攻击、文件上传漏洞和DDOS攻击等。

  • SQL注入防护

漏洞原理

SQL注入发生在攻击者能够操纵应用程序的SQL查询结构时。当应用直接将用户输入拼接到SQL语句中,攻击者可以插入恶意SQL片段,执行非授权操作。

特殊场景 ------ ORDER BY注入

在排序场景中,由于ORDER BY子句不能使用预编译参数 (预编译会添加引号),开发者常直接拼接输入,导致漏洞:

// 危险示例:直接拼接排序字段

@Select("SELECT * FROM users ORDER BY {sortField} {sortDirection}")

List<User> findUsersSorted(@Param("sortField") String sortField,

@Param("sortDirection") String sortDirection);

攻击者可传入:sortField="id; DROP TABLE users--" 进行破坏

防护方案

  1. 预编译参数(#{})

// 安全:使用预编译参数

@Select("SELECT * FROM users WHERE username = #{username}")

User findByUsername(@Param("username") String username);

  1. ORDER BY字段白名单验证

// 安全处理ORDER BY

public List<User> findUsersSorted(String sortField, String sortDirection) {

// 定义允许的排序字段

Set<String> allowedFields = Set.of("id", "name", "email", "created_at");

if (!allowedFields.contains(sortField)) {

sortField = "id"; // 默认值

}

// 验证排序方向

if (!"ASC".equalsIgnoreCase(sortDirection) && !"DESC".equalsIgnoreCase(sortDirection)) {

sortDirection = "ASC";

}

// 使用QueryWrapper

QueryWrapper<User> wrapper = new QueryWrapper<>();

wrapper.orderBy(true, "ASC".equalsIgnoreCase(sortDirection), sortField);

return userMapper.selectList(wrapper);

}

  1. MyBatis Plus内置防护

// 使用Lambda表达式避免SQL注入

LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();

lambdaQuery.eq(User::getUsername, username)

.orderByDesc(User::getCreatedAt);

  • XSS(跨站脚本)攻击防护

漏洞原理

攻击者向网页注入恶意脚本,当其他用户浏览该页面时,脚本执行并窃取用户信息或进行恶意操作。

防护方案

  1. 全局XSS过滤器

@Component

public class XssFilter implements Filter {

@Override

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

// 包装原始请求

XssHttpServletRequestWrapper wrappedRequest =

new XssHttpServletRequestWrapper((HttpServletRequest) request);

chain.doFilter(wrappedRequest, response);

}

}

// XSS过滤请求包装器

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

private static final HtmlSanitizer SANITIZER = new HtmlSanitizer.Builder()

.allowStandardUrlProtocols()

.allowElements("a", "b", "blockquote", "br", "caption", "cite", "code", "col",

"colgroup", "dd", "dl", "dt", "em", "h1", "h2", "h3", "h4", "h5",

"h6", "i", "img", "li", "ol", "p", "pre", "q", "small", "strike",

"strong", "sub", "sup", "table", "tbody", "td", "tfoot", "th",

"thead", "tr", "u", "ul")

.allowAttributes("href", "src", "alt", "title", "class")

.onElements("a", "img")

.build();

public XssHttpServletRequestWrapper(HttpServletRequest request) {

super(request);

}

@Override

public String getParameter(String name) {

String value = super.getParameter(name);

return sanitize(value);

}

private String sanitize(String input) {

if (input == null) return null;

return SANITIZER.sanitize(input);

}

}

2. 响应头设置Content Security Policy

// 添加CSP过滤器

@Bean

public FilterRegistrationBean<CspFilter> cspFilter() {

FilterRegistrationBean<CspFilter> registration = new FilterRegistrationBean<>();

registration.setFilter(new CspFilter());

registration.addUrlPatterns("/*");

registration.setName("cspFilter");

return registration;

}

// CSP过滤器实现

public class CspFilter implements Filter {

@Override

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

HttpServletResponse httpResponse = (HttpServletResponse) response;

httpResponse.setHeader("Content-Security-Policy",

"default-src 'self'; script-src 'self' 'unsafe-inline';");

chain.doFilter(request, response);

}

}

3. 前端对用户输入进行转义处理

<template>

<div>

<!-- 安全方式:自动转义HTML -->

<p>{{ userInput }}</p>

<!-- 危险方式:避免使用v-html -->

<div v-html="userInput"></div>

</div>

</template>

<script>

export default {

data() {

return {

userInput: ''

}

},

methods: {

// 清理用户输入

sanitizeInput(input) {

return input

.replace(/&/g, '&')

.replace(/</g, '<')

.replace(/>/g, '>')

.replace(/"/g, '"')

.replace(/'/g, ''');

}

}

}

</script>

  • 防盗链防护

漏洞原理

盗链是指其他网站直接链接到你的静态资源(如图片、视频),消耗你的服务器带宽。

防护方案

  1. Referer检查拦截器

@Component

public class HotlinkInterceptor implements HandlerInterceptor {

private static final Set<String> ALLOWED_DOMAINS = Set.of(

"https://yourdomain.com",

"https://sub.yourdomain.com"

);

@Override

public boolean preHandle(HttpServletRequest request,

HttpServletResponse response,

Object handler) {

// 静态资源请求才检查

String uri = request.getRequestURI();

if (!uri.startsWith("/static/")) {

return true;

}

String referer = request.getHeader("Referer");

if (referer == null) {

// 无Referer时返回错误图片

response.setStatus(HttpStatus.FORBIDDEN.value());

return false;

}

// 检查Referer域名

boolean allowed = ALLOWED_DOMAINS.stream()

.anyMatch(domain -> referer.startsWith(domain));

if (!allowed) {

// 返回替代图片或错误响应

response.sendRedirect("/static/images/anti-hotlink.png");

return false;

}

return true;

}

}

  1. 签名URL(高级防护)

@RestController

@RequestMapping("/protected")

public class ProtectedResourceController {

@GetMapping("/image/{filename}")

public ResponseEntity<Resource> getImage(

@PathVariable String filename,

@RequestParam String signature,

@RequestParam long expires) {

// 1. 验证签名有效性

if (!validateSignature(filename, expires, signature)) {

return ResponseEntity.status(HttpStatus.FORBIDDEN).build();

}

// 2. 验证URL有效期

if (System.currentTimeMillis() > expires) {

return ResponseEntity.status(HttpStatus.GONE).build();

}

// 3. 返回资源

Resource resource = new ClassPathResource("static/images/" + filename);

return ResponseEntity.ok()

.contentType(MediaType.IMAGE_JPEG)

.body(resource);

}

private boolean validateSignature(String filename, long expires, String signature) {

String data = filename + "|" + expires;

String expected = HmacUtils.hmacSha256Hex("SECRET_KEY", data);

return expected.equals(signature);

}

}

  • CSRF(跨站请求伪造)防护

漏洞原理

攻击者诱导用户访问恶意页面,该页面自动向已认证的网站发起请求,利用用户的登录状态执行非授权操作。

防护方案:

使用CSRF Token;设置SameSite Cookie属性;验证Origin/Referer头

// Spring Security配置CSRF防护

@Configuration

@EnableWebSecurity

public class SecurityConfig {

@Bean

public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

http

.csrf(csrf -> csrf

.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

.ignoringRequestMatchers("/api/public/**")

)

.authorizeHttpRequests(auth -> auth

.anyRequest().authenticated()

);

return http.build();

}

}

前端集成CSRF Token:

<template>

<form @submit.prevent="submitForm">

<input type="hidden" name="_csrf" :value="csrfToken">

<!-- 表单内容 -->

</form>

</template>

<script>

import axios from 'axios';

export default {

data() {

return {

csrfToken: ''

};

},

created() {

// 从Cookie中获取CSRF Token

this.csrfToken = this.getCookie('XSRF-TOKEN');

// 设置Axios默认携带CSRF Token

axios.defaults.headers.common['X-XSRF-TOKEN'] = this.csrfToken;

},

methods: {

getCookie(name) {

const value = `; ${document.cookie}`;

const parts = value.split(`; ${name}=`);

if (parts.length === 2) return parts.pop().split(';').shift();

},

submitForm() {

// 表单提交逻辑

}

}

};

</script>

  • 文件上传漏洞

漏洞原理:

攻击者上传恶意文件(如木马、病毒)或超大文件,破坏服务器安全或耗尽资源。

防护方案:

验证文件类型和内容;限制文件大小;重命名上传文件;隔离存储上传文件

// 安全文件上传控制器

@RestController

@RequestMapping("/upload")

public class FileUploadController {

// 允许的文件类型

private static final List<String> ALLOWED_TYPES = Arrays.asList(

"image/jpeg", "image/png", "application/pdf");

@PostMapping

public ResponseEntity<String> uploadFile(

@RequestParam("file") MultipartFile file,

@RequestParam("category") String category) {

try {

// 1. 验证文件大小

if (file.getSize() > 5 * 1024 * 1024) { // 5MB

return ResponseEntity.badRequest().body("File size exceeds limit");

}

// 2. 验证文件类型

String contentType = file.getContentType();

if (!ALLOWED_TYPES.contains(contentType)) {

return ResponseEntity.badRequest().body("Invalid file type");

}

// 3. 验证文件内容(简单示例)

byte[] bytes = file.getBytes();

if (bytes.length < 4) {

return ResponseEntity.badRequest().body("Invalid file content");

}

// 4. 生成安全文件名

String extension = FilenameUtils.getExtension(file.getOriginalFilename());

String safeFilename = UUID.randomUUID() + "." + extension;

Path path = Paths.get("/secure/upload/dir", category, safeFilename);

// 5. 保存文件

Files.createDirectories(path.getParent());

Files.write(path, bytes);

return ResponseEntity.ok("File uploaded successfully");

} catch (IOException e) {

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)

.body("File upload failed");

}

}

}

  • DDOS攻击(分布式拒绝服务攻击)

漏洞原理:

攻击者使用大量受控机器向目标服务器发送海量请求,耗尽服务器资源,导致服务不可用。

防护方案:

配置Web服务器限流;实现应用层限流;使用缓存减轻压力

// 基于Redis的限流器

@Component

public class RateLimiter {

@Autowired

private RedisTemplate<String, String> redisTemplate;

public boolean allowRequest(String ip, String endpoint, int limit, int windowInSeconds) {

String key = "rate_limit:" + endpoint + ":" + ip;

long now = System.currentTimeMillis();

long window = windowInSeconds * 1000L;

// 使用Redis事务确保原子性

return redisTemplate.execute(new SessionCallback<Boolean>() {

@Override

public Boolean execute(RedisOperations operations) {

operations.multi();

// 1. 删除时间窗口外的记录

operations.opsForZSet().removeRangeByScore(key, 0, now - window);

// 2. 获取当前请求数

Long count = operations.opsForZSet().zCard(key);

// 3. 添加当前请求

operations.opsForZSet().add(key, UUID.randomUUID().toString(), now);

// 4. 设置过期时间

operations.expire(key, windowInSeconds + 1, TimeUnit.SECONDS);

operations.exec();

return count != null && count < limit;

}

});

}

}

// 限流拦截器

@Component

public class RateLimitInterceptor implements HandlerInterceptor {

@Autowired

private RateLimiter rateLimiter;

@Override

public boolean preHandle(HttpServletRequest request,

HttpServletResponse response,

Object handler) throws Exception {

String ip = request.getRemoteAddr();

String path = request.getRequestURI();

// 每IP每秒最多10次请求

if (!rateLimiter.allowRequest(ip, path, 10, 1)) {

response.sendError(HttpStatus.TOO_MANY_REQUESTS.value(), "Too many requests");

return false;

}

return true;

}

}

总结:

在JAVA开发中,Web安全防护需要从多个层面进行考虑:

  1. 输入验证:对所有用户输入进行严格验证
  2. 访问控制:实施严格的权限管理和资源访问控制
  3. 会话管理:使用安全的会话管理机制
  4. 加密传输:确保数据传输过程中的安全
  5. 错误处理:避免暴露系统内部信息
  6. 安全审计:记录安全相关事件

通过实施这些防护措施,可以显著提高Web应用的安全性,保护用户数据和系统资源免受攻击。安全是一个持续的过程,需要定期审查和更新防护策略以应对新的威胁。

相关推荐
你的人类朋友9 小时前
什么是API签名?
前端·后端·安全
深盾安全14 小时前
ProGuard混淆在Android程序中的应用
安全
CYRUS_STUDIO15 小时前
利用 Linux 信号机制(SIGTRAP)实现 Android 下的反调试
android·安全·逆向
白帽黑客沐瑶20 小时前
【网络安全就业】信息安全专业的就业前景(非常详细)零基础入门到精通,收藏这篇就够了
网络·安全·web安全·计算机·程序员·编程·网络安全就业
深盾安全20 小时前
符号执行技术实践-求解程序密码
安全
贾维思基21 小时前
被监管警告后,我连夜给系统上了“双保险”!
安全
00后程序员张1 天前
iOS App 混淆与加固对比 源码混淆与ipa文件混淆的区别、iOS代码保护与应用安全场景最佳实践
android·安全·ios·小程序·uni-app·iphone·webview
Devil枫1 天前
鸿蒙深链落地实战:从安全解析到异常兜底的全链路设计
安全·华为·harmonyos
lubiii_1 天前
网络安全渗透测试第一步信息收集
安全·web安全·网络安全
你的人类朋友1 天前
🔒什么是HMAC
后端·安全·程序员