2018年7月6日金曜日

Active Directoryのパスワードに特定の文字の利用を禁止する

こんにちは、富士榮です。

先日紹介したAzure ADの新機能「Azure AD Password Protection for Windows Server Active Directory」を使うとブラックリストに載っているパスワードを使うことを禁止することは出来る様になりますが、特定の文字だけを禁止することは今のところ出来なさそうです。

エンタープライズのレガシーなID管理のシナリオだと未だにCSV万能説な文化なので、パスワードに特定の文字を使えなくしたい、というニーズがそこそこあります。
例えば、「,」(カンマ)とか「”」(ダブルクォート)とか「’」(シングルクォート)とかですね。なぜなら、平文パスワードをCSVに載せてFTPで送りつける、ということをしようとすると、この辺りの記号が邪魔をするんですよね・・・。

この辺りに起因する不具合を防止するために、CTRL+ALT+DELを使ったパスワード変更をグループポリシーで禁止して、ID管理パッケージの持つパスワード管理画面からしかパスワードを変更させない様に構成、ID管理システムではパスワードに利用できない文字を定義する、というのが従来の王道パターンでした。

しかし、やはりWindowsの標準の仕組みでパスワード変更を許可したい、というニーズは根強く、各社パスワード・フック用のモジュールをリリースしていたり、という状況です。

当ブログでもほぼ10年前に紹介した「Active Directoryのパスワード変更をフックする」という記事へのアクセスが以外と息が長く、今でもアクセス数トップ3くらいには入っていたりして、何とかしてADのパスワードを引っこ抜いてやろう、という人々が数多く存在するんだな~(違)と感じている今日この頃です。


最近も某所でCSVにパスワードを出力したいからカンマを使えない様にしたい、と言う雑談をしていたりしたので、良し悪しはおいておいてちょっと書いてみました。

この辺りにおいてあります。
 https://github.com/fujie/pwdpol

Visual Studio 2017でC++のDLLを書く、というのも最近は中々無い経験なので新鮮な感じです。

ちゃちゃっと書いたので、エラーハンドリングやログ出力などもありませんし、Visual Studio 2017 on Windows 10 Proで作って、Windows Server 2012 R2で動作確認をしたので、VC++のランタイムのバージョンを合わせるのが面倒だったので、必要なDLL(msvcp140d.dll、vcruntime140d.dll、ucrtbased.dllの3つ)をC:\Windows\System32へコピーするとか強引なことをしてますが、皆さんはちゃんと必要なランタイムの再配布用パッケージをダウンロードして使ってください。

使い方は、ドメインコントローラ上で
・必要なDLLをC:\Windows\System32へ配置
・レジストリへの登録
・再起動
という3ステップですが、こちらは昔の記事と何も変わらないので、こちらをご参照ください。
https://idmlab.eidentity.jp/2018/06/azure-ad-ngad.html

こんなコードです。
<本体:pwdpol.cpp>

#include "stdafx.h"
#include <ntsecapi.h>
#include <regex>

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif

using namespace std;

// initialize
BOOLEAN NTAPI InitializeChangeNotify(void) {
    return TRUE;
}

// evaluate filter
BOOLEAN NTAPI PasswordFilter(
    PUNICODE_STRING AccountName,
    PUNICODE_STRING FullName,
    PUNICODE_STRING Password,
    BOOLEAN SetOperation) {

    BOOLEAN ret;

    // filter in regular expression
    const wchar_t* pattern = LR"([\"\',])";

    // convert PUNICODE_STRING to wstring
    std::wstring pwd(Password->Buffer, Password->Length / sizeof(WCHAR));
    
    // search filtered charactors
    regex_search(pwd, wregex(pattern)) ? ret = FALSE : ret = TRUE;

    // clear buffer
    SecureZeroMemory((PVOID)pwd.c_str(), pwd.size());

    return ret;
}

// notify change
NTSTATUS NTAPI PasswordChangeNotify(
    PUNICODE_STRING UserName,
    ULONG RelativeId,
    PUNICODE_STRING NewPassword) {

    // nop
    return STATUS_SUCCESS;
}
<定義:pwdpol.def>

LIBRARY "pwdpol"
EXPORTS
    InitializeChangeNotify
    PasswordFilter
    PasswordChangeNotify


DLLの配置をして再起動すると上手くいけばポリシーが有効になります。
管理者がカンマを含むパスワードでリセットしようとしても

ユーザが自分でしようとしても、

ダメです。弾かれます。

これでパスワードをCSVに出力し放題です。何も気にすることはありません。どんどん出力してFTPでばらまきましょう。ファイルサーバにおいてCIFSで共有するのもいいアイデアです。

良い子はマネしちゃいけませんよ。



0 件のコメント:

コメントを投稿