同様に、クエリを実行してユーザーのリモートIPアドレスを取得することは可能で、その方法は次のとおりです。SUSER_SNAME()
?
バウンティの前に更新
データベース所有者ではなく、一般の一般ユーザーのIPアドレスを取得できるソリューションを探しています。 TheGameiswarまたはnjcによって提案されたアイデアでは、execute
権限のみが付与されているユーザーのIPアドレスを取得することはできません。しかし、それらは問題から始めるための優れたアイデアです。ここに私はアイデアの本質をリストします:
私が従うシーケンスを見てください:
create procedure MyStoredProcedure as
select client_net_address
from sys.dm_exec_connections
where session_id = @@SPID
次に、ユーザーを追加して権限を付与します。
CREATE LOGIN [user_mortal_jack] WITH PASSWORD=N'LongYouLive!!!';
GRANT EXECUTE ON MyStoredProcedure TO [user_mortal_jack];
クエリでプロシージャを実行すると:
EXECUTE AS USER = 'user_mortal_jack'
exec MyStoredProcedure
REVERT
エラーメッセージが表示されます。
実行中のモジュールは信頼されていません。モジュールのデータベースの所有者に認証権限を付与するか、モジュールにデジタル署名する必要があります。
追加の許可を与えても、このメッセージが表示されます。
grant VIEW SERVER STATE to [user_mortal_jack];
ストアドプロシージャの先頭を次のように変更した場合:
create procedure MyStoredProcedure
with execute as OWNER as
私はさまざまな種類のエラーに終わります:
Windows NTグループ/ユーザー 'blahblah\admin_user'に関する情報を取得できませんでした。エラーコード0x534。
バウンティ後に更新
賞金は、回答に隠された次の1行のコードに対してハディに付与されます。
CONNECTIONPROPERTY('client_net_address')
これにより、ユーザーに追加の権限を付与したり、データベースのTRUSTWORTHY ONオプションを設定したり、プロシージャを作成したりすることなく、一般ユーザーのIPアドレスを取得できますWITH EXECUTE AS OWNER
句。
現在の接続情報を取得するには2つの方法があります
SELECT
conn.session_ID as SPID,
conn.client_net_address as IPAddress,
sess.Host_name as MachineName,
sess.program_name as ApplicationName,
login_name as LoginName
FROM sys.dm_exec_connections conn
inner join sys.dm_exec_sessions sess
on conn.session_ID=sess.session_ID
[〜#〜] connectionproperty [〜#〜] 関数の使用(SQL Server 2008以降のバージョン):
select
CONNECTIONPROPERTY('net_transport') AS net_transport,
CONNECTIONPROPERTY('protocol_type') AS protocol_type,
CONNECTIONPROPERTY('auth_scheme') AS auth_scheme,
CONNECTIONPROPERTY('local_net_address') AS local_net_address,
CONNECTIONPROPERTY('local_tcp_port') AS local_tcp_port,
CONNECTIONPROPERTY('client_net_address') AS client_net_address
ユーザーに特定のIPアドレスを付与する場合
CREATE PROCEDURE MyStoredProcedure AS
BEGIN
DECLARE @IP_Address varchar(255);
SELECT @IP_Address = CAST(CONNECTIONPROPERTY('client_net_address') as varchar(200))
IF @IP_Address = 'XXX.XXX.XXX.XXX'
SELECT TOP 1 FROM tb
END
許可されたIPアドレスを含むテーブルがあると仮定します(つまり、TBL_IP
)
CREATE PROCEDURE MyStoredProcedure AS BEGIN DECLARE @IP_Address varchar(255);
SELECT @IP_Address = CAST(CONNECTIONPROPERTY('client_net_address') as varchar(200))
IF EXISTS (SELECT 1 FROM TBL_IP WHERE [IP] = @IP_Address )
SELECT TOP 1 FROM tb
終わり
ストアドプロシージャを実行するユーザー(データベースユーザー)を許可する場合は、このコマンドを使用する必要があります
MyStoredProcedureの実行をユーザーに許可します。
あなたが直面している問題について話している多くの詳細な記事と回答、そしてTRUSTWORTHY
モードでのデータベースの設定(使用する前に以下の最初のリンクを読んでください)やオーセンティケーターの信頼、およびその他の方法。あなたは以下のリンクでそれらを見つけることができます
注:TRUSTWORTHY
property を使用して@SteveFordの回答を確認できます
特定のIPアドレス以外の接続をブロックする場合は、この回答に従う必要があります
また、以下の質問で見つけることができるクライアントまたはサーバーのIPアドレスを取得するために使用できる多くのスクリプトがあります:
参照
EXECUTE AS OWNER
ステートメントでCREATE PROCEDURE
ステートメントを使用する:
From[〜#〜] msdn [〜#〜]
CALLER以外のコンテキストで実行するように指定されたモジュールをユーザーが実行すると、モジュールを実行するユーザーの権限がチェックされますが、モジュールによってアクセスされるオブジェクトに対する追加の権限チェックは、 EXECUTE AS句。モジュールを実行しているユーザーは、事実上、指定されたユーザーになりすましています。
モジュールのEXECUTE AS句で指定されたコンテキストは、モジュールの実行中のみ有効です。モジュールの実行が完了すると、コンテキストは呼び出し元に戻ります。
以下は、DMVをクエリする権限を持つユーザーが作成する必要があります
CREATE PROCEDURE MyStoredProcedure
WITH EXECUTE AS OWNER
AS
BEGIN
SET NOCOUNT ON
SELECT TOP 1
FROM tb
INNER JOIN sys.dm_exec_connections cn
ON tb.client_net_address = cn.client_net_address
WHERE cn.Session_Id = @@SPID
END
次に、ストアドプロシージャを実行するためのアクセス許可をユーザーに与える必要があります。
適切な権限を作成するための更新
データベースを信頼できるように設定する必要があります( データベースを信頼できるように設定する を参照):
ALTER DATABASE MyDataBase SET TRUSTWORTHY ON
CREATE LOGIN [user_mortal_jack] WITH PASSWORD=N'LongYouLive!!!';
CREATE USER [user_mortal_jack] FOR LOGIN [user_mortal_jack] WITH DEFAULT_SCHEMA=[dbo]
GO
GRANT EXECUTE ON MyStoredProcedure TO [user_mortal_jack];
私はこれをテストしましたが、これは期待通りに機能します
接続DMVを使用してそれを実現できます。
select ec.client_net_address,* from sys.dm_exec_connections ec
join
sys.dm_exec_requests rq
on rq.connection_id=ec.connection_id
cross apply
sys.dm_exec_sql_text(rq.sql_handle) txt
where txt.text like '%your stored proc%'
MSDN for client_net_address
このサーバーに接続しているクライアントのホストアドレス。 null可能です。
呼び出し元のIPアドレスとユーザー名のすべてに特別な権限を付与せずに取得するには、cheatサーバーとデータベースを少し変更します。これを実現するには、いくつかのことが必要です。
ALTER DATABASE MyDataBase SET TRUSTWORTHY ON
_[user_mortal_jack]
_ではありません)_[user_immortan_joe]
_[user_immortan_joe]
_のユーザーを作成するmaster
_grant VIEW SERVER STATE to [user_immortan_joe];
_のコンテキストでMyDataBase
で、特定の_get_ip
_パラメータを表すintを受け取っているストアドプロシージャ(MyStoredProcedure
ではなく、例では_session_id
_)を作成しますoutput
(出力ではなく)IPアドレスまたはその_session_id
_。それを_with execute as 'user_immortan_joe'
_で作成します。get_ip
_およびSUSER_SNAME()
を使用して、呼び出し元のIPアドレスとユーザー名を返すように作成します。このようにして、最小限の特権の原則を尊重し、解決策の追求中に遭遇した問題を回避するMyStoredProcedure
の呼び出し元のIPアドレスとユーザー名を取得します。
サンプルスクリプト:
_use MyDataBase
go
alter database MyDataBase set trustworthy on;
go
CREATE LOGIN [user_mortal_jack] WITH PASSWORD=N'LongYouLive!!!';
go
create user [user_mortal_jack];
go
CREATE LOGIN [user_immortan_joe] WITH PASSWORD=N'ToTheGatesOfValhalla!!!';
go
create user [user_immortan_joe];
go
use master
go
grant VIEW SERVER STATE to [user_immortan_joe];
use MyDataBase
go
create PROCEDURE get_ip
@spid int, @ip varchar(50) output
with execute as 'user_immortan_joe'
as
begin
select @ip = client_net_address
from sys.dm_exec_connections
where session_id = @spid
end;
go
create procedure MyStoredProcedure
as
begin
declare @spid int = @@spid, @ip varchar(50);
exec dbo.get_ip @spid,@ip output;
select @ip as ipAddress ,SUSER_SNAME() as userName
end
go
GRANT EXECUTE ON MyStoredProcedure TO [user_mortal_jack];
go
EXECUTE AS USER = 'user_mortal_jack'
exec MyStoredProcedure
REVERT
_