Coders Conquer Security OWASP Top 10 API Series - Broken Object Level Authorization

2020年09月09日掲載
マティアス・マドゥ博士著
ケーススタディ

Coders Conquer Security OWASP Top 10 API Series - Broken Object Level Authorization

2020年09月09日掲載
マティアス・マドゥ博士著
リソースを見る
リソースを見る

昨今のサイバーセキュリティへの脅威は、どこにでもあり、容赦ないものです。あまりにもひどいので、プログラムを導入した後にそれらに対処しようとするのはほとんど不可能になっています。しかし、DevSecOps、継続的デリバリ、そしてかつてないほど多くのデータが得られるこの時代に、賢明な企業は、開発者をセキュリティ意識の高いスーパースターに育て上げ、一般的な脆弱性を本番稼動前に排除できるように支援しています。これまでに、Webの脆弱性Infrastructure as Codeのバグのトップ8を紹介してきましたが、次は、ソフトウェアセキュリティの次の大きな課題について知っておくべきでしょう。準備はできていますか?

今回のブログシリーズでは、アプリケーション・プログラミング・インターフェース(API)に関連した最悪のセキュリティバグを取り上げます。これらのバグは、Open Web Application Security Project(OWASP)が発表したAPI脆弱性のトップリストに掲載されるほどのものです。現代のコンピュータ・インフラにおいてAPIがいかに重要であるかを考えると、これらの問題は、アプリケーションやプログラムから絶対に排除しなければならない重大な問題です。

コードを使ってセキュリティを強化することがなぜ必要なのか、その完璧な例は、壊れたオブジェクト・レベル認証の脆弱性の検証に見ることができます。これは、プログラマが、どのユーザがオブジェクトやデータを閲覧できるかを明示的に定義せず、また、オブジェクトの閲覧、変更、その他の操作やアクセスのリクエストを行うための何らかの検証を行わず、APIエンドポイントを通じてオブジェクトやデータの変更やアクセスを許してしまうことで起こります。APIエンドポイントとは、API自体と他のシステムとの間の通信に利用されるタッチポイントであり、多くの場合URLである。アプリ間の接続機能は、世界で最も愛されているソフトウェアを向上させましたが、気密性が高くなければ複数のエンドポイントを公開してしまう危険性があります。

また、コード作成者が親クラスのプロパティを忘れたり、継承したりすることで、コード内の重要な検証プロセスが省略されていることに気づかないこともあります。一般的には、ユーザからの入力を利用してデータソースにアクセスするすべての関数に対して、オブジェクトレベルの認証チェックを行う必要があります。

今すぐアクセスコントロールのバグを発見し、修正し、排除することができます。ゲーム感覚でチャレンジしてみてください。

あなたの成績はいかがでしたか?スコアアップしたい方は、このまま読み進めてくださいね。

壊れたオブジェクトレベルの認証の脆弱性の例としてはどのようなものがありますか?

オブジェクト・レベル・アクセス・コントロールの脆弱性により、攻撃者は本来許可されていない行為を行うことができます。これは、機密データへのアクセスや閲覧、あるいは記録の破棄など、管理者にのみ許されるべき行為かもしれません。
オブジェクトレベルの認証を定義する際には、考えられるすべてのアクションを念頭に置く必要があります。例えば、Java Spring APIでは、問題が発生する可能性のあるエンドポイントは次のようになります。

public boolean deleteOrder(Long id) {
       Order order = orderRepository.getOne(id);
       if (order == null) {
           log.info("No found order");
           return false;
       }
       User user = order.getUser();
       orderRepository.delete(order);
       log.info("Delete order for user {}", user.getId());
       return true;

APIエンドポイントは、IDごとに注文を削除しますが、この注文が現在ログインしているユーザーによって行われたかどうかは検証しません。このため、攻撃者がこの抜け道を利用して、他のユーザーの注文を削除する機会があります。

安全なアクセス制限を適切に実装するためには、以下のようなコードになります。

public boolean deleteOrder(Long id) {
       User user = userService.getUserByContext();
       boolean orderExist = getUserOrders().stream()
               .anyMatch(order -> (order.getId() == id));
       if (orderExist) {
           orderRepository.deleteById(id);
           log.info("Delete order for user {}", user.getId());
           return true;
       } else {
           log.info("No found order");
           return false;

壊れたオブジェクトレベル認証の脆弱性の解消

アクセス制御のコードは、過度に複雑である必要はありません。今回のJava Spring API環境の例で言えば、誰がオブジェクトにアクセスできるかを厳密に定義することで解決できます。

まず、誰がリクエストをしているのかを確認するために、検証プロセスを実施する必要があります。

User user = userService.getUserByContext();

次に、オブジェクトIDが存在し、リクエストを行ったユーザーのものであることを確認する必要があります。

boolean orderExist = getUserOrders().stream()
.anyMatch(order -> (order.getId() == id));

そして最後に、オブジェクトの削除に進みます。

orderRepository.deleteById(id)。

コードの中の認証方法が、組織のユーザーポリシーやデータアクセスコントロールと一致していることを確認する必要があることを覚えておいてください。コードが完全に安全であることを確認する方法として、異なる権限レベルを持つユーザが、業務を遂行するために必要なデータにアクセスできるが、自分に制限されるべきものは閲覧や変更ができないようになっていることを確認するチェックを行う必要があります。そうすることで、誤って見過ごされていたオブジェクト制御の脆弱性が発見されるかもしれません。

これらの例から得られる主な教訓は、まず、ユーザーがオブジェクトに対して取り得るすべてのアクションを定義し、強力なアクセス制御をコードに直接追加することです。そして最後に、継承された親プロパティにその仕事を任せたり、その権限を別の場所に委ねたりしてはいけません。代わりに、保護する必要のあるすべてのオブジェクトタイプについて、コードの中でユーザーの権限とアクションを明示的に定義します。

をご覧ください。 Secure Code Warriorブログページでは、この脆弱性に関するより詳しい情報や、他のセキュリティ上の欠陥の被害から組織や顧客を守るための方法を紹介しています。また、Secure Code Warrior トレーニングプラットフォームのデモをお試しいただくことで、サイバーセキュリティに関するすべてのスキルを磨き、最新の状態に保つことができます。



リソースを見る
リソースを見る

著者

マティアス・マドゥ博士

マティアスは、15年以上のソフトウェアセキュリティの実務経験を持つ研究者・開発者です。フォーティファイ・ソフトウェア社や自身の会社(Sensei Security)などでソリューションを開発してきました。キャリアの中で、Matiasは、商用製品につながる複数のアプリケーションセキュリティ研究プロジェクトを主導し、10件以上の特許を取得しています。また、RSAカンファレンス、Black Hat、DefCon、BSIMM、OWASP AppSec、BruConなどの世界的なカンファレンスで定期的に講演を行っているほか、高度なアプリケーションセキュリティトレーニング(courses )の講師も務めています。

Matiasはゲント大学でコンピュータ工学の博士号を取得し、アプリケーションの内部構造を隠すためのプログラム難読化によるアプリケーションセキュリティを研究しました。

もっと知りたい?

セキュアコーディングに関する最新の知見をブログでご紹介しています。

当社の豊富なリソースライブラリは、安全なコーディングアップスキルに対する人間的なアプローチを強化することを目的としています。

ブログを見る
もっと知りたい?

開発者主導のセキュリティに関する最新の研究成果を入手する

ホワイトペーパーからウェビナーまで、開発者主導のセキュアコーディングを始めるために役立つリソースが満載のリソースライブラリです。今すぐご覧ください。

リソース・ハブ

Coders Conquer Security OWASP Top 10 API Series - Broken Object Level Authorization

2020年09月09日掲載
マティアス・マドゥ博士著

昨今のサイバーセキュリティへの脅威は、どこにでもあり、容赦ないものです。あまりにもひどいので、プログラムを導入した後にそれらに対処しようとするのはほとんど不可能になっています。しかし、DevSecOps、継続的デリバリ、そしてかつてないほど多くのデータが得られるこの時代に、賢明な企業は、開発者をセキュリティ意識の高いスーパースターに育て上げ、一般的な脆弱性を本番稼動前に排除できるように支援しています。これまでに、Webの脆弱性Infrastructure as Codeのバグのトップ8を紹介してきましたが、次は、ソフトウェアセキュリティの次の大きな課題について知っておくべきでしょう。準備はできていますか?

今回のブログシリーズでは、アプリケーション・プログラミング・インターフェース(API)に関連した最悪のセキュリティバグを取り上げます。これらのバグは、Open Web Application Security Project(OWASP)が発表したAPI脆弱性のトップリストに掲載されるほどのものです。現代のコンピュータ・インフラにおいてAPIがいかに重要であるかを考えると、これらの問題は、アプリケーションやプログラムから絶対に排除しなければならない重大な問題です。

コードを使ってセキュリティを強化することがなぜ必要なのか、その完璧な例は、壊れたオブジェクト・レベル認証の脆弱性の検証に見ることができます。これは、プログラマが、どのユーザがオブジェクトやデータを閲覧できるかを明示的に定義せず、また、オブジェクトの閲覧、変更、その他の操作やアクセスのリクエストを行うための何らかの検証を行わず、APIエンドポイントを通じてオブジェクトやデータの変更やアクセスを許してしまうことで起こります。APIエンドポイントとは、API自体と他のシステムとの間の通信に利用されるタッチポイントであり、多くの場合URLである。アプリ間の接続機能は、世界で最も愛されているソフトウェアを向上させましたが、気密性が高くなければ複数のエンドポイントを公開してしまう危険性があります。

また、コード作成者が親クラスのプロパティを忘れたり、継承したりすることで、コード内の重要な検証プロセスが省略されていることに気づかないこともあります。一般的には、ユーザからの入力を利用してデータソースにアクセスするすべての関数に対して、オブジェクトレベルの認証チェックを行う必要があります。

今すぐアクセスコントロールのバグを発見し、修正し、排除することができます。ゲーム感覚でチャレンジしてみてください。

あなたの成績はいかがでしたか?スコアアップしたい方は、このまま読み進めてくださいね。

壊れたオブジェクトレベルの認証の脆弱性の例としてはどのようなものがありますか?

オブジェクト・レベル・アクセス・コントロールの脆弱性により、攻撃者は本来許可されていない行為を行うことができます。これは、機密データへのアクセスや閲覧、あるいは記録の破棄など、管理者にのみ許されるべき行為かもしれません。
オブジェクトレベルの認証を定義する際には、考えられるすべてのアクションを念頭に置く必要があります。例えば、Java Spring APIでは、問題が発生する可能性のあるエンドポイントは次のようになります。

public boolean deleteOrder(Long id) {
       Order order = orderRepository.getOne(id);
       if (order == null) {
           log.info("No found order");
           return false;
       }
       User user = order.getUser();
       orderRepository.delete(order);
       log.info("Delete order for user {}", user.getId());
       return true;

APIエンドポイントは、IDごとに注文を削除しますが、この注文が現在ログインしているユーザーによって行われたかどうかは検証しません。このため、攻撃者がこの抜け道を利用して、他のユーザーの注文を削除する機会があります。

安全なアクセス制限を適切に実装するためには、以下のようなコードになります。

public boolean deleteOrder(Long id) {
       User user = userService.getUserByContext();
       boolean orderExist = getUserOrders().stream()
               .anyMatch(order -> (order.getId() == id));
       if (orderExist) {
           orderRepository.deleteById(id);
           log.info("Delete order for user {}", user.getId());
           return true;
       } else {
           log.info("No found order");
           return false;

壊れたオブジェクトレベル認証の脆弱性の解消

アクセス制御のコードは、過度に複雑である必要はありません。今回のJava Spring API環境の例で言えば、誰がオブジェクトにアクセスできるかを厳密に定義することで解決できます。

まず、誰がリクエストをしているのかを確認するために、検証プロセスを実施する必要があります。

User user = userService.getUserByContext();

次に、オブジェクトIDが存在し、リクエストを行ったユーザーのものであることを確認する必要があります。

boolean orderExist = getUserOrders().stream()
.anyMatch(order -> (order.getId() == id));

そして最後に、オブジェクトの削除に進みます。

orderRepository.deleteById(id)。

コードの中の認証方法が、組織のユーザーポリシーやデータアクセスコントロールと一致していることを確認する必要があることを覚えておいてください。コードが完全に安全であることを確認する方法として、異なる権限レベルを持つユーザが、業務を遂行するために必要なデータにアクセスできるが、自分に制限されるべきものは閲覧や変更ができないようになっていることを確認するチェックを行う必要があります。そうすることで、誤って見過ごされていたオブジェクト制御の脆弱性が発見されるかもしれません。

これらの例から得られる主な教訓は、まず、ユーザーがオブジェクトに対して取り得るすべてのアクションを定義し、強力なアクセス制御をコードに直接追加することです。そして最後に、継承された親プロパティにその仕事を任せたり、その権限を別の場所に委ねたりしてはいけません。代わりに、保護する必要のあるすべてのオブジェクトタイプについて、コードの中でユーザーの権限とアクションを明示的に定義します。

をご覧ください。 Secure Code Warriorブログページでは、この脆弱性に関するより詳しい情報や、他のセキュリティ上の欠陥の被害から組織や顧客を守るための方法を紹介しています。また、Secure Code Warrior トレーニングプラットフォームのデモをお試しいただくことで、サイバーセキュリティに関するすべてのスキルを磨き、最新の状態に保つことができます。



弊社製品や関連するセキュアコーディングのトピックに関する情報をお送りする許可をお願いします。当社は、お客様の個人情報を細心の注意を払って取り扱い、マーケティング目的で他社に販売することは決してありません。

送信
フォームを送信するには、「Analytics」のCookieを有効にしてください。完了したら、再度無効にしてください。