イラン関連の DEV-0343 は、防衛、GIS、海事部門を標的にしています

news

DEV-0343 は、Microsoft Threat Intelligence Center (MSTIC) が最初に観測し、2021 年 7 月下旬に追跡を開始した新しいアクティビティ クラスターです。イスラエルの防衛技術企業、ペルシャ湾の通関港、または中東で事業を展開する世界的な海運会社。標的となったテナントのうち、侵害に成功したのは 20 未満ですが、DEV-0343 は攻撃を改良するために技術を進化させ続けています。 MSTIC は、多要素認証 (MFA) が有効になっている Office 365 アカウントは、パスワード スプレーに対して回復力があると述べています。

Microsoft は DEV-#### の指定を、脅威活動の未知の、新興の、または開発中のクラスターに付けられた一時的な名前として使用します。これにより、MSTIC は、発信元または身元について高い信頼に達するまで、一意の情報セットとして追跡できます。操作の背後にある俳優の。基準を満たすと、DEV は名前付きアクターに変換されます。観察された国家の攻撃者の活動と同様に、Microsoft は、標的にされた、または侵害された顧客に直接通知し、アカウントを保護するために必要な情報を提供しました。

この DEV-0343 活動での標的化は、米国、欧州連合、イスラエル政府のパートナーをサポートする防衛企業全体で観察されており、軍用レーダー、ドローン技術、衛星システム、緊急対応通信システムを生産しています。さらなる活動は、地理情報システム (GIS)、空間分析、ペルシャ湾の地域の通関港、および中東に事業を集中しているいくつかの海事および貨物輸送会社の顧客を標的にしています。

この活動は、生活パターンの分析、イランのアクターとの地理的および部門別ターゲティングの広範なクロスオーバー、およびイランを起源とする別のアクターとの技術とターゲットの調整に基づいて、イランのイスラム共和国の国益をサポートする可能性があります。マイクロソフトは、この標的設定が、イラン政府が緊急時対応計画を強化するために中東で敵のセキュリティ サービスと海運を追跡していることを裏付けていると評価しています。商用衛星画像と独自の出荷計画とログへのアクセスを得ることは、イランが開発中の衛星プログラムを補うのに役立つ可能性があります。イランが過去に海運および海運の標的に対するサイバー攻撃および軍事攻撃を行ったことを考えると、Microsoft は、この活動がこれらのセクターの企業に対するリスクを増大させると考えており、これらの業界および地理的地域のお客様には、このブログで共有されている情報を確認して、この問題から身を守ることをお勧めします。脅威。

DEV-0343 は、Firefox ブラウザをエミュレートし、Tor プロキシ ネットワークでホストされている IP を使用して、広範なパスワード スプレーを実行します。日曜日から木曜日の午前 7 時 30 分~午後 8 時 30 分 (イラン時間 (04:00:00 ~ 17:00:00 UTC)) の間で最も活動的であり、午前 7 時 30 分より前と午前 8 時以降は活動が大幅に減少します。イラン時間午後 30 時。通常、組織内の数十から数百のアカウントを対象とし、規模にもよりますが、各アカウントを数十から数千回列挙します。平均して、150 から 1,000 以上の固有の Tor プロキシ IP アドレスが、各組織に対する攻撃に使用されています。

DEV-0343 オペレーターは通常、使用する列挙/パスワード スプレー ツールの機能として、2 つの Exchange エンドポイント (自動検出と ActiveSync) を標的にします。これにより、DEV-0343 はアクティブなアカウントとパスワードを検証し、パスワード スプレー アクティビティをさらに改良することができます。

観察された行動

DEV-0343 は、精巧な一連の Tor IP アドレスを使用して、運用インフラストラクチャを難読化します。このため、このアクティビティに関連して共有できるセキュリティ侵害の痕跡 (IOC) の静的なセットはありません。以下のリストは、攻撃者によって使用されていることが観察された一連の動作と戦術を示しています。この情報を使用して、ログやネットワーク アクティビティで同様のパターンを探し、詳細な調査が必要な領域を特定することをお勧めします。

  • パスワード スプレー キャンペーンのための Tor IP アドレスからの大量のインバウンド トラフィック
  • パスワード スプレー キャンペーンでの FireFox (最も一般的) または Chrome ブラウザのエミュレーション
  • Exchange ActiveSync (最も一般的) または自動検出エンドポイントの列挙
  • https://github.com/0xZDH/o365sprayでホストされている「o365spray」ツールと同様の列挙/パスワード スプレー ツールの使用
  • 自動検出を使用してアカウントとパスワードを検証する
  • 通常、04:00:00 から 11:00:00 UTC の間にピークに達するパスワード スプレー アクティビティが観察されました。

推奨防御

次のガイダンスは、脅威活動で説明されている手法を軽減できます。

高度なハンティング クエリ

Microsoft 365 ディフェンダー

関連するアクティビティを見つけるには、 Microsoft 365 Defenderで次の高度な検索クエリを実行します。

AlertInfo
| where Title in~('Unusual sequence of failed logons to Exchange services',
'Unusual sequence of failed logons',
'Password spraying')
| join AlertEvidence on AlertId

アズールセンチネル

Azure Sentinel のお客様は、次の検出クエリを使用して、このアクティビティを探すことができます。

以下のクエリは、ClientAppUsed が Exchange ActiveSync または Autodiscover であり、エミュレートされたブラウザーが Chrome または Firefox である場合のパスワード スプレー アクティビティの証拠を識別します。クエリは Azure AD データを利用して、時間枠内で同じ IP アドレスから複数のアカウントのエラーを探します。時間枠内で IP アドレスによる認証が成功したかどうかの詳細も含まれます。これは、攻撃が成功したことを示している可能性があります。デフォルトの失敗アカウントのしきい値は 5 で、失敗のデフォルトの時間枠は 20 分です。

timeRange = 3d;
見てみましょう = 7d;
authenticationWindow = 20m を許可します。
authenticationThreshold = 5 にします。
let isGUID = "[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0 -9a-z]{12}";
let failureCodes = dynamic([50053, 50126]); // 無効なパスワード、アカウントがロックされている - サインインが多すぎる、パスワードの有効期限が切れている
let successCodes = dynamic([0, 50055, 50057, 50155, 50105, 50133, 50005, 50076, 50079, 50173, 50158, 50072, 50074, 53003, 53000, 53001, 50129]);
let ClientApps = dynamic(["AutoDiscover","Exchange ActiveSync"]);
let BrowserList = dynamic(["Chrome","Firefox "]);
// 過去 7 日間に解決された ID を検索します
let aadFunc = (テーブル名:文字列){
let identityLookup = table(tableName)
| |どこで TimeGenerated >= ago(lookBack)
| | where not(ID は正規表現の isGUID と一致します)
| |どこにありません(UserId)
| | UserId、lu_UserDisplayName = UserDisplayName、lu_UserPrincipalName = UserPrincipalName、Type で要約します。
// ウィンドウのしきい値違反を収集します
テーブル(テーブル名)
| |どこで TimeGenerated > ago(timeRange)
| | where ResultType in(failureCodes)
| | StartTime = min(TimeGenerated)、EndTime = max(TimeGenerated)、make_set(ClientAppUsed)、count() by bin(TimeGenerated、authenticationWindow)、IPAddress、AppDisplayName、UserPrincipalName、Type を要約します。
| |まとめ FailedPrincipalCount = dcount(UserPrincipalName) by bin(TimeGenerated, authenticationWindow), IPAddress, AppDisplayName, Type
| |ここで、FailedPrincipalCount >= authenticationThreshold
| |まとめ WindowThresholdBreaches = count() by IPAddress, Type
| |結合種類 = 内部 (
// しきい値を超えた場合は、すべての障害データの詳細を結合して戻します
テーブル(テーブル名)
| |どこで TimeGenerated > ago(timeRange)
| | where ResultType in(failureCodes)
| |拡張 LocationDetails = todynamic(LocationDetails)
| |拡張 FullLocation = strcat(LocationDetails.countryOrRegion,'|', LocationDetails.state, '|', LocationDetails.city)
| |拡張 DeviceDetail = todynamic(DeviceDetail)
| |拡張 Browser = DeviceDetail.browser
| | StartTime = min(TimeGenerated)、EndTime = max(TimeGenerated)、make_set(ClientAppUsed)、make_set(FullLocation)、make_set(Browser)、FailureCount = count() を IPAddress、AppDisplayName、UserPrincipalName、UserDisplayName、Identity、UserId、Type ごとに要約します。
// 未解決の ID を検索します
| | extends UnresolvedUserId = iff(ID は正規表現 isGUID、UserId、"" と一致します)
| |結合種類= leftouter (
IDルックアップ
) $left.UnresolvedUserId==$right.UserId で
| | extend UserDisplayName=iff(isempty(lu_UserDisplayName), UserDisplayName, lu_UserDisplayName)
| | extends UserPrincipalName=iff(isempty(lu_UserPrincipalName), UserPrincipalName, lu_UserPrincipalName)
| | StartTime = min(StartTime)、EndTime = max(EndTime)、make_set(UserPrincipalName)、make_set(UserDisplayName)、make_set(set_ClientAppUsed)、make_set(set_Browser)、make_set(set_FullLocation)、make_list(FailureCount) を IPAddress、AppDisplayName、Type 別に要約します。
| |拡張 FailedPrincipalCount = arraylength(set_UserPrincipalName)
) の IP アドレス
| |プロジェクト IPAddress、StartTime、EndTime、TargetedApplication=AppDisplayName、FailedPrincipalCount、UserPrincipalNames=set_UserPrincipalName、UserDisplayNames=set_UserDisplayName、ClientAppUsed=set_set_ClientAppUsed、Locations=set_set_FullLocation、FailureCountByPrincipal=list_FailureCount、WindowThresholdBreaches、Type、Browser = set_set_Browser
| |結合種類 = 内部 (
table(tableName) // 各 IP の成功と失敗の履歴に関するデータを取得します
| |どこで TimeGenerated > ago(timeRange)
| | where ResultType in(successCodes) or ResultType in(failureCodes) // 成功または失敗のタイプ
| |要約 GlobalSuccessPrincipalCount = dcountif(UserPrincipalName, (ResultType in(successCodes)))、ResultTypeSuccesses = make_set_if(ResultType, (ResultType in(successCodes)))、GlobalFailPrincipalCount = dcountif(UserPrincipalName, (ResultType in(failureCodes)))、ResultTypeFailures = make_set_if( ResultType、(ResultType in(failureCodes))) IPAddress、Type による
| | where GlobalFailPrincipalCount > GlobalSuccessPrincipalCount // 失敗したプリンシパルの数が成功よりも多い場合 - 認証に成功した IP から FP を排除し、副作用として多くの失敗があります
) の IP アドレス
| |プロジェクトアウェイ IPAddress1
| |タイムスタンプを拡張 = StartTime、IPCustomEntity = IPAddress
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
ユニオン isfuzzy=true aadSignin, aadNonInt
| |ブラウザには has_any (BrowserList)
| |どこ ClientAppUsed has_any (ClientApps)

 

クエリが表示する結果の 1 つは、サインインの発信元の IPAddress フィールドです。お客様は、TOR 出口ノードに関する詳細を含む脅威インテリジェンス データを活用して、このクエリに参加し、さらに忠実度を高めることができます。 Azure Sentinel のクエリとの照合に使用したり、条件付きアクセスを使用して TOR 出口ノードからのサインインをブロックしたりできるように、既知のすべての TOR 出口ノードのリストを用意しておくことは、多くの場合価値があります。 Azure Sentinel は、ビッグ データ クラウドなどの TOR 情報のサード パーティ プロバイダーを利用して、1 時間ごとに既知の TOR 出口ノードのリストを同期できるプレイブックも提供します。そのようなプレイブックの 1 つへのリンクは次のとおりです: https://github.com/Azure/Azure-Sentinel/blob/master/Playbooks/Update-NamedLocations-TOR/readme.md

次に、1 つのユーザー アカウントで非常に揮発性の高い IP アドレスからの試行が失敗する頻度が高いインスタンスを特定する別のハンティング クエリがあります。パスワードを試行するたびに IP アドレスを変更することは、巧妙な脅威グループの間でより一般的な手法になりつつあります。多くの場合、脅威グループは、使用しているユーザー エージェントと IP アドレスをランダム化します。この手法は、膨大な数の住宅用 IP アドレスを提供するサービスの出現によって可能になりました。これらのサービスは、多くの場合、悪意のあるブラウザー プラグインによって有効化されます。このクエリは、より長い時間枠で実行するのが最適です。 「IPs」、「Failures」、および「DaysWithAttempts」が最も高い結果は、さらに調査するのに適した候補です。このクエリは、意図的に UserAgent、IP などでクラスター化されません。このクエリは、非常に不安定な IP 動作でクラスター化されます。

timeRange = 14d;
Let UnsuccessfulLoginCountryThreshold = 5; // ログインに失敗した国の数。フィルタリングする良い方法です。
let ClientApps = dynamic(["AutoDiscover","Exchange ActiveSync"]);
let BrowserList = dynamic(["Chrome","Firefox "]);
サインインログ
| |どこで TimeGenerated > ago(timeRange)
// ブルートフォース/スプレー時に最も一般的な、ユーザー名/パスワードの失敗エラーに制限
| |どこで ResultType has_any("50126", "50053")
//この攻撃で見られる clientapps と browsers に結果をさらに絞り込みます。
| |どこ ClientAppUsed has_any (ClientApps)
| | extends Browser = tostring(DeviceDetail.browser)
| |どこで Browser has_any (BrowserList)
// IP が 1 回しか使用されていないインスタンスを見つける
| | IPLogins=count()、make_list(TimeGenerated) を IPAddress、Location、UserPrincipalName で要約
| |ここで IPLogins == 1
// イベントが 1 つあるインスタンスのみを保持するため、リストには datetime が 1 つしかないことがわかっています
| |拡張 LoginAttemptTime = format_datetime(todatetime(list_TimeGenerated[0]), 'dd-MM-yyyy')
// ここまでは失敗のみを収集しました。ログに戻って、IP からの成功したログインがないことを確認します
| |結合の種類= leftouter (
サインインログ
| |どこで TimeGenerated > ago(timeRange)
| |ここで、ResultType == 0
| | count() を IPAddress ごとに要約、UserPrincipalNameSuccess=UserPrincipalName
) $left.IPAddress で == $right.IPAddress
// IP からの成功したログインが 2 回未満の場合
| |ここで、count_ < 2 または isempty(count_)
// 可能であれば、結果が同じアカウントのものであることを確認します
| |ここで、UserPrincipalName == UserPrincipalNameSuccess または isempty(UserPrincipalNameSuccess)
// ユーザーのメールアドレスに関する収集された詳細を要約します
| |まとめ IPs=dcount(IPAddress), UnsuccessfulLoginCountryCount=dcount(Location), make_list(IPAddress), make_list(Location), DaysWithAttempts=dcount(LoginAttemptTime), Failures=count() by UserPrincipalName
| |プロジェクト UserPrincipalName、失敗、IP、UnsuccessfulLoginCountryCount、DaysWithAttempts、IPAddresses=list_IPAddress、IPAddressLocations=list_Location
// 再度参加して、ユーザーが認証に成功した国を取得し、失敗した国と比較します
| |結合の種類= leftouter (
サインインログ
| |どこで TimeGenerated > ago(timeRange)
| |ここで、ResultType == 0
// 場所がない場合、出力をきれいにします
| |拡張場所 = iff(isempty(場所)、「NODATA」、場所)
| | UserPrincipalName ごとに、SuccessfulLoginCountries=make_set(Location)、SuccessfulLoginCountryCount=dcount(Location) を要約します。
) $left.UserPrincipalName で == $right.UserPrincipalName
| |プロジェクト離れた UserPrincipalName1
| | UnsuccessfulLoginCountryCount desc 順
// ログインが成功した国と失敗した国の違いを計算します
| |拡張 IPIncreaseOnSuccess = UnsuccessfulLoginCountryCount - SuccessfulLoginCountryCount
// アクターが 1 つの国で IP を使用している場合は、以下の行を削除できます
| |どこで UnsuccessfulLoginCountryCount > UnsuccessfulLoginCountryThreshold
| |プロジェクト UserPrincipalName、Failures、IPs、DaysWithAttempts、UnsuccessfulLoginCountryCount、UnuccessfulLoginCountries=IPAddressLocations、SuccessfulLoginCountries、FailureIPAddresses=IPAddresses

参照: https://www.microsoft.com/en-us/security/blog/2021/10/11/iran-linked-dev-0343-targeting-defense-gis-and-maritime-sectors/

Comments

Copied title and URL