December 3, 2004 at 6:12 am
I need to audit the sa login and as such I carried out the following scenario.
I logged on to my XP domain account and then go into Query Analyser as 'sa'. I have switched on Profiler but when I look at the output it tells me the Hostname but it doesn't tell me who is logged on to the host. i.e The NTUserName and NTDomainName are both blank.
Can anyone please help as we need to know who may be using the sa account surreptitiously.
December 3, 2004 at 6:19 am
change the password without telling anyone but your manager. You will find out VERY quickly.
Seriously though.. I don't know of anything INTERNAL to SQL that will manage this. Possibly IMCEDA or InDepth have this capability....
Good Hunting!
AJ Ahrens
webmaster@kritter.net
December 3, 2004 at 7:40 am
When you login as sa, thre is no NTUsername, that's when you log in using Windows authentication.
I agree with AJ, change the pwd and you'll find out, or someone will change it back
December 3, 2004 at 8:05 am
Does this mean that I can't find out who is using the sa login thru any Microsoft product? Profiler can tell me what pc is using it, isn't there anything available to interrogate that pc to see who is logged on?
This all stems from SOX. Who should have what login and privileges and what they do with these privileges including members of the DBA team.
December 3, 2004 at 9:41 am
I had a situation where i needed to cycle through active connections to any particular database and kill the connection for scheduled maintenance weekend integrity checks. I found that dbo.sysprocesses had the info on active connections. It may not be exactly what you are looking for, but here is the code I use to clean up connections to a database. It should include info on sa activity. keep in mind that dbo.sysprocesses is a very dynamic table and can change many times in a second depending on database traffic.
Good Hunting!!!
--*****************************************
-- Declare database name to check
-- integrity of. Note, All indexes
-- will be repaired. All Active
-- connections to the database
-- must be halted to perform this action.
-- DBCC CheckDB will be called in
-- the next step of this job.
--*****************************************
declare
@database varchar(250),
@tablename varchar(250),
@insert varchar(8000)
select @database = 'siebel' --Insert Database Name here
select @tablename = @database + '.dbo.sysusers'
select @insert = 'insert into #temp
select a.[spid], b.name as dbname, c.name as username, a.cmd, a.program_name as program ,a.hostname
from sysprocesses a, sysdatabases b, ' + @tablename + ' c ' + 'where a.dbid = b.dbid
and a.uid = c.uid
and b.name = ''' + @database + ''''
create table #temp(
[spid] int,
dbname varchar(250),
username varchar(250),
cmd varchar(250),
program varchar(250),
hostname varchar(250))
exec (@insert)
while (select count(*)from #temp) <> 0
begin
Declare
@spid int,
@spidtxt varchar(100),
@username varchar(250),
@hostname varchar(250),
@program varchar(250),
@cmd varchar(250),
@date varchar(50),
@dbname varchar(250),
@kill varchar(250)
select @spid = (select top 1 (spid) from #temp order by spid desc)
select @spidtxt = convert (varchar(100),@spid)
select @username = (select upper(username) from #temp where spid = @spid)
select @hostname = (select (rtrim(hostname)) from #temp where spid = @spid)
select @program = (select (upper(rtrim(program))) from #temp where spid = @spid)
select @cmd = (select (rtrim(cmd)) from #temp where spid = @spid)
select @date =
(select (convert (varchar(4),datepart (year,getdate ())) +
case when len(convert (varchar(4),datepart (month,getdate ()))) = 1
then
(select '0' + convert (varchar(4),datepart (month,getdate ())))
else
(select convert (varchar(4),datepart (month,getdate ())))
end +
case when len(convert (varchar(4),datepart (day,getdate ()))) = 1
then
(select '0' + convert (varchar(4),datepart (day,getdate ())))
else
(select convert (varchar(4),datepart (day,getdate ())))
end +
case when len(convert (varchar(4),datepart (hh,getdate ()))) = 1
then
(select '0' + convert (varchar(4),datepart (hh,getdate ())))
else
(select convert (varchar(4),datepart (hh,getdate ())))
end +
case when len(convert (varchar(4),datepart (mi,getdate ()))) = 1
then
(select '0' + convert (varchar(4),datepart (mi,getdate ())))
else
(select convert (varchar(4),datepart (mi,getdate ())))
end
 )
select @dbname = (upper(@database))
select @kill = 'kill ' + @spidtxt
Raiserror (60000,19,1,@spidtxt,@username,@hostname,@program,@cmd,@date,@dbname ) With Log
exec (@kill)
delete from #temp where spid = @spid
end
drop table #temp
Cody Pack
MCSE Windows 2000
MCDBA SQL Server 2000
December 3, 2004 at 9:58 am
If its always from the same machine, put a key-logger on it. That'd give you concrete proof.
Steve
December 6, 2004 at 7:34 am
Using the host name, can you identify where the machine is physically located? Is it a shared machine, or does it belong to one user? If you can physically visit the PC, maybe you can cross-reference the events in the Security Log in event viewer (on the host in question) with the sa login time in the SQL Server log.
I agree with the others, change the sa password immediately.
Also, I would check the built in server roles, particulary system_administrators and security_administrators, to make sure no one added a login id to those roles. If I hacked into a SQL Server with sa, I would probably create a new login and assign it to the system_administrators role so that if the sa password was later changed, I could still get in with admin rights.
December 6, 2004 at 9:57 am
You can check if any of your enterprise admins can help you figure out where the host is located ? Something we also do is we have alerts set up on successful sa logins and you can run a script which can kill the session on successfull sa login.(something i might be concerned in doing unless you have some exceptions in the script.)
December 10, 2004 at 9:42 am
This will cycle and look to see who is using SA, and what applicaiton they are using to connect with it....
/*
Security audit in SQL server captures only successful and failed logins.
It does not capture the application that uses the login. Login used by
an application may have full read and write access on all of the tables
and procedures but the application restricts the users by providing a
front-end which will allow them to see only a few columns, tables etc.
However, certain users out of curiosity may log on to the database using
SQL Query tools such as Enterprise manager and Query analyzer, using
production login information. The following process will capture such un-
authorized users who log on to the SQL server.
*/
drop procedure sp_adhocTracking
GO
create procedure sp_adhocTracking (@StartSnapID int = 1,
@Documentation char(1) = 'N',
@Clear char(1) = 'N')
with encryption
as
declare @SnapID int,
@DomainName varchar(128),
@TimeStamp datetime,
@count int,
@message varchar(1000)
create table #tmp
(ServerRole sysname, MemberName sysname, MemberID varbinary(4000))
insert into #tmp exec sp_helpsrvrolemember 'sysadmin'
if SYSTEM_USER not in (select MemberName from #tmp)
begin
RAISERROR('YOU MUST BE LOGGED IN AS A SYSTEM ADMIN TO EXECUTE THIS PROCEDURE!!! ABORTING!!!', 16, 1)
RETURN
end
DROP TABLE #TMP
if @Clear = 'Y'
begin
truncate table master.[dbo].[AUDIT_TRACE]
RETURN
end
if @Documentation = 'Y'
begin
PRINT 'This procedure will log information on who was using unauthorized software against ' +
CHAR(13) + 'a given database server. The parameters are as follows: ' + CHAR(13) + CHAR(9) +
'@StartSnapID int - This parameter will report back to you all information from a given snapshot' +
CHAR(13) + CHAR(9) +
'@Clear char(1) - ''Y'' or ''N'' - Clear the AUDIT_TRACE table.' + CHAR(13) + CHAR(9) +
'@Documentation char(1) ''Y'' or ''N'' - Display this text.' + REPLICATE(CHAR(13), 2) +
'This procedure must be run as SA, and be aware that each time you run this, if you do not specify' +
CHAR(13) + 'a StartSnapID, then each recorded instance of unauthorized activity will be logged to SQL Server' +
CHAR(13) + 'error log, and the NT Event Log. If you set this up as a job, then it will also record it to the ' +
CHAR(13) + 'job history log.' + REPLICATE(CHAR(13), 2) + REPLICATE(CHAR(9), 2) +
'Email me with any questions at: Jake@Freedomproject.net'
RETURN
end
if NOT exists (select *
from master.dbo.sysobjects
where id = object_id(N'[dbo].[AUDIT_TRACE]')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
begin
raiserror('AUDIT_TRACE table does not exist. Now creating...', 16, 1)
create table master.[dbo].[AUDIT_TRACE]
( PK int IDENTITY(1,1) NOT NULL ,
TRACE_ID int NOT NULL ,
DATABASE_NAME varchar(128) NOT NULL ,
SPID varchar(455) NOT NULL ,
LOGIN_NAME varchar(128) NOT NULL ,
PROGRAM_NAME varchar(455) NOT NULL ,
HOSTNAME varchar(128) NULL,
HOSTUSERNAME varchar(128) NULL ,
LOGIN_TIME datetime NULL ,
TIME_STAMP datetime NOT NULL
)
set @SnapID = 1
end
else
begin
select @SnapID = max(TRACE_ID) + 1 from master.dbo.AUDIT_TRACE group by TRACE_ID
if @SnapID <= 0 set @SnapID = 1
end
INSERT INTO master.[dbo].[AUDIT_TRACE]
select @SnapID,
a.name ,
ltrim(rtrim(convert(varchar,b.spid))) ,
ltrim(rtrim(b.loginame)) ,
ltrim(rtrim(b.program_name)) ,
ltrim(rtrim(b.hostname)) ,
nt_username ,
b.login_time,
getdate()
from master.dbo.sysprocesses b (nolock) ,
master.dbo.sysdatabases A
where a.dbid = b.dbid
and ltrim(rtrim(b.loginame)) = 'sa'
-- and ltrim(rtrim(left(program_name,8))) in ('MS SQLEM', 'SQL Quer')
select *
from master.[dbo].[AUDIT_TRACE]
where TRACE_ID BETWEEN @StartSnapID
AND @SnapID
set @count = (select count(*)
from master.[dbo].[AUDIT_TRACE]
where TRACE_ID BETWEEN @StartSnapID
AND @SnapID)
While @count >=1
begin
set @message = (
select 'SQL Security Enhanced Auditing: ' + CHAR(13) +
'SPID =' + SPID + CHAR(13) +
'Database: ' + DATABASE_NAME + CHAR(13) +
'Loginame: ' + LOGIN_NAME + CHAR(13) +
'hostname: ' + HOSTNAME + CHAR(13) +
'Host Username: ' + HOSTUSERNAME + CHAR(13) +
'Program Name: ' + PROGRAM_NAME + CHAR(13) +
'Login Time: ' + CAST(LOGIN_TIME as varchar)
from master.dbo.AUDIT_TRACE where PK = @count)
set @count = @count-1
RAISERROR (@message, 16, 1) with log
end
GO
December 10, 2004 at 2:58 pm
We know the Host Name (computer name) from sysprocesses. I wonder could we use WMI class Win32_LoggedOnUser to get this info. The problem is that the person running a script has to have domain admin rights to get WMI counters from another computer or admin rights on that computer.
I am not suggesting to run SQL Server on the Domain Admin. I think if it is only for Audit purposes, you may store results from Sysprocesses in some table like Audit_Trace suggested by Sim30305 and create a trigger that runs a job that will be executed with Domain Admin credentials to run a VBscript that will use WMI , return LoggedOn user from the other computer and update the table with his name.
Yelena
Regards,Yelena Varsha
December 10, 2004 at 3:48 pm
Just tested this Win32_LoggedOnUser thing. Works well, shows me ALL sessions, not only interactive logon, but again, how you may be sure those people are using SA login from the computer interactively? It could be a terminal Services session, script job running or whatever. This is the part of the code. strComputer is a remote Computer Name, HostName from Sysprocesses for example, FileObject was defined outside of this part of code as a FileSystemObject text File
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
'Getting Logged On User
Set colCurrentUser = objWMIService.ExecQuery _
("Select * from Win32_LoggedOnUser")
For Each objUser in colCurrentUser
LoggedUser = objUser.Antecedent
FileObject.WriteLine "Logged On User " & LoggedUser & NewLine
Next
Yelena
Regards,Yelena Varsha
Viewing 11 posts - 1 through 10 (of 10 total)
You must be logged in to reply to this topic. Login to reply