在基於Spring Boot的應用程式中是否可以實現漏洞或資源洩漏

基于最新的Spring Boot框架的应用程序,是否可以插入漏洞或资源泄露?如果可以,那么如何实现才会导致问题?

我实际进行了验证。

验证方式

我们使用Spring Boot作为基础,确认了是否能够制作一个基于旧有技术,充满bug的Web应用程序「EasyBuggy」的克隆版本,并且能够同样实现所有的bug。

最终结果(是否实施)

从结果来看,即使使用Spring Boot进行开发,也可以制造出所有的错误。

migration.png
※このアプリは「EasyBuggy Boot」という名前でGitHubに公開しました。詳細については、こちらのページを参照して下さい。

大多数的漏洞制造起来并不困难,但有一些无法在一般配置下实现或实施困难的漏洞,还有一些需要稍作修改才能实施的漏洞。

每个结果如下所示。对于没有任何特别说明的错误,可以在不考虑是否使用基于Spring Boot的开发的情况下解决,因为它是由Java逻辑问题引起的。对于”可否”标记为”△”的项目,考虑到其使用了不推荐的技术、旧版本或者通过特定方法实现了,因此在通常的Spring Boot配置下,可能构建的可能性较低。

バグ可否特記事項デッドロック (Java)○
デッドロック (SQL)○明示的にトランザクション管理することで実現。完了しないプロセスの待機○
無限ループ○
メモリリーク (Javaヒープ領域)○
メモリリーク (パーマネント領域/MetaSpace)○
メモリリーク (Cヒープ領域)○
ネットワークソケットリーク○
データベースコネクションリーク○Spring JDBCにはプールからコネクションを取得するメソッドがあるので、それを利用。ファイルディスクリプタリーク○
スレッドリーク○
文字化け○デフォルトで、文字コードに関する煩わしい問題が発生しないような仕組みになっている。そのため、文字化けは発生しにくいが、文字コードを変更する方法は提供されている。整数オーバーフロー○
丸め誤差○
打ち切り誤差○
情報落ち○
XSS (クロスサイトスクリプティング)○Thymeleafを使っていれば、XSSは簡単に実現可能。SQLインジェクション○Spring JDBCを使っていても、SQLの文字列にユーザーの入力値を連結すれば実現できる。LDAPインジェクション○Spring LDAPのメソッドが、LDAPインジェクションの対象となる文字をエスケープしていなかったので、それを利用。コードインジェクション○
OSコマンドインジェクション○
メールヘッダーインジェクション△古いバージョンのJavaMailでSpring Mailをオーバーライドして実現。Nullバイトインジェクション△バージョン1.7.0_40より前のJavaを使用することで実現可能。サイズ制限の無いファイルアップロード△application.propertiesで明示的にサイズ制限を無効(またはそれと同等に大きな値)にできる。拡張子制限の無いファイルアップロード○
オープンリダイレクト可能なログイン画面○
ブルートフォース攻撃可能なログイン画面○
セッション固定攻撃可能なログイン画面○Spring Scurityのセッション固定攻撃の抑止機能を正しく実装しなければ、実現可能。親切過ぎる認証エラーメッセージ○
危険なファイルインクルード△ThymeleafではなくをJSPを使用することで実現。パストラバーサル△ThymeleafではなくをJSPを使用することで実現。意図しないファイル公開△ディレクリリスティングを有効にすれば可能。CSRF (クロスサイトリクエストフォージェリ)○Spring ScurityのCSRF攻撃の抑止機能を正しく実装しなければ、実現可能。クリックジャッキング○Spring Scurityのクリックジャッキングの抑止機能を正しく実装しなければ、実現可能。XEE (XMLエンティティ拡張)○
XXE (XML外部エンティティ)○
正規表現解析による遅延○
プラス演算子による文字列結合の遅延○
不必要なオブジェクト生成による遅延○

在EasyBuggy中,我们实现了一键触发NullPointerException等异常和OutOfMemoryError等错误的功能。然而,由于这些问题都是与Java逻辑相关的,不论是否使用Spring Boot,您都可以进行调整和修复。

说明

我会稍微详细解释一下。关于实现方式,我认为最好是参考实际的源代码。

死锁 (SQL)

通过使用PlatformTransactionManager或者注解@Transactional来显式地实现事务管理,如果多个线程以相反的顺序更新记录,则可以实现死锁。

数据库连接泄漏

使用Spring JDBC时,基本上不需要直接从连接池中获取连接。然而,并非无法做到这一点,因为仍然存在用于获取连接的方法,因此可以利用该方法创建连接泄漏。

乱码

意外而且在实施过程中有困难的是乱码问题。我原以为通过在Servlet过滤器中将字符编码更改为适当的编码就会出现乱码问题,但实际尝试后并没有出现乱码。通过继承OrderedCharacterEncodingFilter类,调用super.setEncoding(“[适当的字符编码]”)方法可以更改字符编码为除UTF-8以外的其他编码,从而引发乱码问题。

跨站脚本攻击(XSS)

如果使用Thymeleaf的th:utext,将不会进行任何的转义处理,因此很容易实现XSS攻击。

SQL注入

因为SQL的字符串可以进行连接,所以即使使用Spring JDBC,也无法避免SQL注入。

LDAP注入

我使用了Spring LDAP,但是有一个方法没有对LDAP过滤器的字符串进行转义。起初我以为这是实现过程中的一个错误,导致转义处理被遗漏。但是当我阅读LdapQuery.filter(String)的Javadoc时发现,其中提到不进行转义。

/**
 * Specify a hardcoded filter. Please note that using this method, the filter string will not be
 * validated or escaped in any way. <b>Never</b> use direct user input and use it concatenating strings
 * to use as LDAP filters. Doing so opens up for &quot;LDAP injection&quot;, where malicious user
 * may inject specifically constructed data to form filters at their convenience. When user input is used
 * consider using {@link #where(String)} or {@link #filter(String, Object...)} instead.
 *
 * @param hardcodedFilter The hardcoded filter string to use in the search.
 * @return this instance.
 * @throws IllegalStateException if a filter has already been specified.
 */
public LdapQuery filter(String hardcodedFilter) {
    initRootContainer();
    rootContainer.append(new HardcodedFilter(hardcodedFilter));
    return this;
}

电子邮件头注入

如果使用最新的Spring Boot,您可能不需要担心这个漏洞,因为它需要通过将pom.xml中的javax.mailversion>1.5.1覆盖为较低的版本才能实现。

空字节注入

由于Java版本1.7.0_40之前的漏洞,因此,无法在Spring Boot推荐的前提版本1.8中复制此漏洞。但是,Spring Boot可以在Java版本1.7下运行,因此,在这种情况下,可以复制此漏洞。

无限制大小的文件上传

可以通过在 application.properties 文件中显式定义 spring.http.multipart.max-file-size=-1 来实现复现。

会话固定攻击

在此应用程序中,没有实现和采取任何Spring Security,但可以通过使用Spring Security的会话管理功能来启用会话固定攻击防护。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig
    extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.sessionManagement().sessionFixation().migrateSession();
    }
}

在这个例子中,因为调用了.sessionFixation().migrateSession(),所以会销毁之前使用的会话并生成一个新的会话。

危险的文件包含

通过使用已经被Spring Boot弃用的JSP/JSTL来实现。由于Thymeleaf没有替代JSTL的c:import功能,所以无法实现远程文件包含,但可以通过th:include实现本地文件包含。

过去遍历

我们使用了被Spring Boot弃用的JSP/JSTL来实现。如果使用Thymeleaf,则无法通过 “../” 返回上级目录,因此无法实现路径遍历。

意外地泄露文件

我們使用了以下方式來實現,但是這樣做將無法使用Thymeleaf或JSP來生成動態頁面。由於它與非Spring Boot內置的Tomcat的目錄列表行為不同,所以可能是Spring Boot的錯誤(如果這個實現是正確的話)。

@Bean
public ServletRegistrationBean servletRegistrationBean() {
    /* Enable directory listing under /uid/ */
    final DefaultServlet servlet = new DefaultServlet();
    final ServletRegistrationBean bean = new ServletRegistrationBean(servlet, "/uid/*");
    bean.setEnabled(true);
    bean.addInitParameter("listings", "true");
    bean.setLoadOnStartup(1);
    return bean;
}

跨站请求伪造 (Cross-Site Request Forgery) (CSRF)

从Spring Security 4.0开始,默认情况下启用了CSRF攻击的防御功能。即使已经使用了Spring Security,如果明确地将其禁用,将会导致问题。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig
    extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable();
    }
}

点击劫持

Spring Security具有防点击劫持功能,但需要正确实施才能避免安全漏洞。以下是正确的实施示例。

@EnableWebSecurity
public class WebSecurityConfig extends
    WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers().frameOptions().sameOrigin();
    }
}

总结

使用最新的Java和框架可以避免制作错误,但这只是一小部分。作为程序员,我们需要理解这些问题并进行正确的实现。

广告
将在 10 秒后关闭
bannerAds