
Golangで書かれたADWSの実用的なクライアント
Sopaは、ADWSプロトコルスタック(MS-NNS + MC-NMF + SOAP)を実装し、以下のコマンドライン機能を提供します:
query:WS-EnumerationのEnumerate + Pullループを使用したLDAPフィルタ検索を実行し、属性の射影、スコープ制御(Base/OneLevel/Subtree)、ページネーションをサポートget:WS-TransferのGetを使用してDNで単一のオブジェクトを取得create:WS-TransferのResourceFactoryを使用してオブジェクトを作成(組み込み型:user、computer、group、OU、container;またはYAMLテンプレートを使用したIMDAのAddRequestによるカスタムオブジェクト)delete:WS-TransferのDeleteを使用してDNでオブジェクトを削除attr:WS-TransferのPutを使用して既存のオブジェクトの個別の属性値を追加、置換、削除set-password:MS-ADCAPのを使用してアカウントパスワードを設定$ go install github.com/Macmod/sopa/cmd/sopa@latest
# Auth flags (-u, -p, -d, -k, -H, -c, ...) are omitted for brevity - see Authentication section.
# Search objects by LDAP filter
$ sopa [auth_flags] query --dc <DC> --filter '(objectClass=*)'
# Fetch a single object by DN
$ sopa [auth_flags] get --dc <DC> --dn '<DN>'
# Delete an object by DN
$ sopa [auth_flags] delete --dc <DC> --dn '<DN>'
# Edit attribute values
$ sopa [auth_flags] attr add --dc <DC> --dn '<DN>' --attr <ATTR> --value <VALUE>
$ sopa [auth_flags] attr replace --dc <DC> --dn '<DN>' --attr <ATTR> --value <VALUE>
$ sopa [auth_flags] attr delete --dc <DC> --dn '<DN>' --attr <ATTR>
# Create objects
$ sopa [auth_flags] create user --dc <DC> --name <CN> --pass <INITIAL_PASS>
$ sopa [auth_flags] create computer --dc <DC> --name <CN>
$ sopa [auth_flags] create group --dc <DC> --name <CN> --type GlobalSecurity
$ sopa [auth_flags] create ou --dc <DC> --name <CN>
$ sopa [auth_flags] create container --dc <DC> --name <CN>
$ sopa [auth_flags] create custom --dc <DC> --template <TEMPLATE.yaml>
# Set / change account passwords (MS-ADCAP)
$ sopa [auth_flags] set-password --dc <DC> --dn '<DN>' --new <NEW_PASS>
$ sopa [auth_flags] change-password --dc <DC> --dn '<DN>' --old <OLD_PASS> --new <NEW_PASS>
# Translate DN <-> canonical name (MS-ADCAP)
# (this call is mostly useless but kept for completeness 😄)
$ sopa [auth_flags] translate-name --dc <DC> --offered DistinguishedName --desired CanonicalName '<DN>'
# Principal group memberships (MS-ADCAP)
$ sopa [auth_flags] groups --dc <DC> --dn '<DN>' --membership --authz
# Group members (MS-ADCAP)
$ sopa [auth_flags] members --dc <DC> --dn '<GROUP_DN>' --recursive
# Toggle optional AD feature, e.g. Recycle Bin (MS-ADCAP)
$ sopa [auth_flags] optfeature --dc <DC> --feature-id <FEATURE_GUID> --enable
# Topology info (MS-ADCAP)
$ sopa [auth_flags] info version --dc <DC>
$ sopa [auth_flags] info domain --dc <DC>
$ sopa [auth_flags] info forest --dc <DC>
$ sopa [auth_flags] info dcs --dc <DC>
# ADWS service endpoint metadata (unauthenticated - auth flags not needed)
$ sopa mex --dc <DC>
サブコマンドなしでsopaを実行すると、インタラクティブシェルが起動します。単一の接続をすべてのコマンドで再利用し、タブ補完を提供します。
$ sopa --dc <DC> -u <USER> -p <PASS> -d <DOMAIN>
sopa v1.1.0
Connected dc.corp.local domain=corp.local user=Administrator
Type 'help' for commands or 'exit' to quit.
[corp.local]> query --filter '(objectClass=user)' --attrs sAMAccountName
[corp.local]> get --dn 'CN=Administrator,CN=Users,DC=corp,DC=local'
[corp.local]> exit
シェルを終了するには、exit、quit、またはCtrl-Dを使用します。
テンプレート例:examples/custom-create.example.yaml
テンプレートスキーマ (YAML):
parentDN (文字列、必須):コンテナDNrdn (文字列、必須):新しいオブジェクトの相対DN(例:CN=Foo)attributes (リスト、必須):各項目は以下を持つ:
name (文字列、必須):属性名(cn または addata:cn)type (文字列、オプション):string|int|bool|base64|hex(または明示的な xsd:*)、デフォルトは stringvalue (文字列) または values (文字列のリスト) のいずれか注意事項:
ad:relativeDistinguishedName や ad:container-hierarchy-parent をテンプレートに含めないでください(自動的に注入されます)。hex 値は xsd:base64Binary に変換されます。value: "" を使用します。--dc は FQDN、IPアドレス、または 省略 を受け付けます。
DCのホスト名はネットワークのデフォルトDNSから利用できない場合があるため、常に --dns <DC-IP> を渡して、sopaがすべてのルックアップにDC自身のDNSサーバを使用することを強く推奨します:
# Option 1: let sopa resolve everything through the DC's DNS
$ sopa query --dns 192.168.1.10 -d corp.local -u user -p pass --filter '(objectClass=user)'
--dc が省略され --domain が指定された場合、sopaはSRVレコードをクエリして自動的にDCを発見します:
_ldap._tcp.<domain> (tried first)
_kerberos._tcp.<domain> (fallback)
最も優先度の高いレコードのターゲットが使用されます。これには、--dns で指定されたDNSサーバがそれらのSRVクエリに応答できる必要があります - DC自身の統合DNSサーバ(存在する場合)はそれが可能なはずです。
# Option 2: provide DC explicitly without Kerberos
$ sopa info version --dc 192.168.1.10 --domain corp.local -u user -p pass
--dc にIPが指定された場合、そのIPは常に 逆PTRルックアップ を介してFQDNに解決されます - ADWSエンドポイントのWCFアドレスフィルタは、認証方法に関係なく wsa:To ヘッダにFQDNを必要とします。
このPTRルックアップも --dns を経由するため、DC上に正しく設定された逆引きゾーンが必要です:
# Option 3: IP input - PTR lookup resolves 192.168.1.10 -> dc.corp.local
$ sopa info version --dc 192.168.1.10 --dns 192.168.1.10 --domain corp.local -u user -p pass
スタック内のすべてのDNS操作(DC発見、PTR解決、ADWS TCPダイヤル、Kerberos KDC接続)は、--dns / --dns-tcp から構築された同じリゾルバを使用します。
sopa は以下の認証情報モードをサポートしています:
# Password
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -p <PASS> <subcommand> [...]
# NT hash
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -H <NT_HASH> <subcommand> [...]
# AES session key (Kerberos is implied)
# 32 hex chars = AES-128, 64 hex chars = AES-256
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --aes-key <HEX_KEY> <subcommand> [...]
# Kerberos ccache (Kerberos is implied)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -c <CCACHE_PATH> <subcommand> [...]
# PFX certificate (Kerberos is implied / via PKINIT)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --pfx <CERT.pfx> --pfx-password <PFX_PASS> <subcommand> [...]
# PEM certificate (Kerberos is implied / via PKINIT)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --cert <CERT.pem> --key <KEY.pem> <subcommand> [...]
すべてのTCP接続(ADWS、Kerberos、DNS)は、-x / --socks5 を介してSOCKS5プロキシ経由でトンネリングできます:
# Route everything through a SOCKS5 proxy
$ sopa -x 127.0.0.1:1080 --dc dc.corp.local -d corp.local -u user -p pass query --filter '(objectClass=user)'
# Use the DC's own DNS through the proxy, then connect via proxy
$ sopa -x 127.0.0.1:1080 --dns 192.168.1.10 --dc 192.168.1.10 -d corp.local -u user -p pass query --filter '(objectClass=user)'
# Keep DNS local (e.g. DNS already reachable without proxy), only proxy TCP connections
$ sopa -x 127.0.0.1:1080 --no-proxy-dns --dc dc.corp.local -d corp.local -u user -p pass query --filter '(objectClass=user)'
貢献は、issueを開く または プルリクエストを送信する ことで歓迎します。
このツールを書くアイデアは、主に回避目的のADWSに特化したツールの波から来ました。理論的にはこれらでできることはすべて sopa でもできますが、より複雑・具体的なアクションを実行したい場合は、それらもチェックしてください:
oiweiwei 氏に多大なる感謝を。彼の go-msrpc の ssp パッケージがGSSAPIによる認証フローをシームレスに実装してくれたためです。
MIT License (MIT)
Copyright (c) 2023 Artur Henrique Marzano Gonzaga
以下に定める条件に従い、本ソフトウェアおよび関連文書ファイル(以下「ソフトウェア」)の複製を入手するすべての人に対し、ソフトウェアを無制限に扱うことを許可します。これには、ソフトウェアの使用、複製、変更、結合、公開、配布、サブライセンス、販売の権利、およびソフトウェアを提供された者がこれらを行うことを許可する権利を含みますが、これに限定されません。
上記の著作権表示およびこの許可表示は、ソフトウェアのすべての複製または重要な部分に含まれなければなりません。
本ソフトウェアは「現状のまま」提供され、明示的か黙示的かを問わず、商品性、特定目的への適合性、および非侵害の保証を含むがこれに限らない、いかなる種類の保証もありません。いかなる場合においても、作者または著作権者は、契約行為、不法行為、またはそれ以外であろうと、本ソフトウェアに起因または関連して生じた、いかなる請求、損害、その他の責任についても責任を負わないものとします。
SetPasswordchange-password:MS-ADCAPのChangePasswordを使用してアカウントパスワードを変更(古いパスワードが必要)translate-name:TranslateNameを使用してDNと正規名の形式を変換groups:GetADPrincipalGroupMembership / GetADPrincipalAuthorizationGroupを使用してプリンシパルのグループメンバーシップまたは認証グループを一覧表示members:GetADGroupMemberを使用してグループメンバーを列挙(オプションで再帰的)optfeature:ChangeOptionalFeatureを使用してオプションのAD機能(例:ごみ箱)を切り替えinfo:GetVersion、GetADDomain、GetADForest、GetADDomainControllersを使用してトポロジメタデータ(バージョン、ドメイン、フォレスト、DCリスト)を取得mex:認証なしのWS-MetadataExchangeリクエストを使用してADWSサービスエンドポイントのメタデータを取得| フラグ | 説明 |
|---|
--dns <host[:port]> | すべてのルックアップ(SRV、PTR、前方)のカスタムDNSサーバ。デフォルトはポート53。 |
--dns-tcp | UDPの代わりにTCP経由でDNSクエリを強制。UDPがブロックされている場合やSRV応答が大きい場合に便利。 |
-x / --socks5 <host:port> | すべてのTCP接続をSOCKS5プロキシ経由でルーティング。--no-proxy-dns が設定されていない限り、DNSクエリもプロキシ経由でトンネリングされます。 |
--no-proxy-dns | --socks5 がアクティブな場合、プロキシではなくローカルシステムリゾルバを使用してDNSを解決します。 |
--dns-timeout <duration> | DNS操作のタイムアウト(デフォルト10秒)。 |
--tcp-timeout <duration> | TCPダイヤルおよびADWSプロトコル操作のタイムアウト(デフォルト30秒)。 |