Windows上的隐身用户
这篇文章引证了Windows控制面板上的用户帐号管理在用网络应用程序接口报告交互登陆时的错误。这种安全问题在Windows 2000 Professional, Windows XP Home, 和Windows XP Professional中都会出现。微软公司于2005年6月28日被通知了此问题。问题不在于网络应用程序接口,也不在于创建用户者的能力,而在于Windows中的用户帐号管理。它只是不能列出系统上的所有用户。
这个问题是在Windows上探索网络应用程序接口的时候发现的:创建时带有网络用户添加功能的用户,在用户帐号管理中并不显现(如下所例)。因为网络应用程序接口而引起的用户列举失败引出了一个问题,原因有很多种:家庭用户和管理员在使用控制面板的时候都想知道所有的用户名。
在Windows所有版本中的解决方案都是很简单的。当你在你的系统上管理你的用户帐号时,不要依赖于用户帐号管理。相反而应该用本地用户和群管理。通过以下步骤即可:控制面板/管理工具/计算机管理/本地用户和组。你也可以通过从运行框运行lusrmgr.msc 来实现。
如果你也不幸是XP Home Edition 的受害者之一的话,你可以不必用本地用户和组这种模式。作为一种替换方式,你也可以在你的系统上用以下命令列出所有的用户。
C:\net user User accounts for \\XPHOMEBITES ------------------------------------------------------------------ Administrator ASPNET Guest HelpAssistant nabiy SUPPORT_388945a0
指令成功完成。
当你用这个方法的时候你可能会看到你以前从来没见过的一些帐号。当你安装Windows的时候,微软就已经建立了4个用户:管理者帐号,客户帐号,助手帐号和Support_388945a0 帐号。可能还会有其他的帐号(比如ASPNET),这些都是后来建立的,以用作特殊目的。这些都是特殊用户,它们在以下登记处定义:[HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList]
如果你发现一个应该从XP上移除的用户名,你可以用以下指令完成:net user ACCOUNTNAME/delete,ACCOUNTNAME也就是你所想要删除的帐号。
我希望在将来的微软的各种Windows系统中,会允许用户在控制面板中列出所有的交互式帐号。感谢NEWORDER告诉我这些并让我发现其他的相关问题。
以下例子通常用来证实这些问题。
CPP方面的例子:
#include <windows.h>
#include <lm.h>
int main()
{
USER_INFO_1 ui;DWORD dwLevel = 1;
DWORD dwError = 0;
LPWSTR name = L"hidden";
LPWSTR pass = L"hidden";
ui.usri1_name = name;
ui.usri1_password = pass;
ui.usri1_priv = USER_PRIV_USER;
ui.usri1_home_dir = NULL;
ui.usri1_comment = NULL;
ui.usri1_flags = UF_SCRIPT;
ui.usri1_script_path = NULL;
NetUserAdd(NULL,
dwLevel,
(LPBYTE)&ui,
&dwError);
return 0;
}
VB.NET方面的例子
(calling the API functions) by stand__sure:
Imports System.Runtime.InteropServices
Imports LPWSTR = System.String
Imports DWORD = System.UInt32
Imports LMSTR = System.String
Imports NET_API_STATUS = System.UInt32
Module Module1
Sub Main()
Dim ui As NativeWin32.NetApi32.USER_INFO_1
Dim dwLevel As DWORD = 1
Dim dwError As DWORD = 0
Dim name As LPWSTR = "hidden"
Dim pass As LPWSTR = "H1i2D3D4e5n6"
ui.usri1_name = name
ui.usri1_password = pass
ui.usri1_priv = NativeWin32.NetApi32.USER_PRIV_USER
ui.usri1_home_dir = Nothing
ui.usri1_comment = Nothing
ui.usri1_flags = NativeWin32.NetApi32.UF_SCRIPT
ui.usri1_script_path = Nothing
Dim retval As NET_API_STATUS = NativeWin32.NetApi32.NetUserAdd(Nothing, dwLevel, ui, dwError)
Select Case retval
Case NativeWin32.Errors.NERR_Success
Console.WriteLine("Success")
Case NativeWin32.Errors.ERROR_ACCESS_DENIED
Case NativeWin32.Errors.NERR_GroupExists
Console.WriteLine("NERR_GroupExists")
Case NativeWin32.Errors.NERR_InvalidComputer
Console.WriteLine("NERR_InvalidComputer")
Case NativeWin32.Errors.NERR_PasswordTooShort
Console.WriteLine("NERR_PasswordTooShort")
Case NativeWin32.Errors.NERR_UserExists
Console.WriteLine("NERR_UserExists")
Case Else
Console.WriteLine("Error: {0:n}", retval)
End Select
End Sub
Public Class NativeWin32
Public Class NetApi32
Public Const USER_PRIV_MASK As UInt32 = &H3
Public Const USER_PRIV_GUEST As UInt32 = 0
Public Const USER_PRIV_USER As UInt32 = 1
Public Const USER_PRIV_ADMIN As UInt32 = 2
Public Const UF_SCRIPT As UInt32 = &H1
Public Const UF_ACCOUNTDISABLE As UInt32 = &H2
Public Const UF_HOMEDIR_REQUIRED As UInt32 = &H8
Public Const UF_LOCKOUT As UInt32 = &H10
Public Const UF_PASSWD_NOTREQD As UInt32 = &H20
Public Const UF_PASSWD_CANT_CHANGE As UInt32 = &H40
Public Const UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED As UInt32 = &H80 <StructLayout(LayoutKind.Sequential, _
CharSet:=CharSet.Auto)> _
Public Structure USER_INFO_1
<MarshalAs(UnmanagedType.LPWStr)> _
Dim usri1_name As LPWSTR
<MarshalAs(UnmanagedType.LPWStr)> _
Dim usri1_password As LPWSTR
Dim usri1_password_age As DWORD
Dim usri1_priv As DWORD
<MarshalAs(UnmanagedType.LPWStr)> _
Dim usri1_home_dir As LPWSTR
<MarshalAs(UnmanagedType.LPWStr)> _
Dim usri1_comment As LPWSTR
Dim usri1_flags As DWORD
<MarshalAs(UnmanagedType.LPWStr)> _
Dim usri1_script_path As LPWSTR
End Structure
<DllImport("Netapi32.dll", _
CallingConvention:=CallingConvention.Winapi, _
CharSet:=CharSet.Auto, _SetLastError:=True)> _
Public Shared Function NetUserAdd( _
<[In]()> ByVal servername As LMSTR, _
<[In]()> ByVal level As DWORD, _
<[In]()> ByRef buf As USER_INFO_1, _
<Out()> ByRef parm_err As DWORD _
) As NET_API_STATUS
End Function
End Class
Public Class Errors
''selected error constants
Public Const NERR_Success As UInt32 = 0
Public Const ERROR_ACCESS_DENIED As UInt32 = 5
Public Const NERR_BASE As UInt32 = 2100
Public Const NERR_InvalidComputer As UInt32 = (NERR_BASE + 251)
Public Const NERR_PasswordTooShort As UInt32 = (NERR_BASE + 145)
Public Const NERR_UserExists As UInt32 = (NERR_BASE + 124)
Public Const NERR_GroupExists As UInt32 = (NERR_BASE + 123)
End Class
End Class
End Module
Timeline
Security Issue Discovered Late June 2005
Microsoft Security Response Center Notified July 28, 2005
Microsoft SRC Response (Case Number 6111) July 28, 2005
Published on NewOrder.box.sk July 31, 2005
Published on Full-Disclosure August 3, 2005