web-dev-qa-db-ja.com

REST XMLに基づくAPIバックエンドを備えた単一ページアプリケーション、動的XPathによってクエリ

私が開発しているWebアプリケーションは、jQuery.ajax()呼び出しを通じてREST APIバックエンドと対話するシングルページアプリケーション(SPA)です。

SPAとAPIはどちらもhttps/TLS接続を介して提供されます。 APIはSPAドメインのサブドメインから提供されます:

_SPA: example.org
API: api.example.org
_

...そして適切なCORSヘッダーで応答します:

_Access-Control-Allow-Origin: example.org
Access-Control-Allow-Methods: GET, POST, etc. // whatever applicable to the requested resource
Access-Control-Allow-Headers: Accept, Authorization, Content-Type
_

SPAにログインすると、ユーザー(組織)は、一意の関連付けられたsha1 _API-key_(Cookieまたはグローバルjavascript変数として)を提供され、その間、SPAはAPIとの対話に使用しますユーザーのログインセッションの。 SPAは、AuthorizationヘッダーのAPIへの各リクエストでこれを_API-key_として発行します。

_Authorization: MyAppsApi apikey=<API-key>
_

REST APIの永続ストレージはXMLベースです。現時点では、実際のストレージメカニズムベンダーはまだ決定していません(現時点では eXistdb の使用を検討しています)。ただし、開発の初期段階では、PHPの DOMDocumentDOMXPath を使用しているだけで、同時読み取り/書き込み機能はありません。

REST APIは、受信したリクエストURIのパスに基づいて、XPathクエリをさらに動的に生成します。ただし、SPAとAPIの間の通信は、おそらくJSONで行われます。

次のXMLドキュメントの例を考えてみます。

_<?xml version="1.0" encoding="utf-8"?>
<organisations>
  <organisation id="1">
    <apiKey>some hex sha1 digest</apiKey>
    <products>
      <product id="1">
        <parts>
          <part id="1">
            <subParts>
              <subPart id="1">
                ...
              </subPart>
            </subParts>
          </part>
        </parts>
      </product>
    </products>
  </organisation>
  <organisation id="2">
    <apiKey>another hex sha1 digest</apiKey>
    <products>
      ...
    </products>
  </organisation>
</organisations>
_

現在、このドキュメントはカスタムXSDスキーマによって検証されています。

REST APIは、XMLをさらに操作する前に、発行された_<organisation>_を持つ_<apiKey>_ノードが存在するかどうかを最初に判別します。_<organisation>_ノードが見つかった場合、これは、それ以降のXPathクエリのコンテキストノードとして使用されます。

リクエストURIパスは、次の正規表現パターンによって制限されます。

_~\G(/(?<collection>[a-z]+)(?:/(?<resourceId>\d+))?)(?:(?=(?1))|/?$)~
_

/<loweralpha>+(/<digit>+)?セグメントのみを許可

これらのリクエストURIパスの例とそれらの動的に生成されたXPathを考えてみます。

_/products/1          => .//products/*[@id="1"]
/parts/1             => .//parts/*[@id="1"]
/products/1/parts/1  => .//products/*[@id="1"]/parts/*[@id="1"]
_

ご覧のとおり、これらは_<organisation>_コンテキストノードに関連しています。

XMLバックエンドの典型的な動作をまだ完全に調査していないことを考えると、XMLドキュメントを作成する必要があるという点で、上記のXMLセットアップにはまず欠陥があることがよくわかります per組織。_<organisation>_コンテキストノードに属していないノードにアクセスするリスクを軽減します。

ただし、この現在のセットアップに固有の欠陥はありますか?

私の現在のセットアップでは、リスクが高すぎることが判明する可能性のある動的XPathクエリについて主に懸念しています。おそらく、攻撃者はどういうわけかXPath軸に忍び込むことができますか?しかし、他に起こりうる欠陥についても聞きたいです。

ありがとうございました。

追伸:おそらく私は、リスクが何であるかをもっと明確にすべきだった。

  1. 敵対者は、(他の)組織のAPIキーを何らかの方法で取得できますか?
  2. 敵対者は(他の)組織のコンテンツをどうにかして操作できますか?
3
Decent Dabbler

クライアントが提供するものを処理するときの主な問題は、 XML External Entities(XXE) 攻撃です。このような脆弱性のあるシステムは、ファイルを読み取ったり、サーバーが接続されている内部ネットワークを列挙したりするために悪用されることがよくあります。 PHPで、外部エンティティを無効にするためにlibxml_disable_entity_loader(true);を呼び出すことで、これを修正することができます。

もう1つの問題は、潜在的に Billion Laughs 攻撃です。これは、ネストされた要素型宣言を使用するCPUおよびメモリ枯渇DoS攻撃です。 このSO質問 は、この種の攻撃を回避するためにロードする前にXMLを事前検証する方法についての良いアイデアを提供するはずですが、簡単な答えはlibxmlが許可することですカスタムDTDバリデーター/ローダーコールバックを設定します。

XPath Injection を検討することもできますが、ユースケースでこれがどれほど重要かはわかりません。アプリケーションを広く理解していなければ、それがシステムのビジネスロジックにどのような影響を与えるかを判断するのは困難です。

1
Polynomial