Pythonの主要なセキュリティ脆弱性
今日の急速な開発パイプラインにおいて、安全でないPythonコードは深刻なリスクをもたらす可能性があります。Pythonはそのシンプルさで広く利用されていますが、その柔軟性ゆえに、安全なコーディングプラクティスが疎かにされると危険なものになり得ます。コードインジェクションの落とし穴から脆弱なサードパーティライブラリに至るまで、わずかな見落としでも攻撃者への扉を開くことになりかねません。最近の研究では、数百万もの認証情報やAPIキーがコード内に誤って漏洩していることが示されており、セキュリティが後回しにできないものであることを強く示唆しています。本記事では、主要なPython言語レベルのセキュリティ脆弱性(Webフレームワークの問題に留まらない)をいくつか掘り下げ、実際の事例(人気ライブラリのCVEを含む)でその影響を説明し、各リスクを軽減するためのヒントを提供します。また、AikidoのSAST、シークレットスキャン、依存関係チェックなどのセキュリティツールをワークフローの早い段階で統合することが、これらの問題が大きな被害をもたらす前に発見するのにどのように役立つかについても強調します。
Pythonの主要な10のセキュリティ脆弱性
以下に、Pythonアプリケーションにおける最も一般的で危険なセキュリティ脆弱性を10個挙げます。それぞれについて、脆弱性がどのように発生するか、潜在的な影響、そして修正または防止方法を説明します。現代のセキュリティツールがどのように役立つかについても特に言及します。
1. 任意のコード実行(~を介して) eval() そして exec()
Pythonの eval() (およびその類似機能である exec()) 評価 は、単純なスクリプトを時限爆弾に変える可能性があります。攻撃者がに渡される文字列に影響を与えることができる場合、 eval()、 任意のコードを データ出力からファイルの削除、あるいはそれ以上のことまで、実行できます。ある開発者が述べたように、 「の問題は、 評価 攻撃者が悪意のある入力を作成し、プログラムに有害なコードを実行させる危険性があることです。」。言い換えれば、 eval(user_input) の呼び出しは、安全な入力であれば今日は機能するかもしれませんが、明日巧妙に作成された入力(例えば、 __import__('os').system('rm -rf /'))によって、 サーバーが消去される.
影響: 任意のコード実行は、その言葉が示す通り深刻であり、アプリケーションの完全な侵害を意味します。攻撃者はデータを盗んだり、改ざんしたり、ホストを乗っ取ったりする可能性があります。これは理論上の特殊なケースではなく、の安全でない使用によって実際に侵害が発生しています。 評価。たとえの利用が 評価 今日「安全」であったとしても(例えば、数学的表現のみを評価する場合など)、それは 潜在的な脆弱性 将来の変更が意図せず引き起こす可能性があるもの。
緩和策: 信頼できない入力に対してevalやexecを使用しないでください。 実際、絶対に必要な場合を除き、これらを完全に避けるべきです。Pythonはほとんどのユースケースにおいてより安全な代替手段を提供しています(例えば、リテラル評価には ast.literal_eval を使用してデータ構造を読み取る、または文字列を構築して関数を呼び出す代わりにディスパッチテーブルを使用するなど)。 評価動的な実行が必要な場合は、常に厳密に入力を検証またはサニタイズしてください。
Aikido Securityからの注意喚起: 優れた静的解析ツール(SAST)は、危険な関数の使用を検出できます。例えば、Aikidoのコードスキャンは、 eval() または exec() のインスタンスをコード内で特定できます。これにより、コードレビューやCI中にリスクのあるコードパスを特定するのに役立ちます。 前に それらが本番環境に到達する前に。このようなスキャンをパイプラインに統合することで、新しい 評価 の使用が紛れ込んだ際にアラートを受け取ることができ、直ちにリファクタリングまたは精査することが可能です。
2. を介したOSコマンドインジェクション subprocess または os.system
コードインジェクションのテーマをさらに掘り下げると、もう一つの重大な落とし穴は OS command injectionです。これは、Pythonプログラムがユーザー入力をシステムシェルコマンドに適切なサニタイズなしで渡す場合に発生します。 os.system(), subprocess.run() ( shell=Trueを使用)のような関数、あるいはバッククォート/popenの使用でさえシェルコマンドを実行できます。ユーザーが制御するデータがこれらのコマンドに連結されると、攻撃者は不正なコマンドを注入できます。例:
# Vulnerable snippet:filename = input("Enter the filename to delete: ")os.system(f"rm -f {filename}")
攻撃者は file.txt; shutdown -h now と入力し、突然私たちの無害なスクリプトが実行してしまいます。 rm -f file.txt; shutdown -h now。実際のインシデントでは、攻撃者は、サニタイズされていないデータが渡されたことに起因するMLflowの脆弱性をエクスプロイトしました。 os.system predict関数内の呼び出し。Snykのセキュリティ研究者が指摘するように、コマンドインジェクションは不正なコマンド実行を可能にし、データ漏洩、システム侵害、およびその他の悪意のある活動につながります。
影響: OSコマンドインジェクションは壊滅的な被害をもたらす可能性があります。攻撃者はコマンドを連鎖させ、機密ファイル(例:アプリケーション設定やクレデンシャルの読み取り)を盗んだり、バックドアユーザーアカウントを作成したり、ネットワークの奥深くに侵入したりする可能性があります。これらのコマンドはPythonプロセスと同じ権限で実行されるため、影響はデータベースのダンプからサーバーの完全な乗っ取りにまで及ぶ可能性があります。コマンドインジェクションによって引き起こされる侵害は、しばしば深刻な金銭的および評判上の損害をもたらします。
緩和策: ユーザー入力をシェルコマンドに直接連結してはいけません。 外部プログラムを呼び出す必要がある場合は、より安全なAPIを使用してください。Pythonの subprocess モジュールは引数をリストとして渡すことを可能にします(これにより実際のシェルを呼び出すことを回避できます)。例えば、 subprocess.run(["rm", "-f", filename]) 代わりに os.system("rm -f " + filename)。もし使用が subprocess を用いて shell=True 避けられない場合は、 入力が厳密に検証またはサニタイズされていることを確認してください (例えば、予期される英数字のファイル名のみを許可するなど)。さらに、OSタスクには高レベルのライブラリの使用を検討してください(例:ファイルの削除にはPythonのファイル処理を使用し、 rm の代わりに)。
Aikido Securityからの注意喚起: Aikidoの静的コード分析には、 コマンドインジェクションパターンを検出するためのルールが含まれています。。それは、 os.system(user_input) または subprocess.Popen(..., shell=True) 変数入力を含むものを見つけた場合に警告します。実際には、これは危険な使用法が導入された場合、CI/CDパイプラインがビルドを失敗させる可能性があることを意味します。これらを開発中に捕捉することで、忘れられたデバッグスニペットや場当たり的なシェル呼び出しが攻撃者にとって開かれた扉となるような「しまった」という瞬間を防ぎます。
3. コード内のハードコードされたシークレット
APIキー、クレデンシャル、トークン、または秘密鍵のようなシークレットをソースコードにハードコーディングすることは、蔓延しており、危険な慣行です。それは簡単に行えます(「とりあえずAWSキーをここに置いておこう…」)が、シークレットは削除後もコミット履歴に残る可能性があるため、元に戻すのは困難です。露出したシークレットは攻撃者にとって宝の山です。実際、シークレットの漏洩は最近急増しており、2022年には、公開GitHubリポジトリの分析で、わずか1年間で1,000万件のシークレットが露出していることが判明しました(前年比67%増)。これらはジュニア開発者によってのみコミットされるわけではなく、あらゆるレベルで発生します。一度漏洩すると、シークレットは大規模な侵害に利用されてきました(例えば、攻撃者はコード内のハードコードされた管理者クレデンシャルを使用してUberの内部システムに侵入しました)。
影響: 攻撃者がシークレット(公開リポジトリ、漏洩したバックアップ、Dockerイメージなど)を発見した場合、しばしばシステムに直接侵入できます。ハードコードされたデータベースパスワードを想像してみてください。もし漏洩した場合、攻撃者はデータベースにログインしてユーザーデータを抽出する可能性があります。ハードコードされたクラウドAPIキーはさらに悪質です。クラウドプロバイダーは、露出したクレデンシャルがリポジトリをスキャンするボットによって発見後数分以内にエクスプロイトされると報告しています。影響範囲には、クラウド環境全体の侵害、クリプトマイナーによる高額なクラウド料金、または機密サービスへの不正アクセスが含まれる可能性があります。シークレットはまさに「王国の鍵」であり、それらを漏洩させることは、泥棒のために玄関のドアの鍵を開けたままにするようなものです。
軽減策: 実際のシークレットをコードにコミットしてはいけません。代わりに、設定ファイル、環境変数、またはシークレット管理サービス(HashiCorp Vault、AWS Secrets Managerなど)を使用して、実行時にシークレットを注入してください。もしコードにデフォルトまたは例のクレデンシャルを含める必要がある場合は、それが非本番環境のプレースホルダーであることを確認してください。コードベースと履歴に対して定期的なシークレットスキャンを実施してください。もしシークレットが紛れ込んだ場合は、直ちにローテーションし(つまり、無効化して置き換え)、可能であればコミットをパージしてください。最小権限の原則を採用してください。シークレットが漏洩したとしても、読み取り専用トークンは完全な管理者キーよりも被害が少なくなります。
Aikidoセキュリティの注目点: ここでシークレット検出ツールが真価を発揮します。Aikidoのシークレットスキャン(GitGuardianなどに触発されたもの)は、リポジトリ内でAPIキー、クレデンシャル、証明書などのパターンを自動的に検索します。開発者が誤ってシークレットをコミットした瞬間に警告を発することができます。このようなツールをCI/CD(またはプリコミットフック)に統合することは、ハードコードされたAWSキーがGitHubに到達する前にフラグが立てられることを意味します。Aikidoのプラットフォームは自動修復も提供しており、例えば、露出したクレデンシャルを失効させ、開発者に代わりに安全なストレージ方法を使用するよう促します。
4. 安全でないデシリアライゼーション (Pickleの悪用)
Pythonのpickleモジュールは、複雑なオブジェクトをシリアライズおよびデシリアライズする方法を提供します。しかし、pickleはその設計上、非常に安全性が低いことで知られています。信頼できないソースからのデータをアンピクルすると、デシリアライゼーションプロセス中に任意のコードが実行される可能性があります。Pythonのドキュメント自体もこの点について明確に述べています。“pickleモジュールは悪意のあるデータに対して安全であるようには設計されていません。信頼できない、または認証されていないソースから受け取ったデータをアンピクルしないでください。” 実際には、攻撃者がアプリケーションにpickleデータ(偽造されたクッキーやキャッシュされたオブジェクトなど)を送り込むことができれば、サーバー上で任意のPythonコードを実行できることを意味します。これは本質的に、認証前RCE(リモートコード実行)の脆弱性となります。
実例: 開発者は pickle.loads() をネットワーク経由で受信したデータに対して使用する可能性があります(Pythonオブジェクトを送信する便利な方法だと考えているかもしれません)。攻撃者は、アンピクルされた際にシステムコマンドを実行するpickleペイロードを作成できます。セキュリティ研究者は、一見無害なオブジェクトをアンピクルするだけで攻撃者へのリバースシェルがトリガーされるという、単純なエクスプロイトを実証しています。あるケースでは、アプリケーションがネットワーク上のpickleデータを盲目的に信頼していたため、わずか15行のpickleを使ったエクスプロイトでシェルを生成するのに十分でした。
影響: 安全でないデシリアライゼーションは、通常、完全なリモートコード実行につながる重大な問題です。pickleはロード中に任意のクラスやメソッドを呼び出すことができるため、攻撃者はこれを悪用してファイルの削除、マルウェアのインストール、他の内部サービスへのピボットなどを行うことができます。データが「ただ」漏洩するだけの脆弱性とは異なり、これは攻撃者に直接的な制御を与えます。その影響は、実行中のアプリケーションの権限によってのみ制限されます(そして、Pythonアプリケーションはしばしば多くの特権で実行されます)。
緩和策: 信頼できないソースからのデータに対して、pickle(またはmarshalのような類似のシリアライゼーション)を使用しないでください。 システム間でデータを交換する必要がある場合は、JSONやXMLのような安全な形式を使用してください。その場合でも、注意を払い(入力を検証し)てください。Python固有のユースケース(オブジェクトの共有)では、 jsonpickle をセーフモードまたは他のより安全なシリアライザを検討してください。ただし、入力は常に敵対的である可能性があると仮定してください。どうしてもpickleデータを受け入れる必要がある場合(互換性のためなど)は、コードとして扱ってください。認証を要求し、デジタル署名を使用して信頼できるソースからのものであることを確認するか、制限された権限を持つサンドボックス内でデシリアライゼーションを実行してください。最も単純なアドバイスが通常は最善です。 ユーザー入力の動的なデシリアライゼーションは完全に避ける.
Aikido Securityからの注意喚起: 最新のコードスキャナーは、次のような危険なAPIの使用を検出できます pickle.loads または pickle.load を潜在的に外部からのデータに対して使用している場合です。例えば、AikidoのSASTエンジンは、安全でないデシリアライゼーションに対するチェック機能を備えており、pickleの呼び出しは、そうでないと証明されない限り危険信号であると認識しています。コードレビュー中にこれらを強調表示します。さらに、Aikidoの依存関係スキャナーは、既知のデシリアライゼーション関連のCVEを追跡しています。例えば、一部のライブラリ(またはフレームワーク)にはデシリアライゼーションの欠陥がありました(pickleだけでなく、XMLやYAMLのようなものも含まれます。これについては次に説明します)。Aikidoは、そのようなライブラリの脆弱なバージョンを使用している場合に警告し、アップグレードやパッチを提案します。
5. 安全でないYAMLのロード (PyYAMLの脆弱性)
シリアライゼーションの問題はpickleに限定されません。 YAMLは、人間が読みやすいデータ形式ですが、安全でない方法で使用すると問題を引き起こす可能性があります。人気のあるPyYAMLライブラリには、よく知られた欠陥がありました。それは、 yaml.load() を信頼できない入力に対して使用すると、任意のPythonオブジェクトを実行する可能性があるというものです。実際、PyYAMLの load() は、基本的にpickleと同じくらい強力でした。 CVE-2017-18342 この問題に起因するものでした。「PyYAML 5.1より前のバージョンでは、信頼できないデータと共に使用された場合、yaml.load() APIが任意のコードを実行する可能性がありました。」この修正は、 safe_load 関数を導入し、 load() 新しいバージョンでセーフモードをデフォルトにすることでした。しかし、多くのアプリケーションでは、意図せず古い yaml.load (または古いPyYAMLバージョン)を使用している可能性があり、設定を解析しているだけだと考えているかもしれません。しかし実際には、攻撃者がコードを実行するYAMLを作成できる可能性があります。
影響: pickleと同様に、その影響はリモートコード実行です。例えば、YAMLファイルは、構築時にシステムコールを実行するタイプのPythonオブジェクトを埋め込むことができます。これを悪用する攻撃者は、悪意のあるYAMLを解析しようとした瞬間に、アプリケーションにOSコマンドを実行させることができます。これは、ユーザーが提供するYAMLを解析するあらゆる機能を通じて悪用される可能性があります(一般的なシナリオとしては、設定インポーター、CI/CDにおけるKubernetesテンプレート、YAML入力を受け入れるWebアプリケーションなどがあります)。上記のCVEは、そのトリガーの容易さと結果の重大性から、Critical(CVSS 9.8)と評価されました。
緩和策: 常に 安全なロード メソッドをデータ形式に使用してください。PyYAMLでは、 yaml.safe_load() for any content that is not fully trusted. This mode only parses basic YAML types (strings, ints, lists, dicts) and will refuse to instantiate custom objects. If you are on PyYAML < 5.1, upgrade the library – the old load() は完全に安全ではありません。同様に、他のシリアライゼーション形式にも注意してください。 json.loads (JSONは設計上コード実行機能がなく、これは良い点です)を使用するか、または pickleのような 代替手段を使用する場合は、安全なモードがあることを確認してください。多層防御のアイデアとして、可能な場合は、低権限環境またはサンドボックスで解析を実行してください(これにより、コードが実行されたとしても、大きな損害を与えることはできません)。
Aikido Securityからの注意喚起: 依存関係スキャン is key here. Aikido’s dependency analyzer would flag that you have PyYAML <5.1 in your requirements, warning you of CVE-2017-18342 and advising an upgrade. On the code side, Aikido’s SAST can also catch usage of yaml.load(...) を行い、代わりにsafe_loadを使用することを提案します。この問題は2つのレベルで捕捉することが重要です。安全なライブラリバージョンを使用していることを確認し、安全な関数を呼び出していることを確認してください。これらのチェックを統合することで、開発中に「このYAML解析呼び出しは安全ではありません」という通知と、修正のためのガイダンスを受け取ることができます。
6. 不安全なファイル操作(Tarfile抽出)によるディレクトリトラバーサル
Pythonではファイルの処理が一般的です(例:ユーザーがアップロードしたアーカイブの展開)。しかし、単純なファイル操作は パストラバーサルの脆弱性を引き起こす可能性があります。顕著な例としては、Pythonの組み込み tarfile モジュールがあります。15年以上にわたり、 tarfile.extractall() パストラバーサル攻撃(「15年前の脆弱性」が再発見された)に対して脆弱でした。悪意のあるtarアーカイブに、ファイルエントリが ../ の名前で含まれている場合、 extractall は意図されたディレクトリ外にファイルを書き込み、重要なシステムファイルを上書きする可能性がありました。これは CVE-2007-4559として追跡されています。これは古いCVEですが、本稿執筆時点ではPython標準ライブラリで未修正のままであり、2022年の調査では 数十万のリポジトリが 未だに tarfile を脆弱な方法で使用していることが示されました。
攻撃者は、特別に細工されたtarファイルをアップロードまたは提供し、コードがそれを抽出する際に、攻撃者がアクセスすべきではない場所にペイロード(例:ウェブシェル、または上書きされた設定)を配置することができました。あるデモでは、研究者たちはこれを悪用し、抽出後にPythonパッケージ自身のコードを上書きすることでコード実行を実現しました。
tarファイルに限らず、zipファイル(zip slip 脆弱性)や、外部入力からパスを構築するあらゆるファイル操作で同様の問題が発生する可能性があります。適切なチェックがない場合、という名前のアーカイブエントリは、 ../../../../../etc/passwd に書き込まれます。 /etc/passwd 抽出時に。
影響: パストラバーサルは、 任意のファイル書き込み (または場合によっては読み取り)をサーバー上で引き起こす可能性があります。誤った場所にファイルを書き込むことは、コード実行にエスカレートする可能性があります。例えば、アプリの設定を上書きして攻撃者が制御するコードを指すようにしたり、PATHにトロイの木馬バイナリをドロップしたりするケースです。たとえ直ちにRCE(リモートコード実行)につながらなくても、重要なファイルを上書きすることはシステム整合性を損なったり、後の攻撃を容易にしたりする可能性があります。攻撃者がアプリケーションの 環境 ファイルや実行されるスクリプトを上書きした場合の結果を考えてみてください。彼らは悪意のあるコマンドを挿入する可能性があります。CVE-2007-4559の場合、ファイルの上書きをエクスプロイトすることがコード実行に直結することが示された際、コミュニティはその深刻度を引き上げました。
緩和策: 信頼できないソースからのアーカイブは、検証なしに決して抽出しないでください。 tarfileの場合、 tarfile.extractall(path, members=...) そして を手動でフィルタリング メンバーを。メンバーのファイルパスがターゲットディレクトリの外に出ていないことを確認するチェックを実装できます(例:絶対パスを解決し、トラバーサルパターンをチェックする)。Pythonのドキュメントには、これを安全に行うためのコードスニペットが含まれており、実質的に .. またはドライブプレフィックスを使用してください。あるいは、安全な抽出を実行するサードパーティライブラリの使用を検討してください。zipファイルの場合も同様に、書き込む前に名前を検査するか、zip slipを軽減するライブラリを使用してください。常に最小特権を適用してください。可能であれば、サンドボックスまたは制限された権限を持つディレクトリで抽出を実行してください。そうすることで、たとえエクスプロイトが脱出しようとしても、システムにとって重要なファイルに到達することはできません。
Aikido Securityからの注意喚起: Aikidoの静的解析は、次のような危険なパターンを検出できます。 tarfile.extractall() 安全なメンバーフィルタリングなしでの使用。CVE-2007-4559を認識しており、予防措置なしでextractallまたはextractを呼び出しているコード内のインスタンスにフラグを立てることができます。これは、適切なチェックを実装するためのきっかけとなります。さらに、Aikidoの脆弱性インテリジェンスフィード(社内研究)は、標準ライブラリと人気のあるパッケージの両方におけるこれらの「潜んでいる」問題を追跡しています。コードと依存関係をスキャンすることで、「tarfileの使用における潜在的なパス・トラバーサル – アーカイブコンテンツの検証を検討してください」のような警告を表示し、ベストプラクティスガイダンスへのリンクを提供します。要するに、開発者がコード内で見過ごされがちな15年前のバグを発見するのに役立ちます。
7. 既知の脆弱性を持つ古いライブラリの使用 (Requests、urllib3など)
Pythonの豊富なパッケージエコシステムはその強みの一つですが、含めるすべての依存関係は、最新の状態に保たれていない場合、脆弱性を引き起こす可能性があります。注目度の高いPythonライブラリも、多くのCVEを抱えてきました。例えば、広く使用されているRequests HTTPライブラリには、次のようなバグがありました。
- CVE-2023-32681 – Requestsが特定のHTTPリダイレクトシナリオでHTTPプロキシの認証情報を漏洩させ、
Proxy-Authorizationヘッダーを宛先サーバーに送信し、機密情報を漏洩させる可能性がありました。 インフォメーション。(これはRequests 2.31.0で修正されました。) - CVE-2024-35195 – セッションで一度SSL証明書検証を無効にすると、Requestsが同じホストへの後続のリクエストに対して、再有効化しようとしても永続的に検証を無視するというロジックの欠陥。基本的に、一度壊れると、常に壊れたままという、接続を密かに安全でない状態にする可能性のある厄介な問題でした。2.32.0で修正済み。
- urllib3におけるCRLFインジェクション – urllib3(内部でRequestsが使用)には、攻撃者がリクエストURLまたはメソッドの一部を制御できる場合(例:ヘッダーに改行文字を挿入できる場合)に、HTTPヘッダーへのCRLFインジェクションを許容する脆弱性がありました。これは、ヘッダーの密輸やレスポンスの分割に悪用され、セッションハイジャックやウェブキャッシュの操作につながる可能性がありました。(Pythonの組み込みurllibに対するCVE-2019-9740など、複数のCVEがこのような問題に割り当てられました。)
これらはほんの一例です。他に注目すべきものとしては、 URL解析 における脆弱性(例:CVE-2023-24329、 urllib.parse における問題で、攻撃者がスペースまたは制御文字で始まる巧妙なURLを使用することでURLブロックリストをバイパスできるものでした)、および パッケージ管理 ツール(pipの過去の脆弱性CVE-2018-20225のように、悪意のあるダウンロードが任意のファイルを上書きすることを許容するもの)における問題があります。人気のあるデータライブラリ(Pandas、NumPy)でさえ、時折セキュリティ修正(多くはDoSまたはメモリ破損の問題)が行われます。
影響: ライブラリにおける既知の脆弱性は、バグの種類に応じて、情報漏洩やサービス拒否から完全な侵害に至るまで、広範囲にわたる影響を及ぼす可能性があります。重要な点は、攻撃者が古いバージョンを使用しているアプリケーションを積極的にスキャンしていることです。古いRequestsを実行しており、アプリケーションがネットワーク呼び出しを行っている場合、攻撃者はプロキシ認証情報の漏洩をエクスプロイトして認証情報を盗む可能性があります。あるいは、古いurllib3を使用している場合、CRLFインジェクションをエクスプロイトしてHTTPインタラクションを汚染する可能性があります。これらの脆弱性は公開されているため、攻撃者は何を狙うべきかを正確に知っています。依存関係の更新を怠ることは、アプリケーションに既知の穴をパッチせずに放置するようなものです。
緩和策: 依存関係の更新とセキュリティアドバイザリに常に注意を払ってください。 依存関係に既知のCVEがないかを確認するツール(pip-tools、GitHubのDependabot、または商用SCAツール)を使用してください。新しい重大なCVEが発表された場合(例:Django、Flask、Requestsなどに深刻なバグがある場合)、修正済みのバージョンへのアップグレードを優先してください。可能な限り、依存関係を既知の良好なバージョンに固定し、更新の変更履歴を確認してください。また、最小バージョンピンも検討してください。例えば、 requests>=2.31.0 古いバージョンに脆弱性があることがわかっている場合は、これを要求します。さらに、多層防御を採用してください。例えば、Requestsに証明書検証のバグがあったとしても、ネットワークセキュリティの層(TLS傍受や追加の証明書ピンニングなど)を追加してリスクを軽減できます。しかし、最も簡単な方法は次のとおりです。 パッケージを最新の状態に保つ.
Aikido ・コールアウト:ここで ソフトウェア構成分析(SCA) における Aikido において Aikidoの依存関係スキャナーは、既知の脆弱性データベースと照合しながら、プロジェクトの要件(さらには推移的依存関係)を継続的にチェックします。「ライブラリXのバージョンYはCVE-2023-32681の脆弱性があります」と警告し、詳細情報や推奨される修正バージョンを提供します。さらに優れた点は、 Aikidoのプラットフォームは自動修正も実行可能——例えばバージョンアップのためのプルリクエストを自動生成します。これをCI/CDに統合すれば、古いライブラリを含むコンテナやアプリケーションをデプロイするリスクを排除できます。要するに、 Aikido のようなツールは既知のCVEを検知Aikido 、自動修正までAikido 、カスタムルールと最新情報でオープンソーススキャナーを補完 Aikido 。
8. セキュリティ機能の無効化(例:SSL証明書検証の無視)
開発やテストの際、エンジニアが重要なセキュリティチェックを無効にすることがあり、その状態のままコードが本番環境にデプロイされてしまうことがあります。Python の典型的な例としては、HTTP リクエストを SSL検証を無効にして実行することです。Requests ライブラリ(および urllib3のような他のライブラリ)では、 verify=False フラグで SSL 証明書エラーを無視できます。これは開発環境で自己署名証明書を扱う場合に便利ですが、本番環境に到達すると、 中間者攻撃(MitM攻撃)に晒されることになります。Requests のドキュメントには、次のように明示的に警告されています。 verify=Falseの場合、クライアントは いずれも 証明書を受け入れます。これにより、ホスト名の不一致や期限切れ/自己署名証明書が無視され、 アプリケーションが MITM 攻撃に対して脆弱になります。本質的に、実際のサーバーと通信していることを確認できなくなります。攻撃者はトラフィックを傍受し(特に DNS を偽装できる場合や、同じネットワーク上にいる場合)、任意の証明書を提示して接続を乗っ取ることができます。
SSL検証以外にも、無効化された他の機能が問題を引き起こす可能性があります。例えば、機密性の高い通信に HTTPS の代わりに HTTP を使用したり、TLS ホスト名チェックを手動で無効にしたり、あるいは Python の組み込みのセーフティネット(セキュリティ上重要なチェックを保護するアサーションがオフの状態でインタプリタを実行するなど)を無効にしたりすることです。
影響: 攻撃者がトラフィックの途中に侵入できる場合(これは多くの人が考えるよりも容易であり、特にクラウドやコンテナネットワーク、公共 Wi-Fi などでは顕著です)、証明書検証が無効になっていると、転送中のデータを復号し、改ざんすることができます。これにより、攻撃者が API トークンを盗んだり、悪意のある応答を挿入したり、サービスを偽装したりする可能性があります。マイクロサービスアーキテクチャでは、1つの侵害されたサービスまたはネットワークの足がかりが、サービス間の呼び出しが適切に検証されていない場合に、それらを傍受することでピボットを可能にする可能性があります。また、API クライアントライブラリで SSL 検証をオフにしたことで、攻撃者が偽装されたドメインで自己署名証明書を使用するだけで、信頼されたはずのアップデートサーバーからマルウェアを配信できたシナリオも確認されています。その結果、データ盗難、アカウント乗っ取り、またはアプリケーションの機能への悪意のあるデータ/コマンドの注入が発生する可能性があります。
緩和策: 本番コードで SSL 検証を無効にしないでください。 どうしても必要な場合(例:自己署名証明書を持つ内部サービスに接続する場合)は、少なくとも証明書またはサムプリントをピン留めして、任意の証明書を盲目的に信頼しないようにしてください。さらに良いのは、プライベート CA を使用し、CA バンドルを提供することで内部証明書を信頼できるようにすることです。開発中に verify=Falseを使用する場合は、コミットする前に必ず削除するか、非本番環境でのみ無効にするように設定を使用するなど、細心の注意を払ってください。 verify=False は大きな危険信号として扱われるべきです。さらに、リンターのようなツールを使用して、コミットされたコードでこのフラグの使用を禁止することを検討してください。他のショートカットについても同様です。例えば、セキュリティ例外をキャッチして無視したり、デバッグ中に認証や CSRF を無効にして再有効化を忘れたりしないでください。
Aikido Securityからの注意喚起: Aikido のスキャナーは、 verify=False のような危険な設定がリクエストで使用されていることを検出できます。実際、証明書チェックを無効にするコードがないことを保証するために、ポリシー(Prisma/Checkov のポリシーと同様の動作)を適用できます。そのようなパターンが検出された場合、Aikido はスキャン結果でそれを指摘し、脆弱性として扱います。「ここで SSL 証明書検証が無効になっています – これは本番環境で使用すべきではありません」と表示され、該当するコード行へのリンクが提供される場合があります。これを CI に統合することで、「デバッグフラグをオンにしたままにしてしまった」というシナリオを効果的に防ぐことができます。さらに、前述の依存関係スキャンは、意図しない無効化が継続する CVE-2024-35195 のようなバグについても情報を提供し、セキュリティを完全に回復するためにライブラリを更新する必要があることを強調します。
9. 悪意のある、または侵害されたパッケージ(ソフトウェアサプライチェーン攻撃)
脅威は自身のコードのミスからのみ発生するわけではありません。PyPIから取得したコード自体が は 攻撃の原因となることもあります。 サプライチェーン攻撃 悪意のあるPythonパッケージを介した攻撃は近年急増しています。攻撃者は、タイポスクワッティングされた、または完全に偽のパッケージをPyPIに公開し、人気のあるライブラリに似た名前を付けます(例: reqeusts 代わりに requests)や、魅力的な名前(例: free-net-vpn)を付けます。 setup.py疑いを持たない開発者がそれらをインストールし、インストール時(setup.py内)に悪意のあるコードが実行されるか、インポート時に実行されます。例えば、2022年には、以下の悪意のあるPyPIパッケージが10個発見されました。 一般的なライブラリを偽装し、 開発者のシステムに情報窃取マルウェアを注入しました。あるパッケージは、よく知られたパッケージを模倣しており、AWS認証情報を検索し、DiscordのWebhook経由で攻撃者に送信するように設計されていました。また、別のパッケージ( WINRPCexploit )はエクスプロイトツールであると主張していましたが、実際にはすべての環境変数(多くの場合シークレットを含む)を攻撃者に流出させていました。
攻撃者がメンテナーのアカウントにアクセスした場合(Node.jsのevent-streamで発生したように、Pythonでも発生しています)、正規のパッケージでさえも侵害される可能性があります。広く使用されているパッケージが、新しいリリースに悪意のあるコードを含めるために一時的にハイジャックされた事例もあります。例えば、パッケージが突然使用状況のテレメトリ(スパイ行為)を送信し始めたり、特定の条件下でトリガーされるバックドアを含んだりする可能性があります。
影響:悪意のあるパッケージによる影響は、深刻かつ広範囲に及ぶ可能性があります。これらのパッケージは、インストール時(セットアップスクリプト経由)またはインポート時にコードを実行することが多いため、ユーザーができるあらゆることを実行できます。例えば、認証情報(設定ファイル、環境変数、AWS CLI設定などから)を窃取したり、トロイの木馬をインストールしたり、ファイルを暗号化したり(ランサムウェア)、リバースシェルを開いたりすることができます。また、開発者の権限で実行されることが多いため、アプリケーションだけでなく、開発者が持つシステム全体や認証情報が侵害される可能性があります。CIパイプラインでは、汚染されたパッケージがCI環境からシークレットを流出させる可能性があります。本番環境では、悪意のある依存関係が攻撃者にとって継続的なエクスプロイトのバックドアとなる可能性があります。サプライチェーン攻撃は、私たちが使用するツールへの信頼を損なうため、特に陰湿です。
緩和策: 依存関係を慎重に精査し、監視してください。 いくつかのベストプラクティス:依存関係を特定のバージョンに固定する(改ざんされたアップデートを自動的に取得しないようにするため)。パッケージのチェックサムまたは署名を検証する(PyPIは現在GPG署名などをサポートしていますが、すべてのパッケージが使用しているわけではありません)。次のようなツールを使用してください。 pip install --no-build-isolation --only-binary=:all: 既知の安全なホイールに対して、未知のパッケージのsetup.pyの実行を避けるために。ローカルのPyPIプロキシまたはミラーを導入し、精査されたパッケージのみを許可することを検討してください。常にパッケージの詳細を読んでください。もし requests が1億ダウンロードされているのに、突然新しい reqeusts パッケージが登場したら、それは疑わしいです。PyPIのセキュリティ機能(メンテナー向けの2FAなど)は改善されていますが、ユーザー側にも責任があります。 精査せずにランダムなパッケージをインストールしないでください。 os.system('curl ...')).
Aikido Securityからの注意喚起: Aikidoのプラットフォームは、サプライチェーンのリスクに多角的に対処します。まず、その 依存関係スキャン は、既知のマルウェアであるか、疑わしい動作をするパッケージを検出します。Aikidoは脅威インテリジェンス(悪意のあるパッケージの指標)を継続的に取り込み、警告を発することができます。 「パッケージXは悪意があると報告されています。使用しないでください。」 次に、Aikido SafeChain(Aikidoが提供するオープンソースツール)は、 信頼できないパッケージのインストールを防止します。これは、十分に時間が経過していないパッケージや、依存関係ツリーに突然現れたパッケージを実質的にブロックし、「クールオフ」期間(例:公開後24時間以上経過したパッケージのみをインストールするなど、新しく公開されたマルウェアを回避するため)を要求することで、タイポスクワッティング攻撃を軽減します。これらの防御策を統合することで、自動化された監視システムが追加されます。 pip installこれにより、Aikidoは、依存するライブラリが信頼を裏切らないように支援し、既知の悪意のあるアクターを捕捉し、新たなアクターが侵入しにくくするためのポリシーを適用します。
10. 脆弱な暗号化の実践(不十分なランダム性と不適切な暗号利用)
暗号化は難しく、誤った使用は、明らかなバグと同様にセキュリティを損なう可能性があります。Pythonでは、セキュリティ上重要なコンテキストで誤った乱数ジェネレーターを使用することがよくある間違いです。例えば、開発者は random.random() または random.randrange() をパスワードリセットトークンやセッションIDを生成するために使用するかもしれません。しかし、標準の random モジュールは 暗号論的に安全ではありません — 秘密の生成には適さない予測可能なアルゴリズムを使用しています。このため、Pythonは シークレット モジュールを導入し、 シークレット をセキュリティ上重要なランダム性には、 random モジュールのデフォルトの擬似乱数ジェネレーターよりも優先して使用すべきであると述べています。これは、セキュリティや暗号化ではなく、モデリングやシミュレーションのために設計されています。もし random をトークンに使用すると、攻撃者は(十分な観測やシードの知識があれば)値を予測できる可能性があります。
もう一つの脆弱な実践は、古くなったアルゴリズムや弱いアルゴリズムを使用することです。例えば、パスワードのハッシュ化にMD5やSHA1を使用すること(どちらもこの目的では破られていると見なされています)や、パスワードにソルトを全く使用しないことです。あるいは、実績のあるライブラリを使用する代わりに、独自の「暗号化」(例:自家製のXORスキーム)を実装することです。これらの脆弱性はコードにCVEとして現れないかもしれませんが、攻撃者にとってのハードルを大幅に下げます。実際の例として、パスワードがソルトなしでSHA-1で保存されている場合、ハッシュデータベースを盗んだ攻撃者は、事前に計算されたレインボーテーブルを使用してほとんどのパスワードを迅速に解読できます。
影響: 安全でないランダム性は、アカウント乗っ取りやトークン偽造につながる可能性があります。攻撃者が予測可能なPRNG出力から導出されたセッションクッキーを推測する状況を想像してみてください。これは単なる理論ではなく、設計の不十分なシステムで実際に発生しています。弱いハッシュ化や暗号化は、攻撃者が1つの層を侵害した場合(例えば、データベースへの読み取りアクセスを取得したり、暗号化されたトラフィックを傍受したりした場合)、保護されているはずのデータを簡単に復号または解読できることを意味します。全体として、弱い暗号は誤った安心感を与えます。攻撃者は、必要なものを単純にブルートフォース攻撃で推測したり、予測したりできる場合、「エクスプロイト」を必要としないかもしれません。
緩和策: 現在の 暗号化のベストプラクティスに従ってください。使用してください。 シークレット モジュール、または os.urandom() シークレットトークン、キー、またはナンスを生成するために。暗号化には、高レベルのライブラリ(例えば、 cryptography ライブラリのFernetなど)を使用し、独自の暗号化を記述することは避けてください。パスワードの保存には、確立されたKDF(bcrypt、Argon2、十分なイテレーションを持つPBKDF2)を使用し、ソルトなしのプレーンハッシュは決して使用しないでください。アルゴリズムは常に最新の状態に保ってください。例えば、SHA-256は整合性には優れていますが、パスワードにはbcryptのような低速ハッシュが依然として望ましいです。また、ネットワーク通信には常にTLSを有効にし、最新のプロトコル(TLS 1.2以降)を使用してください。基本的に、カスタムやレガシーなアプローチではなく、十分に検証された実装に委ねてください。さらに、非推奨事項にも注意してください。SSL/TLSの設定や暗号が推奨されなくなった場合(Pythonのsslモジュールは通常デフォルトを更新しますが、設定をオーバーライドする場合は注意が必要です)。
Aikido Securityからの注意喚起: AikidoのSASTは、いくつかの暗号化の誤りを特定するのに役立ちます。例えば、 random モジュールが使用されている場所が シークレット 適切であるべき場合、またはセキュリティコンテキストでMD5が使用されているのを発見した場合に警告を発することができます。さらに、Aikidoの脆弱性インテリジェンスは、以前にCVEがあったコンテキストで既知の弱いアルゴリズムを使用している場合に警告します(例えば、使用しているライブラリがデフォルトで安全でないモードになっている場合、Aikidoがそれを指摘する可能性があります)。暗号化において人間の監視は不可欠ですが、自動化されたツールで二重チェックすることは無駄ではありません。これはセキュリティのためのリンターのようなものです。誤って token = random.random()をコミットした場合、ツールは「本当に大丈夫ですか?これは暗号学的に安全ではありません」と伝えることができます。このような早期のフィードバックは、開発者を適切なモジュールへと促すことができます(場合によっては、 import secrets そして secrets.token_hex() を代替案として提案することもあります)。要するに、Aikidoは、明白な弱いパターンを検出し、エコシステムにおける暗号関連の脆弱性について情報を提供することで、暗号衛生の維持を支援します。
結論:Pythonコードを最初からセキュアにする
Pythonの柔軟性と豊富なエコシステムは、開発者にとっては強力なツールである一方で、適切な注意を払わないと攻撃者にとって多くの侵入経路を提供する諸刃の剣となり得ます。動的なコード実行、インジェクションの脆弱性、シークレットの漏洩、古い依存関係、その他の落とし穴がPythonアプリケーションのセキュリティをどのように損なうかを探ってきました。良いニュースは、これらの欠陥はそれぞれ、ベストプラクティスと適切なツールを組み合わせることで防止できるということです。
- 安全なコーディングプラクティスを採用する:入力を検証し、危険な関数を避け、安全なデフォルト(例:安全なローダー、セキュアな乱数、更新されたアルゴリズム)を使用します。
- 依存関係を最新の状態に保ち、検証する:既知のCVEが要件に残らないようにし、インストールするものには注意を払ってください。
- セキュリティを開発パイプラインに統合する:これは、インシデント発生後ではなく、コーディング中およびCI中に静的解析、シークレットスキャン、依存関係監査を実行することを意味します。
現代DevSecOps プラットフォームである Aikido は、これらの問題を自動検出することでこのプロセスを大幅に簡素化します。具体的には、ハードコードされたパスワードがノートPCから流出する前に検知したり、脆弱なパッケージのデプロイをブロックしたり、ライブラリで新たに発見された欠陥を通知したりします。Red Hatのコンテナセキュリティレポートが指摘するように、チームのほぼ半数がコンテナ(ひいてはソフトウェア)セキュリティに頭を悩ませています。Pythonアプリケーションのセキュリティについても同様の傾向があるでしょう。セキュリティを左にシフトする(つまり開発の早い段階で対応する)ことで、回避可能なPythonバグによる深夜の緊急事態発生の可能性を大幅に低減できます。
要約すると、情報収集と積極的な行動が鍵となります。セキュアコーディングについて学び続け(Python Security GuideやOWASPのリソースは非常に優れています)、セキュリティを意識したコードレビューを奨励し、自動化されたツールをセーフティネットとして活用してください。最初からセキュリティを組み込むPython開発者は、長期的には組織の時間、費用、評判を節約することになります。単に巧妙でクリーンなだけでなく、安全でセキュアなコードを書きましょう。未来の自分(そしてユーザー)がそれに感謝するでしょう。
続きを読む:
Dockerコンテナセキュリティの主要な脆弱性トップ9
クラウドセキュリティの脆弱性トップ7
すべてのチームが知るべきWebアプリケーションセキュリティ脆弱性トップ10
トップ9 Kubernetesセキュリティ脆弱性と設定ミス
現代アプリケーションで見つかるコードセキュリティ脆弱性トップ 現代のWebアプリケーションにおける主要なJavaScriptセキュリティ脆弱性トップ
ソフトウェアサプライチェーンセキュリティ脆弱性トップ9の解説
今すぐソフトウェアを保護しましょう



