ホームページ > バックエンド開発 > PHPチュートリアル > 一般的な PHP の脆弱性に関する第 3 章: インジェクションの脆弱性

一般的な PHP の脆弱性に関する第 3 章: インジェクションの脆弱性

WBOY
リリース: 2016-06-23 09:09:35
オリジナル
1252 人が閲覧しました

インジェクションは、おそらくユーザーが制御できるいくつかの変数をデータベース操作に取り込み、SQL の本来の意味を変更する効果があります。たとえば、ユーザーを登録するロジックでは、ユーザー名が存在するかどうかを確認するときに、ユーザーが送信したユーザー名をデータベースから取得してクエリします。ユーザー名がコード ロジックでフィルターされていない場合、ユーザーはいくつかの特殊文字を送信して挿入を完了できます。

現在インジェクションを行う主な理由は、多くのプログラマーが依然として SQL ステートメントを作成するときにステートメントを結合することを好むためです。

SQL の分類によれば、インジェクションは一般に次の 4 つのタイプに分類されます。

    mysql エラーがある場合、次の 4 つが考えられます。エラーを報告するために使用されます。注入は非常に便利です。
  • mysql エラーがない場合は、

  • 注入を選択します。エコーがない場合は、union select+echo を使用して注入してみてください。

  • 更新の挿入: 更新セット内にある場合、このテーブルのどの列が表示されるかを見つけることができます。たとえば、更新の挿入ポイントがユーザー テーブル内にあり、設定された位置で制御できる場合、電子メール列を更新し、ユーザー プロファイルに移動して電子メールを確認し、そのようなステートメントを取得できます。 as update table set email=( select user()); where の後にある場合、通常はブラインド インジェクションです。

  • インサートインジェクション: 一般的には、どの列が表示されるかを調べて、この列に出力するデータを挿入しようとします。 表示されない場合もブラインドベットとなります。

削除の注入: 通常はブラインド注入です。

    数値注入の主な理由は、その変数が一重引用符で囲まれていないことです。ただし、基本的には intval($username) などの型変換を強制されます。しかし、時には見落としてしまうこともあります。
  1. 文字の種類と検索の種類は一重引用符で囲まれます。したがって、注入する前に一重引用符を閉じる必要があります。

  2. シングルクォーテーションと言えば、php.ini の Magic_quotes_gpc の設定についてですが、少し上位のバージョンではデフォルトでオンになっていますが、5.4 では廃止されました。

  3. 文字通り、これは GPC への引用です。 GPC は GET、POST、COOKIE に対応します。コンテンツ内でエスケープされる文字は ' " NULL です。エスケープ方法は、先頭にエスケープ文字を追加することです。その結果、本来の意味が失われ、単一の単語をエスケープすることはできません。引用符は挿入に使用されます。
  4. グローバルに addlashes はありません。
  5. この種のメーカーは、 に直接クエリを実行する場合でも、基本的にユーザーが制御できる変数を addlash します。 addslashes を追加せずにクエリを実行します。
  6. クエリ中に addslashes を追加した場合でも、多くの場合、addslashes をグローバルに実行します

    現在、グローバル ファイルで GET/POST/COOKIE に対して addslashes を実行する方法をよく知っているメーカーが増えています。クエリに取り込まれた関数でエスケープしたりプリコンパイルしたりしても、これは恥ずかしいことです) したがって、基本的には、addslashes の欠落や忘れを心配する必要はありません) 基本的な方法は、まずマジック クオート gpc を取得して、gpc がオンになっているかどうかを判断することです。有効になっていない場合は、addslashes を呼び出してエスケープします。
一般的な注入方法をいくつか示します

ワイドバイト注入

これは一般的な問題です。データベースキャラクタセットGBKのワイドバイトインジェクションから長い時間が経ちましたが、キャラクタセットがGBKであればワイドバイトをインジェクションできるというわけではありません

CMSキャラクタセットは常にそう言っています。 see は gbk ですが、なぜワイド バイトにできないのですか?

これは、データベース接続の場合、Set names gbk を使用してワイド バイトを取得できるためです。バイナリ読み取りは基本的に設定されているため、ほとんど見られませんが、utf8 から gbk への変更、または gbk から utf8 への変更など、別の種類のワイドバイトインジェクションが発生します。例: WooYun: 74cms。最新バージョン インジェクション 8. -9

分析: UTF8 から GBK に変換された後、単語「Jin」は %e5%5c 74 になりました。cms には GET/POST/COOKIE などのラッシュが追加されているため、「エスケープされます」 - >% 5C %e5%5c%5c' が 2 つあるとシングルクォーテーションが出てきます。

例 2: WooYun: qibocms ダウンロード システム SQL インジェクション (公式 Web サイトで再現できます)

解码导致注入

因为在全局文件中addslashes,如果我们能找到一些解码的,例如urldecode、base64_decode之类的,那么我们先提交encode之后的,那么就能不被转义了。然后decode后,再带入查询,造成了注入,无视gpc。

这种的很常见。例子很多 随便找一个

例子: WooYun: qibocms B2b 注入一枚//qibocms 注入

例子: WooYun: phpdisk V7 sql注入2//phpdisk 注入

变量覆盖导致的注入

常见的变量覆盖 有啥extract 和 parse_str 函数啥的,当然还有$$。

变量覆盖得结合一些具体的场景了。例如extract($_POST)啥的,直接从POST数组中取出变量。这样的还是遇到过几个,然后覆盖掉之前的一些变量。

覆盖的话,一般是覆盖掉表前缀之类的。譬如 Select * from $pre_admin where xxx像这种的就覆盖掉$pre,然后直接补全语句然后注入。

例子: WooYun: qibocms分类注入一枚可提升自己为管理

例子2: WooYun: phpmps 注入一枚

当然 $$ 也挺经常用到的 这个例子很不错。

例子3: WooYun: MetInfo最新版(5.2.4)一处SQL盲注漏洞

一些replace造成的注入

一些cms中,总有一些逗比过滤函数,譬如会把’ 啥的replace成空,但是他似乎忘记了自己全局有转义。

这时,当用户提交一个',全局转义成\',然后这过滤函数又会把'替换成空,那么就留下了\,导致可以吃掉一个单引号,是double query的话

select * from c_admin where username=’admin\’ and email=’inject#’
ログイン後にコピー

这样就可以注入了。

例子: WooYun: PHPCMS全版本通杀SQL注入漏洞

当然还有一些replace是用户可控的。就是说用户可以想把啥提交成空就提交成空,例如很久前的cmseasy和ecshop的那个注入。

例如这段代码:

$order_sn = str_replace($_GET['subject'],'',$_GET['out_trade_no']);
ログイン後にコピー

这里因为会被转义,如果提交'就成 \',这里可以看到,这里清成空的,是我们get来的,那我们就想办法把\给replace掉。

但是如果我们GET提交把\给replace,那么会被转义,就是replace掉\。但是我们只是\',所以不能把\去掉,如果我有\,还要你清空个毛啊。

这里我们来理清一下思路:

Addslashes 会对' " \ NULL 转义

'    => \'"    => \"\    => \\NULL => \0
ログイン後にコピー

那这里我们就提交%00’,就会被转义生成 \0\' ,这时候我们再提交把0替换成空,那么就成了\',单引号也就成功出来了。

例子: WooYun: cmseasy绕过补丁SQL注入一枚

SERVER未转义导致的注入

因为在很多cms中,基本上都只是对GET POST COOKIE 进行addslashes,而没有对SERVER进行转义。而一些SERVER的变量也是用户可以控制的。例如什么 QUERY_STRING X_FORWARDED_FOR CLIENT_IP HTTP_HOST ACCEPT_LANGUAGE 很多。

这里最常见的当然也就是X_FORWARDED_FOR,这个一般是在ip函数中用到。如果后面没有进行验证ip是否合法的话就直接return,这个大部分时候都会导致注入。

例子1: WooYun: Phpyun注入漏洞二

这里说到验证ip,这里基本都是用的正则来验证是否合法。而一些厂商连正则都写错。例如在cmseasy中的验证ip的正则中(%.+),导致了后面可以写任意字符。

例子2: WooYun: CmsEasy最新版本无限制SQL注射

FILES未转义导致的注入

这个也差不多,也是因为全局只对COOKIE GET POST 转义,遗漏了FILES,且不受gpc。

FILES注入一般是因为上传,会把上传的名字带到insert当中入库。然后这里文件的名字是我们可以控制的,所以导致了注入。

例子: WooYun: qibocms 黄页系统SQL注入一枚

还有一些,在入库的时候才对文件的名字进行了转义,而在获取后缀后,在入库的时候对文件名转义了却没有对后缀转义也导致了注入

例子: WooYun: Supesite 前台注入 #2 (Insert)

未初始化造成的注入

很久以前php<4.20的时候,为了方便,register_globals默认都是on。而到了后面register_globals的弊端也显现了出来, 所以也在很久以前默认都是off了。

而到了现在, 很多cms却喜欢模仿register_globals 搞起了伪全局机制。例如啥qibocms metinfo destoon 啥的啊。

这样是方便了不少, 但是如果哪里遗漏了初始化,那么就会导致注入了。感觉这种的挺好玩的 多找了几个例子。

例子: WooYun: qibocms地方门户系统注入一个问题(demo测试)

例子: WooYun: qibocms地方门户系统注入(多处类似,demo测试)

例子: WooYun: 齐博地方门户系统SQL注入漏洞(无需登录可批量)

例子: WooYun: 齐博整站/地方门户SQL注入漏洞

数组中的key导致的注入

因为在对全局转义的时候,很多cms都只是判断gpc是否开启,如果off,就对数组中的value就行addslashes,却忘记了对数组中的key进行转义。

那么这样也导致了一个问题。也就是在Gpc off的时候那么数组的key没有被过滤,导致可以引入单引号。(听说低版本的php对二维数组中的key就算gpc on 也不会转义)

如果哪里把数组中的key,读取出来,然后把key带入到了查询当中,那么也会造成安全问题。

而且这样的例子很多。 简直惨不忍睹。

例子: WooYun: qibocms V7 整站系统最新版SQL注入一枚 & 另外一处能引入转义符的地方。//数组key的注入

例子: WooYun: qibocms多个系统绕过补丁继续注入2

例子: WooYun: qibocms全部开源系统 Getshell

例子: WooYun: Discuz 5.x 6.x 7.x 前台SQL注入漏洞一枚

offset造成的注入

这种算是比较常见的一种注入的。

代码大概如下:

<?php$key=0;$a=$_GET[a][$key];$b=$_GET[b];Mysql_query("select * from table where xxx='$a' and xx='$b'")
ログイン後にコピー

如果这里$_GET[a] 提交的是一个数组,且含有一个key为0的,那么$a就是对应的这个key的value。

但是这里并没有强制要求为数组。那么我们提交一个字符串,那么后面的[0]就是截取的第一个字符。在全局中,单引号被转义为\',截取第一个字符就为了\。\会吃掉一个单引号,然后就在$b处写入inject可以注入了。

例子: WooYun: qibocms 地方门户系统 注入#4(demo测试)

还有map发的那Disucz 7.2的那注入也一样。

第三方插件导致的注入

很常见的一种洞。比较常见的uc和alipay tenpay chinabank 啥的特别是uc,因为默认uc里面都会striplashes

Uc的话,一般会遇到的问题是uckey默认的。或者是uckey这个常量根本就没有初始化,导致了uckey可控,再导致了Getshell或者注入啥的。

还有tenpay 和 alipay 啥的,一些是因为忘记把过滤的文件包含进来,且key默认是空的,导致可以通过验证。

例子: WooYun: phpmps 注入 (可修改其他用户密码,官网成功)// phpmps uc致注入

例子: WooYun: PHPEMS (在线考试系统) 设计缺陷 Getshell一枚(官网已shell)/phpems uc致getshell

例子: WooYun: 最土团购注入一枚可直接提升自己为管理 & 无限刷钱。//最土团购 chinabank致注入

例子: WooYun: Destoon Sql注入漏洞2(有条件)//destoon tenpay致注入

例子: WooYun: CSDJCMS程式舞曲最新版Sql 一枚//csdj tenpay致注入

数字型注入

其实也不只是数字型,只是说一些忘记加单引号的地方都这样。这里只是一般数字型的都不会加单引号的。

一般的是这样:

$id=$_GET[id];Select * from table where id=$id;
ログイン後にコピー

$id,没被单引号,且没有被强制类型转换,那么就算addslashes了,由于不需要去闭合单引号,所以也无影响。

例子: WooYun: qibocms 地方门户系统 注入#3 (demo测试)

并不是一些数字型,一些其他的点也有些忘记加单引号,导致了注入。

例子: WooYun: Supesite 前台注入 #3 (Delete)

二次注入

也是一种比较常见的注入。涉及到的是入库和出库。因为有全局转义,然后入库的时候

insert into table (username) values ('a\'');

这样入库后,转义符就会消失,那么就是a'。如果哪里再把这个查询出来,那么也就是出库的是a',如果再把出库的 再带入到了查询啥的,那么就再次成功的引入了单引号导致了注入。

例子: WooYun: phpyun v3.2 (20141226) 两处注入。

例子: WooYun: qibocms 地方门户系统 二次注入#5(demo测试)

例子: WooYun: 74cms (20140709) 二枚二次注入

例子: WooYun: Hdwiki最新版二次注入一枚

截取字符导致的注入

有些cms有的时候会限制用户输入的长度,所以只截取一部分

例如uchome的cutstr($asd,32);

这样只允许输入32个字符,而且uchome里面的这个也没有像dz那样截取字符的后面加...

したがって、 11111111111111111111111111111' を送信すると、エスケープされて 1111111111111111111111111111111'

となり、32 文字がインターセプトされます。これは 111111111111111111111111111111 1

再び二重クエリの場合は、一重引用符を食べると、次に接続された制御可能な変数を挿入できます。 ... 以前に不適切に処理されたセキュリティ脆弱性) //

内の 0x06 は、元のテキストに基づいて簡単な編集と変更を加えて、http://drops.wooyun.org/papers/4544 から転載されています。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート