我们有一个delphi应用程序,它使用tadoconnection连接sql server数据库 问题是当我们在运行exe文件时打开资源黑客时,它会清楚地显示连接字符串,并且任何人都可以连接到我们的服务器
答案 0 :(得分:5)
您没有使用资源黑客。如果您的字符串存储在资源中,它们将更容易查找和查看。
您正在使用内存扫描程序,它在程序运行时查看程序的原始内存。最终,您必须在内存中创建一个连接字符串以传递给数据库引擎。如果黑客可以访问应用程序及其内存,则可以使用应用程序访问其数据。具有此类访问权限的专用黑客将能够在使用该字符串时获取该字符串。
但是你可以采取一些措施让随意黑客更加努力。
首先,不要让非管理员用户有权访问您的应用。当用户运行扫描程序应用程序时,它可能会访问由同一用户运行的其他应用程序中的内存。在不同的用户上下文或升级过程中运行您的应用。用户运行的应用程序无法访问其他用户正在运行的其他应用程序的内存,除非明确授予他们权限,或者他/她是管理员。如果黑客有权访问您的应用,则所有投注均已关闭。
此外,将字符串分解为必要时必须连接的较小子字符串。动态构建连接字符串。这样,如果黑客试图在磁盘上查看EXE文件,那么子串就不会存储在一个地方。
无论如何,不会将敏感凭据存储在应用代码中以开始。将它们存储在外部,并保持加密。仅在绝对需要时将它们检索到内存中,并在使用完{Q 3}后使用SecureZeroMemory()
安全地销毁该内存的内容。如果您需要在内存中保留凭据或连接字符串超过几毫秒,请考虑在不使用它时使用CryptProtectMemory()
加密该内存。
将连接字符串拼凑起来所花费的工作越多,休闲黑客也必须做的工作越多。但是一个专职的黑客只会等到你完成所有的工作,然后在使用它的时候从内存中拔出最后的字符串,所以你必须尽你所能来防止首先访问内存。
答案 1 :(得分:4)
'Persist Security Info=False'
Connection.
LoginPrompt设为True
。Connection.Open
来电的密码。*有很多简单的加密库可供您加密密码。微软的Data Protection API值得考虑。请记住,如果有人可以访问您的应用程序,则无法实现完美的安全性。您可以做的最好的事情是添加混淆层,使黑客更难破解您的数据库登录凭据。
一些示例代码
procedure TAbc.HandleOnLogin(Sender: TObject; Username, Password: string);
var
LPassword: string;
begin
LPassword := GetDecryptedPassword; //Your choice how you do this
Connection.Open(Username, LPassword);
//The next line ensures memory is erased before it is deallocated
//which would otherwise leave the password hanging around.
SecureZeroMemory(Pointer(LPassword), Length(LPassword) * SizeOf(Char));
end;
答案 2 :(得分:0)
除了其他答案之外,您可以执行的操作是删除读取进程内存的权限,如果您控制用户权限(例如在企业环境中),这将非常有用。
在流程开始时调用以下过程可防止非管理员用户读取进程内存。 (您将需要JEDI API单元来丢失API调用)
uses JwaWinNT, JwaWinBase, JwaAclApi, JwaAccCtrl;
//...
{$SCOPEDENUMS ON}
function ProtectProcess(): DWORD;
type
TSidType = (Everyone, CurrentUser, System, Admin);
var
// Released on exit
ProcessToken: THandle;
TokenInfo: PVOID;
SidCurUser: PSID;
SidEveryone: PSID;
SidSystem: PSID;
SidAdmins: PSID;
ACL: PACL;
SecDesc: PSECURITY_DESCRIPTOR;
Size: DWORD;
TokenSize: DWORD;
BResult: Bool;
SIDAuthEveryone: SID_IDENTIFIER_AUTHORITY;
SIDAuthSystem: SID_IDENTIFIER_AUTHORITY;
SIDAuthAdministrators: SID_IDENTIFIER_AUTHORITY;
SIDArray: array[TSidType] of PSID;
I: TSidType;
const
// Mimic Protected Process
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880%28v=vs.85%29.aspx
// Protected processes allow PROCESS_TERMINATE, which is
// probably not appropriate for high integrity software.
DeniedPermissions =
{READ_CONTROL |}
WRITE_DAC or WRITE_OWNER or
PROCESS_CREATE_PROCESS or PROCESS_CREATE_THREAD or
// PROCESS_DUP_HANDLE or // this permission is needed for printing
PROCESS_QUERY_INFORMATION or
PROCESS_SET_QUOTA or PROCESS_SET_INFORMATION or
PROCESS_VM_OPERATION or
PROCESS_VM_READ or PROCESS_VM_WRITE
// In addition to protected process
// or PROCESS_SUSPEND_RESUME or PROCESS_TERMINATE
;
// Standard and specific rights not explicitly denied
AllowedPermissions = ((not DeniedPermissions) and $1FFF) or PROCESS_TERMINATE or SYNCHRONIZE;
begin
ACL := nil;
TokenInfo := nil;
SecDesc := nil;
try
TokenSize := 0;
ProcessToken := 0;
// If this fails, you can try to fallback to OpenThreadToken
if (not OpenProcessToken(GetCurrentProcess(), TOKEN_READ, ProcessToken)) then
begin
Result := GetLastError();
Exit;
end;
BResult := GetTokenInformation(ProcessToken, TokenUser, nil, 0, TokenSize);
Result := GetLastError();
Assert((not BResult) and (ERROR_INSUFFICIENT_BUFFER = Result));
if(not ((BResult = FALSE) and (ERROR_INSUFFICIENT_BUFFER = Result))) then
begin
// failed;
Exit;
end;
if (TokenSize > 0) then
begin
TokenInfo := HeapAlloc(GetProcessHeap(), 0, TokenSize);
Result := GetLastError();
Assert(Assigned(TokenInfo));
if (nil = TokenInfo) then
begin
// failed;
Exit;
end;
end;
BResult := GetTokenInformation(ProcessToken, TokenUser, TokenInfo, TokenSize, TokenSize);
Result := GetLastError();
Assert(BResult and Assigned(TokenInfo));
if not (BResult and Assigned(TokenInfo)) then
begin
Exit;
end;
SidCurUser := (PTokenUser(TokenInfo)).User.Sid;
SIDAuthEveryone := SECURITY_WORLD_SID_AUTHORITY;
BResult := AllocateAndInitializeSid(@SIDAuthEveryone, 1,
SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, SidEveryone);
Result := GetLastError();
Assert(BResult and Assigned(SidEveryone));
if not (BResult and Assigned(SidEveryone)) then
begin
Exit;
end;
SIDAuthSystem := SECURITY_NT_AUTHORITY;
BResult := AllocateAndInitializeSid(@SIDAuthSystem, 1,
SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, SidSystem);
Result := GetLastError();
Assert(BResult and Assigned(SidSystem));
if not (BResult and Assigned(SidSystem)) then
begin
Exit;
end;
SIDAuthAdministrators := SECURITY_NT_AUTHORITY;
BResult := AllocateAndInitializeSid(@SIDAuthAdministrators, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, SidAdmins);
Result := GetLastError();
Assert(BResult and Assigned(SidAdmins));
if not (BResult and Assigned(SidAdmins)) then
begin
Exit;
end;
SIDArray[TSidType.Everyone] := SidEveryone; // Deny most rights to everyone
SIDArray[TSidType.CurrentUser] := SidCurUser; // Allow what was not denied
SIDArray[TSidType.System] := SidSystem; // Full control
SIDArray[TSidType.Admin] := SidAdmins; // Full control
// Determine required size of the ACL
Size := SizeOf(ACL);
// First the DENY, then the ALLOW
Size := Size + GetLengthSid(SIDArray[TSidType.Everyone]);
Size := Size + SizeOf(ACCESS_DENIED_ACE) - SizeOf(DWORD);
for I := TSidType.CurrentUser to High(SIDArray) do
begin
// DWORD is the SidStart field, which is not used for absolute format
Size := Size + GetLengthSid(SIDArray[I]);
Size := Size + SizeOf(ACCESS_ALLOWED_ACE) - SizeOf(DWORD);
end;
Size := Size + SizeOf(DWORD);
ACL := PACL(HeapAlloc(GetProcessHeap(), 0, Size));
Result := GetLastError();
Assert(Assigned(ACL));
if not Assigned(ACL) then
begin
Exit;
end;
BResult := InitializeAcl(ACL, Size, ACL_REVISION);
Result := GetLastError();
Assert(BResult);
if not BResult then
begin
Exit;
end;
BResult := AddAccessDeniedAce(ACL, ACL_REVISION, DeniedPermissions,
SIDArray[TSidType.Everyone]);
Result := GetLastError();
Assert(BResult);
if not BResult then
begin
Exit;
end;
BResult := AddAccessAllowedAce(ACL, ACL_REVISION, AllowedPermissions,
SIDArray[TSidType.CurrentUser]);
Result := GetLastError();
Assert(BResult);
if not BResult then
begin
Exit;
end;
// Because of ACE ordering, System will effectively have dwAllowed even
// though the ACE specifies PROCESS_ALL_ACCESS (unless software uses
// SeDebugPrivilege or SeTcbName and increases access).
// As an exercise, check behavior of tools such as Process Explorer under XP,
// Vista, and above. Vista and above should exhibit slightly different behavior
// due to Restricted tokens.
BResult := AddAccessAllowedAce(ACL, ACL_REVISION, PROCESS_ALL_ACCESS,
SIDArray[TSidType.System]);
Result := GetLastError();
Assert(BResult);
if not BResult then
begin
Exit;
end;
// Because of ACE ordering, Administrators will effectively have dwAllowed
// even though the ACE specifies PROCESS_ALL_ACCESS (unless the Administrator
// invokes 'discretionary security' by taking ownership and increasing access).
// As an exercise, check behavior of tools such as Process Explorer under XP,
// Vista, and above. Vista and above should exhibit slightly different behavior
// due to Restricted tokens.
BResult := AddAccessAllowedAce(ACL, ACL_REVISION, PROCESS_ALL_ACCESS, SIDArray[TSidType.Admin]);
Result := GetLastError();
Assert(BResult);
if not BResult then
begin
SiMain.LogWin32Error('AddAccessAllowedAce failed: ', Result);
Exit;
end;
SecDesc := PSECURITY_DESCRIPTOR(HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH));
Result := GetLastError();
Assert(Assigned(SecDesc));
if not Assigned(SecDesc) then
begin
Exit;
end;
// InitializeSecurityDescriptor initializes a security descriptor in
// absolute format, rather than self-relative format. See
// http://msdn.microsoft.com/en-us/library/aa378863(VS.85).aspx
BResult := InitializeSecurityDescriptor(SecDesc, SECURITY_DESCRIPTOR_REVISION);
Result := GetLastError();
Assert(BResult);
if not BResult then
begin
Exit;
end;
BResult := SetSecurityDescriptorDacl(SecDesc, TRUE, ACL, FALSE);
Result := GetLastError();
Assert(BResult);
if not BResult then
begin
Exit;
end;
SetSecurityInfo(
GetCurrentProcess(),
SE_KERNEL_OBJECT, // process object
OWNER_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION,
SidCurUser, // Owner SID
nil, // Group SID
ACL,
nil // SACL
);
Result := GetLastError();
Assert(ERROR_SUCCESS = Result);
finally
if (nil <> SecDesc) then
begin
HeapFree(GetProcessHeap(), 0, SecDesc);
end;
if (nil <> ACL) then
begin
HeapFree(GetProcessHeap(), 0, ACL);
end;
if (SidAdmins <> nil) then
begin
FreeSid(SidAdmins);
end;
if (SidSystem <> nil) then
begin
FreeSid(SidSystem);
end;
if (SidEveryone <> nil) then
begin
FreeSid(SidEveryone);
end;
if (nil <> TokenInfo) then
begin
HeapFree(GetProcessHeap(), 0, TokenInfo);
end;
if (0 <> ProcessToken) then
begin
CloseHandle(ProcessToken);
end;
end;
end;