誰かがJavaScriptの安全なコーディングガイドラインを推奨できますか?
JavaScriptプログラミング言語に密接に関連している一連の一般的な脆弱性はありますか?私が探しているのは、c/c ++プログラミング言語に密接に関連するスタック、ヒープ、またはバッファオーバーフローの同等の脆弱性です。
JavaScriptコンテキスト内の静的コード分析ツール用のツールを推奨できますか?
完全な開示:次のガイドは Checkmarx の調査チームによって作成されました CxSAST (静的コード分析ツール)の作成者、ここで雇用されています。
JavaScriptセキュアコーディングプラクティスガイドは次のとおりです。
JavaScriptは最近、アプリケーションのフロントエンドとバックエンドの両方で使用されているため、JavaScriptでの開発中に知っておくべき脆弱性や問題が数多くあります。
いくつか例を挙げると... :)
私は JavaScriptの脆弱性 についての記事を書いたので、私はここで助けることができると信じています:
JavaScriptのセキュリティの脆弱性のほとんどは、エンドユーザーとの対話の結果として発生します。
悪意のあるユーザーは、クエリ文字列をフォームに入力して、保護されたデータにアクセスしたり、データを汚染したりできます。
したがって、ユーザー入力に検証ミドルウェアを追加するのは、エンジニアリングチームの責任です。
以下に、最も一般的なJavaScriptの脆弱性を示します。
クロスサイトスクリプティング(XSS)
WebアプリケーションとJavaScriptを含む最も一般的な攻撃の1つは、クロスサイトスクリプティングの脆弱性で、OWASPトップ10 Webアプリケーションのセキュリティリスクに含まれています。
XSS攻撃はWebアプリケーションの欠陥であり、悪意のあるユーザーがWebサイトでJavaScriptコードを実行できるため、ほとんどすべてのWebサイトでユーザーのブラウザーでJavaScriptを有効にする必要があるため、XSS攻撃が人気です。
クロスサイトスクリプティングは、主に次の2種類です。-クライアントXSS-サーバーXSS
クライアントXSS
このタイプの脆弱性は、リモートの場所(主にAPI)から提供された信頼できないデータを使用して、安全でないJavaScript呼び出しでDOMを更新する場合に発生します。例として、以下のスニペットは、信頼できないAPIから気象情報を取得して、現在の気象情報を表示します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>DEMO XSS</title>
</head>
<body>
<p>Today's weather information reads: </br>
<div id="temp"></div>
</p>
<script type="text/javascript">
let untrusted_ajax_res = document.write(location.replace("https://www.w3schools.com"));
document.getElementById("temp").innerHTML=untrusted_ajax_res;
</script>
</body>
</html>
The snippet above shows how malicious code from an untrusted API can be injected into the DOM.
To prevent client xss attacks, developers can install secure xss filters which can be used to sanitise inputs gotten from untrusted domains/locations. A snippet for a web use-case can be seen below:
<!DOCTYPE html>
...
<script src="dist/xss-filters.min.js"></script>
<script>
let untrusted_ajax_res = document.write(location.replace("https://www.w3schools.com"));
document.getElementById("temp").innerHTML=xssFilters.inHTMLData(untrusted_ajax_res);
</script>
-xss-filtersパッケージは、UTF-8でエンコードされたドキュメントにのみ適用する必要があります。 HTML5モードも必要です。
サーバーXSSこのタイプの脆弱性は、信頼できないデータがユーザー入力として含まれ、データベースに格納されるバックエンドに送信されるときに発生します。このデータは、ユーザーに送り返されるときに悪意のあるJavaScriptコードを含む、ユーザーに送り返される応答を計算するために使用されます。
エクスプレスベースのノードサーバーに対するサーバーXSS攻撃の例を以下のスニペットに示します。
...
app.get('/search', (req, res) => {
const results = db.search(req.query.product);
if (results.length === 0) {
return res.send('<p>No results found for "' + req.query.product + '"</p>');
}
...
});
上記のスニペットは、 http://www.domain.com の製品検索ルートの定義を示しています。 XSS攻撃は、次のようにサーバーのクエリとしてJavaScriptコードを渡すことで実行できます。
https://www.domain.com/search?product=<script>alert(XSS:Gat Ya!!)</script>
次のようなレコードはないので
<script>alert(XSS:Gat Ya!!)</script>
データベースでは、サーバーの応答は次のようになります。
<p>No results found for "<script>alert(XSS:Gat Ya!!)</script> </p>
サーバーの応答が受信され、結果が見つかりませんでしたが表示された後、スクリプトはDOMに挿入され、以下に示す出力が提供されます。
このスクリプトは深刻な脅威を引き起こさないため、それほど深刻ではないように見えます。ただし、攻撃者はブログ/ソーシャルメディアサイトで悪意のあるコードを「コメント」として保存できます。これらのいわゆるコメントは、他のユーザーに提供されると、DOMに挿入され、攻撃者の希望を実行します。この脆弱性を修正するには、次のようにnpmを使用してxss-filterパッケージをインストールします。
$ npm i xss-filters --save
インストール後、次のようにサーバーの応答でユーザーの入力をフィルタリングできます。
...
var xssFilters = require('xss-filters');
app.get('/search', (req, res) => {
var productParam = req.query.product;
const results = db.search(req.query.product);
if (results.length === 0) {
res.send('<p>No result found for "' + xssFilters.inHTMLData(productParam) + '"</p>');
}
});
...
SQLインジェクション
SQLインジェクションは、Webアプリケーションの背後にあるデータベースを制御するSQLステートメントを実行できるようにする攻撃の一種です。 SQLインジェクション攻撃は、以下のコードスニペットで確認できます。
...
const db = require('./db');
app.get('/products', (req, res) => {
db.query('SELECT * FROM products WHERE id = ' + req.query.id);
.then((product) => {
...
res.send(product);
})
});
上記のコードスニペットには2つの問題があります。
データベースクエリは、文字列連結によって構築されます。
db.query( 'SELECT * FROM products WHERE id = $ 1'、req.query.id);
上記のスニペットでは、データベースクライアントはreq.query.idを最初の引数として渡します。ノードのMySQLパッケージはパラメーター化されたクエリをサポートしていませんが、次のようにクエリ文字列と連結する前に、ユーザー入力をエスケープ(つまり、すべての特殊文字を削除)できます。
const query = 'SELECT * FROM products WHERE id = ' + connection.escape(req.query.id);