Kaspersky Security Center — the fight for automation

oddly enough, I found habré only one article on the subject — the sandbox much unfinished actually contains a piece of the slightly redesigned the product help. Yes, and Google query klakaut silent.

I'm not going to tell you how to administer the hierarchy of Kaspersky Security Center (hereinafter KSC) from the command line — I do not yet need never. Just want to share some thoughts about automation tools to those who need it and disassemble one case with which I had to face. If you, %habrauser%, this topic will be interesting — welcome under kat.

Historically, the anti-virus protection on the job, I prefer products of Kaspersky Lab (hereafter LK). Causes and other Holy war of personal opinions, I'll leave behind the scenes.

Naturally, I would like to centrally deploy, protect, to protect and to enforce the law to draw beautiful graphics to integrate into existing monitoring systems and to do other work shifting the blame to a healthy server. And if you deploy and protect everything more or less in order (at LC, even there are some online courses product), then the integration is already much sadder: in the latest version KSC 10.2.434 there was integration as much with two SIEM: Arcsight and Qradar. That's all.

For integration into something of their own already KSC provides 2 interfaces:

the
    the
  • klakdb: in the database, KSC has a number of views with names beginning with "v_akpub_" from which you can get some information about the antivirus status.
  • the
  • klakaut: the DCOM object that is used to scriptout work with KSC.

On both counts, there is documentation included with KSC, as indicated in the articles that I gave links to. However, this documentation raises a number of questions that you can ask support enterprise products CompanyAccount and get an answer of the kind "Said. Unfortunately, support for scripts is not klakaut.".

Cons klakdb obvious: to directly access the database, you need to have this database access that leads to the need for much fuss to create access rules in firewalls, configure access rights on servers, databases and other very unexciting pastime. Well, plus monitoring the relevance of all these rules, of course. Particularly interesting it becomes when you have 20+ servers all in different branches, each with its own administrators.

Well, the cherry on the cake: Read Only access exclusively and, to put it mildly, incomplete information about the environment. The advantages are not so obvious, but also have: you can easily upload one to the server statistical information on the number of hosts used versions of anti-virus and anti-virus databases, and most importantly — very convenient (convenience depends on knowledge of SQL) to work with the KSC was on the events of the antivirus infrastructure.

klakaut in this plan is much more interesting: by connecting to the root server of the hierarchy, it is possible by means of KSC go through this hierarchy and get access to all the required data. For example, to build the server tree KSC marked who of them is alive and who is not, to pasupuleti tasks, papermaster computers and generally unleash the imagination.

Disadvantages too, of course: long and difficult. If you need to collect some statistics — will need a long time to write the script, and then long to catch bugs wait, when it will work.

Of course, nobody forbids (at least, me about it is unknown) to use both mechanisms together: for example, walk the hierarchy of servers using klakaut get the full list of servers KSC with information about the used database, and then transmit this information to the more than other automation tools, which will delete obsolete rules from firewalls, create new, will give access permissions and will bring coffee in bed edit the list of data sources in the monitoring system, which, in turn, will interrogate the list and finding any deviation, with klakaut do something good. Well, or just register the incident in the tracker. Then something good will make administrators in manual mode.
Inspired by all these considerations, I wrote my first script:

Here it is
$Params = New-Object -ComObject 'klakaut.KlAkParams';
$Params.Add('Address', 'localhost:13000');
$Params.Add('UseSSL', $true);

$Proxy = New-Object -ComObject 'klakaut.KlAkProxy';
try {
$Proxy.Connect($Params);
$Proxy.Disconnect();
} catch {
$_;
}

Remove-Variable -Name 'Params';
Remove-Variable -Name 'Proxy';


And launched it on the server:

Exception calling "Connect" with "1" argument(s): "Transport level error while connecting to http://localhost:13000: authentication failure"
At line:7 char:5
+ $Proxy.Connect($Params);
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation

That's a good start.

for the record
If you use js, this error does not occur. I wonder why.

Open the KSC console, I was convinced that with the rights I have everything in order.

Unfortunately, KSC is not logging failed login attempts. Correspondence with the vendor showed that the logging of failed login attempts, you can enable (it was a fascinating story, which, incidentally, has not yet ended), but this particular attempt in the logs still get refused.

It would seem that you can do like this:

Incorrect script
$Params = New-Object -ComObject 'klakaut.KlAkParams';
$Params.Add('Address', 'localhost:13000');
$Params.Add('UseSSL', $true);

#------------ Ask explicitly login --------------------------------
$Params.Add('User', 'kavadmin');
$Params.Add('Password', 'P@ssw0rd');
$Params.Add('Domain', 'test');
#-----------------------------------------------------------------------------------

$Proxy = New-Object -ComObject 'klakaut.KlAkProxy';
try {
$Proxy.Connect($Params);
$Proxy.Disconnect();
}

Remove-Variable -Name 'Params';
Remove-Variable -Name 'Proxy';


In this case, no errors will be made, but to specify the username and password in clear text in the script did not seem a great idea. New correspondence with tech support LK gave me the following recommendation:

you Need to set the COM settings tab of the Default Properties:
Default Authentication Level: Packet
Default Impersonation Level: Delegate

This statement forced to work the original script, but struck me as questionable in terms of safety, so I decided to dig a little deeper. After some time searching and found a kind man who told me how to specify these authentication levels and impersonation for a specific object, and not to allow all and everything:

the Right script
$Params = New-Object -ComObject 'klakaut.KlAkParams';
$Params.Add('Address', 'localhost:13000');
$Params.Add('UseSSL', $true);

$Proxy = New-Object -ComObject 'klakaut.KlAkProxy';

$code = @"
using System;
using System.Runtime.InteropServices;

public class PowershellComSecurity
{
[DllImport("Ole32.dll", CharSet = CharSet.Auto)]
public static extern int CoSetProxyBlanket(IntPtr p0, uint p1, uint p2, uint p3, uint, p4, uint, p5, p6 IntPtr, uint, p7);

public static int EnableImpersonation(object objDCOM) { return CoSetProxyBlanket(Marshal.GetIDispatchForObject(objDCOM), 10, 0, 0, 0, 3, IntPtr.Zero, 0); }
}
"@
Add-Type -TypeDefinition $code;
Remove-Variable -Name 'code';

[PowershellComSecurity]::EnableImpersonation($Proxy) | Out-Null;

try {
$Proxy.Connect($Params);
# <-- Here we insert the code
$Proxy.Disconnect();
} catch {
$_;
}

Remove-Variable -Name 'Params';
Remove-Variable -Name 'Proxy';


So the script are no errors to give did not become. The first quest is completed.

for the record
Generally, in a production environment would be nice to check when you call EnableImpersonation the return value for errors, not redirect it to nowhere, as I did.

Next task: get from the KSC data about your database.

But it's complicated: the documentation on how to do it, silent. Study class KlAkProxy nothing is revealed, except for parameter KLADMSRV_SERVER_HOSTNAME, which was the ID of the computer on which you installed KSC.

Let's move on then to the computer, there is a special class KlAkHosts2. To reduce the amount of code will cause only the contents of the try block:

try
try {
$Proxy.Connect($Params);
$KSCHost = New-Object -ComObject 'klakaut.KlAkHosts2';
$KSCHost.AdmServer = $Proxy;
$HostParams = New-Object -ComObject 'klakaut.KlAkCollection';
$HostParams.SetSize(1);
$HostParams.SetAt(0, 'KLHST_WKS_DN');
($KSCHost.GetHostInfo($Proxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), $HostParams)).Item('KLHST_WKS_DN');

Remove-Variable -Name 'KSCHost';
$Proxy.Disconnect();
}


Note: the variable $Params that I used when connecting to the KSC — class instance KlAkParams. And the variable $HostParams when, in my opinion, is similar to the functionality is an instance of the class KlAkCollection. Why use different classes — I can't even imagine. Apparently, the fact that SetAt first argument accepts only an integer value is a very important point.

This code returned: "KSC", which means I'm on the right track.

Method GetHostInfo class KlAkHosts2 fairly well documented, but does not contain useful information. Alas. But there is a method GetHostSettings. Full description for which is as follows:

Returns host's settings as setting storage.

Let's take a look inside:

try
try {
$Proxy.Connect($Params);
$KSCHost = New-Object -ComObject 'klakaut.KlAkHosts2';
$KSCHost.AdmServer = $Proxy;
$KSCSettings = $KSCHost.GetHostSettings($Proxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), 'SS_SETTINGS');
$KSCSettings.Enum() | % {
'------------------------';
$tmp = $_;
$tmp| % {"$_ = $($tmp.Item($_))";};
Remove-Variable -Name 'tmp';
};
Remove-Variable -Name 'KSCSettings';
Remove-Variable -Name 'KSCHost';
$Proxy.Disconnect();
}


Result
------------------------
PRODUCT = .core
SECTION = SubscriptionData
VERSION = .independent
------------------------
PRODUCT = 1093
SECTION = 85
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = 87
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLEVP_NF_SECTION
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLNAG_SECTION_DPNS
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_CONSRVINIT
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_CONSRVUPGRADE
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_DEF_NAGENT_PACKAGE
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_MASTER_SRV
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_NETSIZE_SECTION
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_PKG_ANDROID_CERT_SECTION
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_PROXY_SECTION
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_SRVLIC_SECTION
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KLSRV_USER_ACCOUNTS_SECTION
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KSNPROXY_KEY_STORAGE
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = KSNPROXY_SETTINGS
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = Packages
VERSION = 1.0.0.0
------------------------
PRODUCT = 1093
SECTION = Updater
VERSION = 1.0.0.0
------------------------
PRODUCT = 1103
SECTION = 85
VERSION = 1.0.0.0
------------------------
PRODUCT = 1103
SECTION = 86
VERSION = 1.0.0.0
------------------------
PRODUCT = 1103
SECTION = FileTransfer
VERSION = 1.0.0.0
------------------------
PRODUCT = 1103
SECTION = KLEVP_NF_SECTION
VERSION = 1.0.0.0
------------------------
PRODUCT = 1103
SECTION = KLNAG_KLNLA_DATA
VERSION = 1.0.0.0
------------------------
PRODUCT = 1103
SECTION = KLNAG_SECTION_NETSCAN
VERSION = 1.0.0.0
------------------------
PRODUCT = 1103
SECTION = KLNAG_SECTION_SERVERDATA
VERSION = 1.0.0.0
------------------------
PRODUCT = 1103
SECTION = Updater
VERSION = 1.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = .KLNAG_SECTION_REBOOT_REQUEST
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = 85
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = Backup section
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = Business logic section
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = HSM system section
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = Internal product info
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = KLEVP_NF_SECTION
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = Notification section
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = Predefined tasks section
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = Quarantine section
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = section Reporting
VERSION = 8.0.0.0
------------------------
PRODUCT = KAVFSEE
SECTION = Trusted processes section
VERSION = 8.0.0.0


In klakaut.chm has a section "List of KLHST_WKS_PRODUCT_NAME and KLHST_WKS_PRODUCT_VERSION values for products", where you can catch a glimpse of what the PRODUCT for KSC should be 1093, respectively, all the rest can safely ignore it. So far, at least.

Running your eyes along the names of the sections, I decided to see 85 and 87, because the other on my right was not very similar.

try
try {
$Proxy.Connect($Params);
$KSCHost = New-Object -ComObject 'klakaut.KlAkHosts2';
$KSCHost.AdmServer = $Proxy;
$KSCSettings = $KSCHost.GetHostSettings($Proxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), 'SS_SETTINGS');
$KSCSettings.Read('1093', '1.0.0.0', '85');
'-----------------';
$KSCSettings.Read('1093', '1.0.0.0', '87');
Remove-Variable -Name 'KSCSettings';
Remove-Variable -Name 'KSCHost';
$Proxy.Disconnect();
}


Result
EventFolder
EventStoragePath
KLAG_WAIT_SCHED_FOR_START_EVENT
TaskStoragePath
-----------------
KLSRV_AD_SCAN_ENABLED
KLSRV_CONNECTION_DATA
KLSRV_DATABASENAME
KLSRV_NET_SCAN_ENABLED
KLSRV_SERVERINSTANCENAME

KLSRV_SP_FASTUPDATENET_PERIOD
KLSRV_SP_FULLUPDATENET_PERIOD
KLSRV_SP_INSTANCE_ID
KLSRV_SP_MAX_EVENTS_IN_DB
KLSRV_SP_OPEN_AKLWNGT_PORT
KLSRV_SP_SCAN_AD
KLSRV_SP_SERVERID
KLSRV_SP_SERVERID_DPE
KLSRV_SP_SERVER_AKLWNGT_PORTS_ARRAY
KLSRV_SP_SERVER_PORTS_ARRAY
KLSRV_SP_SERVER_SSL_PORTS_ARRAY
KLSRV_SP_SERVER_SSL_PORTS_ARRAY_GUI
KLSRV_SP_SYNC_LIFETIME
KLSRV_SP_SYNC_LOCKTIME
KLSRV_SP_SYNC_SEC_PACKET_SIZE
KLSRV_SSL_CERT_RSA_BIT_NUMBER


Section 85, apparently, responsible for the events and now we are not interested. But in 87 there's something you should pay attention:

try
try {
$Proxy.Connect($Params);
$KSCHost = New-Object -ComObject 'klakaut.KlAkHosts2';
$KSCHost.AdmServer = $Proxy;
$KSCSettings = $KSCHost.GetHostSettings($Proxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), 'SS_SETTINGS');
$87 = $KSCSettings.Read('1093', '1.0.0.0', '87');
"KLSRV_SERVERINSTANCENAME = $($87.Item('KLSRV_SERVERINSTANCENAME'))";
"KLSRV_DATABASENAME = $($87.Item('KLSRV_DATABASENAME'))";
"KLSRV_CONNECTION_DATA =`R'n$($87.Item('KLSRV_CONNECTION_DATA') | % {"`t$_ = $($87.Item('KLSRV_CONNECTION_DATA').Item($_))`R'n";})";
Remove-Variable -Name '87';
Remove-Variable -Name 'KSCSettings';
Remove-Variable -Name 'KSCHost';
$Proxy.Disconnect();
}


Result
KLSRV_SERVERINSTANCENAME = .
KLSRV_DATABASENAME = KAV
KLSRV_CONNECTION_DATA =
KLDBCON_DB = KAV
KLDBCON_DBTYPE = MSSQLSRV
KLDBCON_HOST = .


Here I have used one of the previous cases where it was mentioned that the required data should take it from KLSRV_CONNECTION_DATA (little did I know that it's all about, just postponed).

Well, here are, in General, that's all. Data used the database obtained. The quest is passed.

Probably still a good idea to jot down the script for the passage of the hierarchy of servers. There is nothing mysterious not any quite documentation. I wrote a script which picks out the UID of a parent, UID the server itself, the database instance, and database name and displays them to stdout using a separator.

Script
$SrvAddr = 'localhost:13291'

function EnumSrv(
$Pxy,
[bool]$IsAlive = $true,
[string]$ParentPxyId = 'Root'
)
{
[string]$result = "$ParentPxyId";
if ($IsAlive) {
$result += "|$($Pxy.GetProp('KLADMSRV_SERVER_HOSTNAME'))";

$Hosts = New-Object -ComObject 'klakaut.KlAkHosts2';
$Hosts.AdmServer = $Pxy;

$Settings = $Hosts.GetHostSettings($Pxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), 'SS_SETTINGS').Read('1093', '1.0.0.0', '87').Item('KLSRV_CONNECTION_DATA');
Remove-Variable -Name 'Hosts';

#'--------> DB Info <--------';
$result += "|$($Settings.Item('KLDBCON_HOST'))";
$result += "|$($Settings.Item('KLDBCON_DB'))";
#'-----------------------------';

Remove-Variable -Name 'Settings';

$SlaveSrvEnum = New-Object -ComObject 'klakaut.KlAkSlaveServers';
$SlaveSrvEnum.AdmServer = $Pxy;
$SlaveServers = $SlaveSrvEnum.GetServers(-1);

$SlaveServers | % {
$Child = $_;
$TmpSrvId = $Child.Item('KLSRVH_SRV_ID');
$HostActive = $true;
try
{
$TmpSrv = $SlaveSrvEnum.Connect($TmpSrvId, -1);
}
catch
{
$HostActive = $false;
};
if ($HostActive) {$HostActive = ($TmpSrv.GetProp('IsAlive') -eq 1);};
$result += "`R'n$(EnumSrv -Pxy $TmpSrv -IsAlive $HostActive -ParentPxyId $Pxy.GetProp('KLADMSRV_SERVER_HOSTNAME'))";
};
Remove-Variable -Name 'SlaveServers';
Remove-Variable -Name 'SlaveSrvEnum';
};
return ("$result'R n");
}

Clear-Host

$Params = New-Object -ComObject 'klakaut.KlAkParams'
$Params.Add('Address', $SrvAddr)
$Params.Add('UseSSL', $true)

$code = @"
using System;
using System.Runtime.InteropServices;

public class PowershellComSecurity
{
[DllImport("Ole32.dll", CharSet = CharSet.Auto)]
public static extern int CoSetProxyBlanket(IntPtr p0, uint p1, uint p2, uint p3, uint, p4, uint, p5, p6 IntPtr, uint, p7);

public static int EnableImpersonation(object objDCOM) { return CoSetProxyBlanket(Marshal.GetIDispatchForObject(objDCOM), 10, 0, 0, 0, 3, IntPtr.Zero, 0); }
}
"@
Add-Type -TypeDefinition $code

$Srv = New-Object -ComObject 'klakaut.KlAkProxy'
[PowershellComSecurity]::EnableImpersonation($Srv) | Out-Null
$Srv.Connect($Params)

"ParentPxyId|KLADMSRV_SERVER_HOSTNAME|KLDBCON_HOST|KLDBCON_DB'R'n" + (EnumSrv -Pxy $Srv);
Remove-Variable -Name 'Srv';
Remove-Variable -Name 'Params';


Stand small, so the result was not very impressive:

Result
ParentPxyId|KLADMSRV_SERVER_HOSTNAME|KLDBCON_HOST|KLDBCON_DB
Root|9d476a75-1e36-4c0e-8145-56e5b888df67|.|KAV
9d476a75-1e36-4c0e-8145-56e5b888df67|ef4fc3be-3abd-4322-ae35-2c50afdce780|.\KAV_CS_ADMIN_KIT|KAV


Of course to turn point to the actual name of the server will have to work some magic with KlAkHosts2.GetHostInfo(), but it is not so scary, just some code.

Tech support LK, naturally, scared me because the structure SS_SETTINGS in next releases of KSC may change, so it is better not to do. Unfortunately, even my inner perfectionist believes that the script can't just write and forget: when you change the version used BY him in any need to test and debug. So long as you use what you have, and the problems will solve in process of receipt, the benefit, the technique is perfected.
Article based on information from habrahabr.ru

Популярные сообщения из этого блога

Approval of WSUS updates: import, export, copy

The Hilbert curve vs. Z-order