码迷,mamicode.com
首页 > Windows程序 > 详细

Windows Directory ACL Security Check By ACL Baseline

时间:2015-08-14 18:31:04      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:

catalog

1. Windows NTFS ACL(MAC) Permission
2. How the System Uses ACLs
3. 服务器不安全ACL配置带来的攻击向量
4. NTFS ACL安全配置风险
5. ACL安全配置最佳实践、检测方案

 

1. Windows NTFS ACL(MAC) Permission 

windows ACL是一个主体-客体的交叉概念

1. 主体
    1) windows账户
        1.1) administrator
        1.2) Guest
        1.3) IUSR_xxx
        1.4) IWAM_xxx
        1,5) SUPPORT_xxx
        1.6) SYSTEM: 系统最高权限
        ..
    2) windows组
        2.1) administrators
        2.2) Backup Operators
        2.3) Distributed COM Users
        2.4) Guests
        2.5) Network Configuration Operators
        2.6) Performance Log Users
        2.7) Performance Monitor Users
        2.8) Power Users
        2.9) Print Operators
        2.10) Remote Desktop Users
        2.11) Replicator
        2.12) Users
        2.13) HelpServicesGroup
        2.14) IIS_WPG
        2.15) TelnetClients
    3) 安全主体
        3.1) Anonymous Logon
        3.2) Authenticated Users 
        3.3) BATCH 
        3.4) DIALUP 
        3.5) Everyone 
        3.6) Network
        3.7) Interactive 
        3.8) Terminal server user 
2. 客体
    1) 目录
    2) 文件
    3) 注册表
    4) 活动目录
    ..

0x1: Understanding Windows NTFS Permissions

When Microsoft released Windows 2000, they released a new version of NTFS, which was versioned 5. The new NTFS permissions were essentially the same logical control as the older version that was available in Windows NT, however, there were some radical and essential changes that occurred to control how the permissions were inherited and configured for each file and folder.

1. Since NTFS permissions are available on every file
2. folder,
3. Registry key
4. printer
5. Active Directory object

it is important to understand the new methods and features that are available once you have Windows 2000, Windows XP, or Windows 2003 Server installed to control resources

0x2: Standard Permissions

1. 文件

1. Full Control
The most popular and infamous standard permission is Full Control. This is what everyone wants, but in reality very few should get. Full Control allows the user that is granted this suite of permissions to do virtually anything to the object the permissions are associated with. 

2. Modify
3. Read & Execute
4. Read
5. Write

技术分享

2. 目录

Folders have the same standard permissions as files, except there is one additional standard permission "List Folder Contents"

1. Full Control:The most popular and infamous standard permission is Full Control. This is what everyone wants, but in reality very few should get. Full Control allows the user that is granted this suite of permissions to do virtually anything to the object the permissions are associated with. 
该权限允许用户对文件夹、子文件夹、文件进行全权控制,如修改资源的权限、获取资源的所有者、删除资源的权限等,拥有完全控制权限就等于拥有了其他所有的权限

2. Modify: 该权限允许用户修改或删除资源,同时让用户拥有写入及读取和运行权限
3. Read & Execute: 该权限允许用户拥有读取和列出资源目录的权限,另外也允许用户在资源中进行移动和遍历,这使得用户能够直接访问子文件夹与文件,即使用户没有权限访问这个路径
4. Read: 该权限允许用户查看该文件夹中的文件以及子文件夹,也允许查看该文件夹的属性、所有者和拥有的权限等
5. Write: 该权限允许用户在该文件夹中创建新的文件和子文件夹,也可以改变文件夹的属性、查看文件夹的所有者和权限等
6. List Folder Contents: 该权限允许用户查看资源中的子文件夹与文件名称

技术分享

When you look at Registry keys, printers, and Active Directory objects, there is a totally different set of standard permissions for these objects

0x3: Advanced Permissions

1. 文件

Advanced permissions are the detailed permissions that are grouped together to create the standard permissions. Since advanced permissions are used in combinations to create the standard permissions, there are more of them overall. For a file, here is a list of the advanced permissions

1. Full Control
2. Traverse Folder/Execute File: 该权限允许用户在文件夹及其子文件夹之间移动(遍历),即使这些文件夹本身没有访问权限
/*
注意:只有当在"组策略"中("计算机配置" -> "Windows设置" -> "安全设置" -> "本地策略" -> "用户权利指派")将"跳过遍历检查"项授予了特定的用户或用户组,该项权限才能起作用。默认状态下,包"Administrators"、"Users"、"Everyone"等在内的组都可以使用该权限。
对于文件来说,拥了这项权限后,用户可以执行该程序文件。但是,如果仅为文件夹设置了这项权限的话,并不会让用户对其中的文件带上"执行"的权限,因为对于目录来说,执行权限是读取的前提
*/

3. List Folder/Read Data: 该权限允许用户查看文件夹中的文件名称、子文件夹名称和查看文件中的数据
4. Read Attributes: 该权限允许用户查看文件或文件夹的属性(如系统、只读、隐藏等属性) 
5. Read Extended Attributes: 该权限允许查看文件或文件夹的扩展属性,这些扩展属性通常由程序所定义,并可以被程序修改
6. Create Files/Write Data: 该权限允许用户在文件夹中创建新文件,也允许将数据写入现有文件并覆盖现有文件中的数据
7. Create Folders/Append Data: 该权限允许用户在文件夹中创建新文件夹或允许用户在现有文件的末尾添加数据,但不能对文件现有的数据进行覆盖、修改,也不能删除数据 
8. Write Attributes: 该权限允许用户改变文件或文件夹的属性
9. Write Extended Attributes: 该权限允许用户对文件或文件夹的扩展属性进行修改
10. Delete: 该权限允许用户删除当前文件夹和文件,如果用户在该文件或文件夹上没有删除权限,但是在其父级的文件夹上有删除子文件及文件夹权限,那么就仍然可以删除它
11. Read Permissions: 该权限允许用户读取文件或文件夹的权限列表
12. Change Permissions: 该权限允许用户改变文件或文件夹上的现有权限
13. Take Ownership: 该权限允许用户获取文件或文件夹的所有权,一旦获取了所有权,用户就可以对文件或文件夹进行全权控制

从本质上来说,高级权限是对标准权限的一个组合
For example, the specific advanced permissions that are used to create the Read standard permission include:

1. List Folder/Read Data
2. Read Attributes
3. Read Extended Attributes
4. Read Permissions

When you evaluate the advanced permissions for a folder, they are identical to those of a file. However, when you investigate the advanced permissions of a printer or Registry key, they are completely different. If you want to see the power and control that NTFS 5.0 provides for access control, it is best to investigate the permissions of an OU within Active Directory.
本文主要关注的是windows主机上目录、文件的ACL不恰当配置

1. 标准访问权限(standard permission)将一些常用的系统权限选项比较笼统地组成6种"套餐型"的权限,即
    1) 完全控制
    2) 修改
    3) 读取和运行
    4) 列出文件夹目录
    5) 读取
    6) 写入
在大多数的情况下,"标准权限"是可以满足管理需要的,但对于权限管理要求严格的环境,它往往就不能令管理员们满意了,如
    1) 只想赋予某用户有建立文件夹的权限,却没有建立文件的权限
    2) 如只能删除当前目录中的文件,却不能删除当前目录中的子目录的权限等
这个时候,就可以让拥有所有权限选项的"特别权限"来大显身手了。也就是说,特别权限不再使用"套餐型",而是使用可以允许用户进行"菜单型"的细节化权限管理选择了

2. 特别访问权限(special permission)是标准权限的细粒度表现,或者说标准权限是对多个特别访问权限进行了"组合(异或)"

这里需要单独说明一下"修改"权限与"写入"权限的区别

1. 修改: 如果仅仅对一个文件拥有修改权限,那么,不仅可以对该文件数据进行写入和附加,而且还可以创建新文件或删除现有文件
2. 写入: 而如果仅仅对一个文件拥有写入权限,那么既可以对文件数据进行写入和附加,也可以创建新文件,但是不能删除文件
//也就是说,有写入权限不等于具有删除权限,但拥有修改权限,就等同于拥有删除和写入权限 

0x4: Inherited vs. Explicit Permissions

1. 拒绝优于允许原则

"拒绝优于允许"原则是一条非常重要且基础性的原则,它可以非常完美地处理好因用户在用户组的归属方面引起的权限"纠纷",例如,"littlehann"这个用户既属于"alisecurity"用户组,也属于"security"用户组

1. 当我们对"security"组中某个资源进行"写入"权限的集中分配(即针对用户组进行))时,这个时候该组中 "littlehann"账户将自动拥有"写入"的权限
2. 同时在"alisecurity"组中同样也对"littlehann"用户进行了针对这个资源的权限设置,但设置的权限是"拒绝写入"
3. 基于"拒绝优于允许"的原则,"littlehann""alisecurity"组中被 "拒绝写入"的权限将优先"security"组中被赋予的允许"写入"权限被执行。因此,在实际操作中,"littlehann"用户无法对这个资源进行"写入"操作

2. 权限最小化原则

Windows将"保持用户最小的权限"作为一个基本原则进行执行,这一点是非常有必要的。这条原则可以确保资源得到最大的安全保障。这条原则可以尽量让用户不能访问或不必要访问的资源得到有效的权限赋予限制
基于这条原则,在实际的权限赋予操作中,我们就必须为资源明确赋予允许或拒绝操作的权限。例如系统中新建的受限用户"littlehann"在默认状态下对 "DOC"目录是没有任何权限的,现在需要为这个用户赋予对"DOC"目录有"读取"的权限,那么就必须在"DOC"目录的权限列表中为 "littlehann"用户添加"读取"权限

3. 权限继承性原则

权限继承性原则可以让资源的权限设置变得更加简单。假设现在有个"DOC"目录,在这个目录中有"DOC01"、"DOC02"、"DOC03"等子目录,现在需要对DOC目录及其下的子目录均设置"littlehann"用户有"写入"权限。因为有继承性原则,所以只需对"DOC"目录设置"littlehann"用户有"写入"权限,其下的所有子目录将自动继承这个权限的设置

4. 累加原则

这个原则比较好理解,假设现在"littlehann"用户既属于"A"用户组,也属于"B"用户组,它在A用户组的权限是"读取",在"B"用户组中的权限是"写入",那么根据累加原则,"littlehann"用户的实际权限将会是"读取+写入"两种

1. "拒绝优于允许"原则是用于解决权限设置上的冲突问题的
2. "权限最小化"原则是用于保障资源安全的
3. "权限继承性"原则是用于"自动化"执行权限设置的
4. 而"累加原则"则是让权限的设置更加灵活多变 
/*
"Administrators"组的全部成员都拥有"取得所有者身份"(Take Ownership)的权力,也就是管理员组的成员可以从其他用户手中"夺取"其身份的权力。例如受限用户"littlehann"建立了一个DOC目录,并只赋予自己拥有读取权力,这看似周到的权限设置,实际上,"Administrators"组的全部成员将可以通过"夺取所有权"等方法获得这个权限 
即windows上的administrators组成员具有最高权限
*/

0x5: 安全主体

安全主体的作用是可以让我们指派权限到某种"状态"的用户(如"匿名用户"、"网络用户")等,而不是某个特定的用户或组(如 "test"、"littlehann"这类用户)。这样一来,对用户权限的管理就更加容易精确控制了。这群用户在Windows中,统一称为内置安全主体

1. Anonymous Logon: 任何没有经过Windows验证程序(Authentication),而以匿名方式登录域的用户均属于此组 
2. Authenticated Users: 与前项相反,所有经过Windows验证程序登录的用户均属于此组。设置权限和用户权力时,可考虑用此项代替Everyone组 
3. BATCH: 这个组包含任何访问这台计算机的批处理程序(Batch Process)
4. DIALUP: 任何通过拨号网络登录的用户
5. Everyone: 指所有经验证登录的用户及来宾(Guest)
6. Network: 任何通过网络登录的用户
7. Interactive: 指任何直接登录本机的用户
8. Terminal server user: 指任何通过终端服务登录的用户

Relevant Link:

http://baike.baidu.com/view/583933.htm
https://support.microsoft.com/zh-cn/kb/313398
http://baike.baidu.com/view/41454.htm
http://www.windowsecurity.com/articles-tutorials/authentication_and_encryption/Understanding-Windows-NTFS-Permissions.html

 

2. How the System Uses ACLs

NTFS是windows上的ACL权限控制架构,是理论级的概念,如果从程序角度理解就是ACLs、ACEs

1. Each user logged onto the system holds an access token with security information for that logon session
2. The system creates an access token when the user logs on
3. Every process executed on behalf of the user has a copy of the access token,进程的权限即启动该进程的那个登录用户的权限
4. The token identifies the user, the users groups, and the users privileges
5. A token also contains a logon SID (Security Identifier) that identifies the current logon session.

When a thread tries to access a securable object, the LSASS (Local Security Authority) either grants or denies access. To do this, the LSASS searches the DACL (Discretionary Access Control List) in the SDS data stream, looking for ACEs that apply to the thread.
Each ACE in the object‘s DACL specifies the access rights that are allowed or denied for a security principal(安全体) or logon session(登录账户).
If the object‘s owner has not created any ACEs in the DACL for that object, the system grants access right away(默认情况下都会赋予system操作权限

1. 如果没有DACL,那么所有人都可以访问:FAT32
2. DACL没有ACE,那么所有人都不能访问:windows的最小权限原则

If the LSASS finds ACEs, it compares the trustee SID in each ACE to the trustee SIDs that are identified in the thread‘s access token,即主体-客体比较
The system examines each ACE in sequence until one of the following events occurs:

1. An access-denied ACE explicitly denies any of the requested access rights to one of the trustees listed in the threads access token.(拒绝优于允许原则)
2. One or more access-allowed ACEs for trustees listed in the threads access token explicitly grant all the requested access rights.(累加原则)
3. All ACEs have been checked and there is still at least one requested access right that has not been explicitly allowed, in which case, access is implicitly denied.

0x1: Order of ACEs

Because the system stops checking ACEs when the requested access is explicitly granted or denied, the order of ACEs in a DACL is important.
The preferred order of ACEs in a DACL is called the "canonical" order. For Windows 2000 and Windows Server 2003, the canonical order is the following:

1. All explicit ACEs are placed in a group before any inherited ACEs. 就近原则,文件/目录自身明确指定的ACE是最优先的
2. Within the group of explicit ACEs, access-denied ACEs are placed before access-allowed ACEs. 拒绝优先原则
3. Within the inherited group, ACEs that are inherited from the child objects parent come first, and then ACEs inherited from the grandparent, and so on up the tree of objects. After that, access-denied ACEs are placed before access-allowed ACEs.逐层逆向递归的权限继承,同时遵循拒绝优先原则

技术分享

The canonical order ensures that the following takes place:

1. An explicit access-denied ACE is enforced regardless of any explicit access-allowed ACE. This means that the objects owner can define permissions that allow access to a group of users and deny access to a subset of that group.
2. All explicit ACEs are processed before any inherited ACE. This is consistent with the concept of discretionary access control: 
//access to a child object (for example a file) is at the discretion of the child‘s owner, not the owner of the parent object (for example a folder). The owner of a child object can define permissions directly on the child. The result is that the effects of inherited permissions are modified. 就近原则

可以把ACEs的匹配规约理解为一个switch链,从上至下逐个匹配,一旦命中某个规则,则立刻应用并停止匹配

0x2: Access Control Entries

As stated previously, an ACL (Access Control List) is an ordered list of ACEs (Access Control Entries). Each ACE contains the following:

1. A SID (Security Identifier) that identifies a particular user or group.
2. An access mask that specifies access rights.
3. A set of bit flags that determine whether or not child objects can inherit the ACE.
4. A flag that indicates the type of ACE(file、directory、regedit..)

ACEs are fundamentally alike. What sets them apart is the degree of control they offer over inheritance and object access. There are two types of ACE:

1. Generic type that are attached to all securable objects.
2. Object-specific type that can occur only in ACLs for Active Directory objects.

0x3: Generic ACE

A generic ACE offers limited control over the kinds of child objects that can inherit them. Essentially, they can distinguish only between containers and noncontainers.
即容器(文件夹)和非容器(文件对象)的generic ACE是不一样的

For example, the DACL (Discretionary Access Control List) on a Folder object in NTFS can include a generic ACE that allows a group of users to list the folder‘s contents. Because listing a folder‘s contents is an operation that can be performed only on a Container object, the ACE that allows the operation can be flagged as a CONTAINER_INHERIT_ACE. Only Container objects in the folder (that is, only other Folder objects) inherit the ACE. Noncontainer objects (that is, File objects) do not inherit the ACE of the parent object.

A generic ACE applies to an entire object. If a generic ACE gives a particular user Read access, the user can read all the information that is associated with the object — both data and properties. This is not a serious limitation for most object types.
File objects, for example, have few properties, which are all used for describing characteristics of the object rather than for storing information. Most of the information in a File object is stored as object data; therefore, there is little need for separate controls on a file‘s properties.

0x4: Object-specific ACE

An object-specific ACE offers a greater degree of control over the types of child objects that can inherit them.

For example, an OU (Organizational Unit) object‘s ACL can have an object-specific ACE that is marked for inheritance only by User objects. Other types of objects, such as Computer objects, will not inherit the ACE.

This capability is why object-specific ACEs are called object-specific. Their inheritance can be limited to specific types of child objects.

There are similar differences in how the two categories of ACE types control access to objects.

An object-specific ACE can apply to any individual property of an object or to a set of properties for that object. This type of ACE is used only in an ACL for Active Directory objects, which, unlike other object types, store most of their information in properties. It is often desirable to place independent controls on each property of an Active Directory object, and object-specific ACEs make that possible.

For example, when you define permissions for a User object, you can use one object-specific ACE to allow Principal Self (that is, the user) Write access to the Phone-Home-Primary (homePhone) property, and you can use other object-specific ACEs to deny Principal Self access to the Logon-Hours (logonHours) property and other properties that set restrictions on the user account.

0x5: Access Control Entry Layout

The table below shows the layout of each ACE.

ACE Field

Description

Type

Flag that indicates the type of ACE.
Windows 2000 and Windows Server 2003 support six types of ACE:
- Three generic ACE types that are attached to all securable objects.
- Three object-specific ACE types that can occur for Active Directory objects.

Flags

Set of bit flags that control inheritance and auditing.

Size

Number of bytes of memory that are allocated for the ACE.

Access mask

32-bit value whose bits correspond to access rights for the object. Bits can be set either on or off, but the setting‘s meaning depends on the ACE type. For example, if the bit that corresponds to the right to read permissions is turned on, and the ACE type is Deny, the ACE denies the right to read the object‘s permissions. If the same bit is set on but the ACE type is Allow, the ACE grants the right to read the object‘s permissions. More details of the Access mask appear in the next table.

SID

Identifies a user or group whose access is controlled or monitored by this ACE.

0x6: Access Mask Layout

Bit (Range)

Meaning

Description/Example

0 – 15

Object Specific Access Rights

Read data, Execute, Append data

16 – 22

Standard Access Rights

Delete, Write ACL, Write Owner

23

Can access security ACL

 

24 – 27

Reserved

 

28

Generic ALL (Read, Write, Execute)

Everything below

29

Generic Execute

All things necessary to execute a program

30

Generic Write

All things necessary to write to a file

31

Generic Read

All things necessary to read a file

Relevant Link:

http://www.ntfs.com/ntfs-permissions-acl-use.htm

 

3. 服务器不安全ACL配置带来的攻击向量

我们从入侵攻防的角度来看NTFS ACL配置在入侵向量中起到的作用

0x1: 上传WEBSHELL到网站目录

在正常情况下,WEB网站的运行过程中,会产生一些临时文件、缓存文件,但这仅仅限于指定目录下,对于其他目录(尤其是网站根目录)不应该具备写权限,由于松散的NTFS ACL配置,导致了黑客将WEBSHELL随意地写入网站目录下,进而获得服务器权限

0x2: 上传可执行程序到网站目录、敏感目录

0x3: 黑客利用WEB组件执行系统指令

一般WebShell用到以下组件

1. WScript.Network
2. WScript.Network.1
3. WScript.Shell
4. WScript.Shell.1
5. Shell.Application
6. Shell.Application.1
//我们在注册表中将以上键值改名或删除,同时需要注意按照这些键值下的CLSID键的内容,从/HKEY_CLASSES_ROOT/CLSID下面对应的键值删除

这些组件基本在system32目录下,对windows系统敏感目录,需要进行严格的ACL权限验证

Relevant Link:

http://tutorials.hostucan.cn/article-5548 
http://www.net.cn/static/newsletter/news_zhoukan004_safe.asp
http://blog.snsgou.com/post-510.html
http://blog.snsgou.com/post-510.html
http://wenku.baidu.com/view/889f9ffbfab069dc502201f7.html

 

4. NTFS ACL安全配置风险

0x1: 系统敏感目录、网站目录、及其子目录/文件设置了everyone权限

everyone是一个安全主体,指所有经验证登录的用户及来宾(Guest),它的涵盖范围太大了,非常不建议设置这个权限,不安全的配置包括

1. 可写
2. 可读
2. 修改
3. 读取和执行
//黑客可以上传可执行文件并执行
4. 完全访问

出于安全性的考虑,everyone不应该被赋予任何权限

0x2: 系统敏感目录、网站目录、及其子目录/文件设置了IUSER_XXXXXX账户(属于Internet来宾帐户安全主体,属于Guest组)权限
0x3: 系统敏感目录、网站目录、及其子目录/文件设置了Users权限
0x4: 系统敏感目录、网站目录、及其子目录/文件设置了Guest权限
0x5: 系统敏感目录、网站目录、及其子目录/文件设置了Power Users权限

对于IIS来说,它的Process Token为IUSER_XXXXXX/Users/Guest/Power Users权限,默认情况所有访问WEB Server的访问者都具有这些权限,不安全的配置包括

1. 可写 
2. 修改 
3. 完全访问

"读取权限"、"读取和运行"、"列出文件夹内容"是WEB Server正常需要的,脚本被解释执行的第一步就是读取文件内容

0x6: 系统敏感目录、网站目录、及其子目录/文件设置了SYSTEM权限

对于很多系统管理员来说,常常直接使用administrator登录系统,并直接启动WEB Server,这导致了WEB Server以SYSTEM安全Token运行,这是一个很高权限的账户权限,不安全的配置包括

1. 可写 
2. 修改 
3. 完全访问

0x7: 系统敏感目录、网站目录、及其子目录/文件设置了administrator/administrators权限

从Vista,Win7开始,系统默认的用户虽然是管理员身份,但Administrator权限并不是系统的最高权限,而系统内置的System权限是Windows系统中高于Administrator的权限,系统底层最高的权限是属于TrustedInstaller用户组权限,非人为可以设置的权限,需要注意的是,windows上以服务形式启动的进程,进程权限都是SYSTEM

所以在登录界面那个时候如果用shift后门启动的cme也是system权限的,因为winlogin也是一个服务,根据进程权限继承原则,它启动的子进程cmd也是system权限的

对于使用这类权限运行的web server来说,不安全的配置包括

1. 可写 
2. 修改 
3. 完全访问

但是需要明白的,导致这个安全风险的根源不在system、administrators、administrator的权限过高,作为操作系统本来就需要对目录/文件有较高的控制权,问题的根源在于作为对外提供服务的web server本身就不应该以这些高权限账户运行

0x8: 系统敏感目录、网站目录、及其子目录/文件设置了Anonymous Logon权限

当IIS设置了匿名登录,所有通过WEB访问的用户都处于Anonymous Logon权限下,不安全的配置包括

1. 可写 
2. 修改 
3. 完全访问

Relevant Link:

http://www.ourys.com/post/99.html
http://blog.csdn.net/liynet/article/details/8854982
http://www.xker.com/page/e2009/1227/89775.html
http://os.51cto.com/art/201005/200977.htm
https://msdn.microsoft.com/zh-cn/library/ms178699(v=vs.100).aspx
http://www.ithome.com/html/soft/56205.htm

 

5. ACL安全配置最佳实践、检测方案

0x1: ACL账户检查项(主体)

1. Anonymous Logon 
2. Everyone 
3. Power Users
4. Users
5. Guests
6. IIS_WPG
7. IUSER_XXXXXX账户  
8. Guest 
9. SUPPORT_xxx

0x2: ACL检测磁盘路径(客体)

1. windows系统敏感目录/文件
    1) C:\WINDOWS\system32
    2) C:\WINDOWS\system32\子目录(文件): 非递归
2. 用户配置信息文件夹
    1) C:\Documents and Settings\All Users\Application Data: Application Data是本地默认的通用应用程序数据文件夹,存放着已经安装的一些应用程序的专用数据,每个用户在Documents and Settings都有一个自己专属的文件夹,而All Users是所有用户公用的文件夹,黑客常常把恶意程序上传到这个文件夹下
    2) C:\Documents and Settings\All Users\Application Data\Microsoft\HTML Help: 
3. web server根目录
    1) apache
    2) nginx
    3) tomcat
    4) IIS

对主体和客体进行二维笛卡儿积组合,获取指定磁盘路径的ACL账户组、及其对应账户组设置的权限,判断当前是否存在不安全ACL配置,这种是典型的黑名单的检测思想,黑名单思想的难点在于枚举过程需要调研全部的攻击面,难以覆盖全,我们可以反过来,采取白名单检测思想,对指定目录设定ACL安全配置基线,实际获取的ACL配置和安全基线的差集就是检测出来存在漏洞的结果

0x3: ACL白名单安全基线

1. C:\WINDOWS\system32
    1) administrators: 完全控制
    2) SYSTEM: 完全控制
    3) Users: 读取和运行 | 列出文件夹目录 | 读取
2. C:\WINDOWS\system32\..(文件)
    1) xx.exe  2) xx.vbs /*
system32下的这些后缀文件的安全基线都是相同的
1) administrators: 完全控制
2) SYSTEM: 完全控制
3) Users: 读取和运行 | 读取
4) Power Users: 读取和运行 | 读取
*/

3. C:\Documents and Settings\All Users\Application Data\ 
//Application Data是本地默认的通用应用程序数据文件夹,存放着已经安装的一些应用程序的专用数据,每个用户在Documents and Settings都有一个自己专属的文件夹,而All Users是所有用户公用的文件夹,黑客常常把恶意程序上传到这个文件夹下
    1) administrators: 完全控制
    2) SYSTEM: 完全控制
    3) Users: 读取和运行 | 列出文件夹目录 | 读取 | 写入
4. C:\Documents and Settings\All Users\Application Data\..(文件夹)
    1) administrators: 完全控制
    2) SYSTEM: 完全控制
    3) Users: 读取和运行 | 读取
    4) Power Users: 修改 | 读取和运行 | 列出文件夹目录 | 读取 | 写入 

5. web server根目录、子目录(文件夹)
    1) administrators: 完全控制
    2) IIS_WPG: 读取和运行 | 列出文件夹目录 | 读取
    3) IUSR_xx(Internet来宾账户): ~写入(拒绝写入)
    4) SYSTEM: 完全控制
    5) Users: 读取和运行 | 列出文件夹目录 | 读取
    6) CREATEOR OWNER: 完全控制(特别权限)
    7) Power Users: 读取和运行 | 列出文件夹目录 | 读取
//除了administrators、SYSTEM、CREATEOR有写权限之外,其他账户都是禁止写入的

6. mysql plugin目录(例如: D:\wamp\bin\mysql\mysql5.6.17\lib\plugin)
    1) administrators: 完全控制
    2) SYSTEM: 完全控制
    3) Users: 读取和运行 | 列出文件夹目录 | 读取
//对mysql plugin目录,安全ACL基线需要设置的严格一点,禁止除了administrators之外的所有的写权限

0x4: 获取指定目录/文件的ACEs列表

1. GetNamedSecurityInfo
//The GetNamedSecurityInfo function retrieves a copy of the security descriptor for an object specified by name.

2. GetExplicitEntriesFromAcl
//The GetExplicitEntriesFromAcl function retrieves an array of structures that describe the access control entries (ACEs) in an access control list (ACL)

3. EXPLICIT_ACCESS -> Trustee.ptstrName: 获取ACE对应SID账户名
4. EXPLICIT_ACCESS -> grfAccessPermissions: 获取ACE对应权限

0x5: 技术方案

1. 声明一个std::map<TCHAR*, map<TCHAR*, vector<TCHAR*>>>作为ACL配置安全基线
2. 遍历ACL安全基线中的路径,获取ACLs账户列表
    1) 如果发现有不在ACL基线中的账户,则记录超出安全基线的账户、及其配置的权限
    2) 如果账户在安全基线中,但是对其配置的权限超出了安全基线中该账户的权限,则记录超出基线配置的权限
    3) 除此之外,则判定为安全

0x6: 需要注意的问题

1. c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\WinNT.h
vs2010的WinNT.h文件中,对账户的枚举定义少于MSDN官方给出的枚举定义,但是需要明白的是,对这类未识别的UnKnown账户,检测程序也可以直接选择忽略,因为我们是白名单基线思想,那些在高版本windows上才出现的为识别的账户,本身也不可能构成入侵向量的ACL配置

2. 所有的ACL安全基线中包含的目录项都是在程序运行时动态生成的,这就包含了如果当前服务器进行了安全加固,使得我们要检测的目标目录不可读取,则安全ACL基线无法生成,但这同时也代表着当前主机是没有ACL风险的

3. 32bit程序在64bit操作系统下调用GetModuleFileNameEx失败返回299错误
http://blog.csdn.net/anycell/article/details/3505864
采取GetProccessImageFileName、QueryFullProcessImageName替代进行进程路径的获取

4. GetProccessImageFileName返回的是逻辑驱动路径,例如: \\Device\\HarddiskVolume3\\wamp\\bin\\mysql\\mysql5.6.17\\bin,可以通过在注册表中查找逻辑驱动映射表来进行查表翻译
http://stackoverflow.com/questions/65170/how-to-get-name-associated-with-open-handle/18792477#18792477

0x7: Code Example

//windowsAclLeakCheck
#include <fstream>
struct cmp_str
{
    bool operator()(const TCHAR *a, const TCHAR *b)
    {
        return _tcscmp(a, b) < 0;
    }
}; 
typedef std::map<TCHAR*, map<TCHAR*, vector<TCHAR*>, cmp_str>, cmp_str> ACLBaseMap;
typedef std::map<TCHAR*, vector<TCHAR*>, cmp_str> ACEBaseMap;

//get SID name string
void SIDToAccountName(PSID pSid, TCHAR* AccountName)
{ 
    if( IsWellKnownSid(pSid, WinNullSid ) == TRUE)
    {
        TCHAR* username = _T("WinNullSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinWorldSid ) == TRUE)
    {
        TCHAR* username = _T("WinWorldSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinLocalSid ) == TRUE)
    {
        TCHAR* username = _T("WinLocalSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinCreatorOwnerSid ) == TRUE)
    {
        TCHAR* username = _T("WinCreatorOwnerSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinCreatorGroupSid ) == TRUE)
    {
        TCHAR* username = _T("WinCreatorGroupSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinCreatorOwnerServerSid ) == TRUE)
    {
        TCHAR* username = _T("WinCreatorOwnerServerSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinCreatorGroupServerSid ) == TRUE)
    {
        TCHAR* username = _T("WinCreatorGroupServerSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinNtAuthoritySid ) == TRUE)
    {
        TCHAR* username = _T("WinNtAuthoritySid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinDialupSid ) == TRUE)
    {
        TCHAR* username = _T("WinDialupSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinNetworkSid ) == TRUE)
    {
        TCHAR* username = _T("WinNetworkSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBatchSid ) == TRUE)
    {
        TCHAR* username = _T("WinBatchSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinInteractiveSid ) == TRUE)
    {
        TCHAR* username = _T("WinInteractiveSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinServiceSid ) == TRUE)
    {
        TCHAR* username = _T("WinServiceSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAnonymousSid ) == TRUE)
    {
        TCHAR* username = _T("WinAnonymousSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinProxySid ) == TRUE)
    {
        TCHAR* username = _T("WinProxySid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinEnterpriseControllersSid ) == TRUE)
    {
        TCHAR* username = _T("WinEnterpriseControllersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinSelfSid ) == TRUE)
    {
        TCHAR* username = _T("WinSelfSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAuthenticatedUserSid ) == TRUE)
    {
        TCHAR* username = _T("WinAuthenticatedUserSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinRestrictedCodeSid ) == TRUE)
    {
        TCHAR* username = _T("WinRestrictedCodeSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinTerminalServerSid ) == TRUE)
    {
        TCHAR* username = _T("WinTerminalServerSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinRemoteLogonIdSid ) == TRUE)
    {
        TCHAR* username = _T("WinRemoteLogonIdSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinLogonIdsSid ) == TRUE)
    {
        TCHAR* username = _T("WinLogonIdsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinLocalSystemSid ) == TRUE)
    {
        TCHAR* username = _T("WinLocalSystemSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinLocalServiceSid ) == TRUE)
    {
        TCHAR* username = _T("WinLocalServiceSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinNetworkServiceSid ) == TRUE)
    {
        TCHAR* username = _T("WinNetworkServiceSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinDomainSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinDomainSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinAdministratorsSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinAdministratorsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinUsersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinUsersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinGuestsSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinGuestsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinPowerUsersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinPowerUsersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinAccountOperatorsSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinAccountOperatorsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinSystemOperatorsSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinSystemOperatorsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinPrintOperatorsSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinPrintOperatorsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinBackupOperatorsSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinBackupOperatorsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinReplicatorSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinReplicatorSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinPreWindows2000CompatibleAccessSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinPreWindows2000CompatibleAccessSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinRemoteDesktopUsersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinRemoteDesktopUsersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinNetworkConfigurationOperatorsSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinNetworkConfigurationOperatorsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountAdministratorSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountAdministratorSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountGuestSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountGuestSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountKrbtgtSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountKrbtgtSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountDomainAdminsSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountDomainAdminsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountDomainUsersSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountDomainUsersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountDomainGuestsSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountDomainGuestsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountComputersSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountComputersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountControllersSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountControllersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountCertAdminsSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountCertAdminsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountSchemaAdminsSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountSchemaAdminsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountEnterpriseAdminsSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountEnterpriseAdminsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountPolicyAdminsSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountPolicyAdminsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountRasAndIasServersSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountRasAndIasServersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinNTLMAuthenticationSid ) == TRUE)
    {
        TCHAR* username = _T("WinNTLMAuthenticationSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinDigestAuthenticationSid ) == TRUE)
    {
        TCHAR* username = _T("WinDigestAuthenticationSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinSChannelAuthenticationSid ) == TRUE)
    {
        TCHAR* username = _T("WinSChannelAuthenticationSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinThisOrganizationSid ) == TRUE)
    {
        TCHAR* username = _T("WinThisOrganizationSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinOtherOrganizationSid ) == TRUE)
    {
        TCHAR* username = _T("WinOtherOrganizationSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinIncomingForestTrustBuildersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinIncomingForestTrustBuildersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinPerfMonitoringUsersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinPerfMonitoringUsersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinPerfLoggingUsersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinPerfLoggingUsersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinAuthorizationAccessSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinAuthorizationAccessSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinTerminalServerLicenseServersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinTerminalServerLicenseServersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinDCOMUsersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinDCOMUsersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinIUsersSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinIUsersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinIUserSid ) == TRUE)
    {
        TCHAR* username = _T("WinIUserSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinCryptoOperatorsSid ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinCryptoOperatorsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinUntrustedLabelSid ) == TRUE)
    {
        TCHAR* username = _T("WinUntrustedLabelSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinLowLabelSid ) == TRUE)
    {
        TCHAR* username = _T("WinLowLabelSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinMediumLabelSid ) == TRUE)
    {
        TCHAR* username = _T("WinMediumLabelSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinHighLabelSid ) == TRUE)
    {
        TCHAR* username = _T("WinHighLabelSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinSystemLabelSid ) == TRUE)
    {
        TCHAR* username = _T("WinSystemLabelSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinWriteRestrictedCodeSid ) == TRUE)
    {
        TCHAR* username = _T("WinWriteRestrictedCodeSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinCreatorOwnerRightsSid ) == TRUE)
    {
        TCHAR* username = _T("WinCreatorOwnerRightsSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinCacheablePrincipalsGroupSid ) == TRUE)
    {
        TCHAR* username = _T("WinCacheablePrincipalsGroupSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinNonCacheablePrincipalsGroupSid ) == TRUE)
    {
        TCHAR* username = _T("WinNonCacheablePrincipalsGroupSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinEnterpriseReadonlyControllersSid ) == TRUE)
    {
        TCHAR* username = _T("WinEnterpriseReadonlyControllersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinAccountReadonlyControllersSid ) == TRUE)
    {
        TCHAR* username = _T("WinAccountReadonlyControllersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinEventLogReadersGroup ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinEventLogReadersGroup");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinNewEnterpriseReadonlyControllersSid ) == TRUE)
    {
        TCHAR* username = _T("WinNewEnterpriseReadonlyControllersSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinBuiltinCertSvcDComAccessGroup ) == TRUE)
    {
        TCHAR* username = _T("WinBuiltinCertSvcDComAccessGroup");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinMediumPlusLabelSid ) == TRUE)
    {
        TCHAR* username = _T("WinMediumPlusLabelSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinLocalLogonSid ) == TRUE)
    {
        TCHAR* username = _T("WinLocalLogonSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinConsoleLogonSid ) == TRUE)
    {
        TCHAR* username = _T("WinConsoleLogonSid");
        lstrcpy(AccountName, username);
    }
    else if( IsWellKnownSid(pSid, WinThisOrganizationCertificateSid ) == TRUE)
    {
        TCHAR* username = _T("WinThisOrganizationCertificateSid");
        lstrcpy(AccountName, username);
    } 
    else
    {
        TCHAR* username = _T("UnKnownAccount");
        lstrcpy(AccountName, username);
    }
}
//get ACCESS_MASK
void AccessPermissionsToACCESSMASK( DWORD grfAccessPermissions, std::vector<TCHAR*>& AccessMakeList)
{
    int found = 0;
    if( (grfAccessPermissions & DELETE) == DELETE)
    { 
        AccessMakeList.push_back(_T("DELETE"));
        found = 1;
    }
    if( (grfAccessPermissions & READ_CONTROL) == READ_CONTROL)
    { 
        AccessMakeList.push_back(_T("READ_CONTROL"));
        found = 1;
    }
    if( (grfAccessPermissions & WRITE_DAC) == WRITE_DAC)
    { 
        AccessMakeList.push_back(_T("WRITE_DAC"));
        found = 1;
    }
    if( (grfAccessPermissions & WRITE_OWNER) == WRITE_OWNER)
    { 
        AccessMakeList.push_back(_T("WRITE_OWNER"));
        found = 1;
    }
    if( (grfAccessPermissions & SYNCHRONIZE) == SYNCHRONIZE)
    { 
        AccessMakeList.push_back(_T("SYNCHRONIZE"));
        found = 1;
    }
    if( (grfAccessPermissions & STANDARD_RIGHTS_REQUIRED) == STANDARD_RIGHTS_REQUIRED)
    { 
        AccessMakeList.push_back(_T("STANDARD_RIGHTS_REQUIRED"));
        found = 1;
    }
    if( (grfAccessPermissions & STANDARD_RIGHTS_READ) == STANDARD_RIGHTS_READ)
    { 
        AccessMakeList.push_back(_T("STANDARD_RIGHTS_READ"));
        found = 1;
    }
    if( (grfAccessPermissions & STANDARD_RIGHTS_WRITE) == STANDARD_RIGHTS_WRITE)
    { 
        AccessMakeList.push_back(_T("STANDARD_RIGHTS_WRITE"));
        found = 1;
    }
    if( (grfAccessPermissions & STANDARD_RIGHTS_EXECUTE) == STANDARD_RIGHTS_EXECUTE)
    { 
        AccessMakeList.push_back(_T("STANDARD_RIGHTS_EXECUTE"));
        found = 1;
    }
    if( (grfAccessPermissions & STANDARD_RIGHTS_ALL) == STANDARD_RIGHTS_ALL)
    { 
        AccessMakeList.push_back(_T("STANDARD_RIGHTS_ALL"));
        found = 1;
    }
    if( (grfAccessPermissions & SPECIFIC_RIGHTS_ALL) == SPECIFIC_RIGHTS_ALL)
    { 
        AccessMakeList.push_back(_T("SPECIFIC_RIGHTS_ALL"));
        found = 1;
    }
    if( (grfAccessPermissions & ACCESS_SYSTEM_SECURITY) == ACCESS_SYSTEM_SECURITY)
    { 
        AccessMakeList.push_back(_T("ACCESS_SYSTEM_SECURITY"));
        found = 1;
    }
    if( (grfAccessPermissions & MAXIMUM_ALLOWED) == MAXIMUM_ALLOWED)
    { 
        AccessMakeList.push_back(_T("MAXIMUM_ALLOWED"));
        found = 1;
    }
    if( (grfAccessPermissions & GENERIC_READ) == GENERIC_READ)
    { 
        AccessMakeList.push_back(_T("GENERIC_READ"));
        found = 1;
    }
    if( (grfAccessPermissions & GENERIC_WRITE) == GENERIC_WRITE)
    { 
        AccessMakeList.push_back(_T("GENERIC_WRITE"));
        found = 1;
    }
    if( (grfAccessPermissions & GENERIC_EXECUTE) == GENERIC_EXECUTE)
    { 
        AccessMakeList.push_back(_T("GENERIC_EXECUTE"));
        found = 1;
    }
    if( (grfAccessPermissions & GENERIC_ALL) == GENERIC_ALL)
    { 
        AccessMakeList.push_back(_T("GENERIC_ALL"));
        found = 1;
    }
    if(found == 0)
    {
        AccessMakeList.push_back(_T("UnKnownPermission"));
    }
}
//根据路径检测指定路径的ACL设置
int checkACLsByPathName( TCHAR* pszObjName, ACEBaseMap& ACEBaseLine )
{
    DWORD dwRes = 0;
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS *ea;
    ULONG nent;    ////ace numbers in acl
    DWORD  dwAceIndex = 0;  

    if (NULL == pszObjName) 
    {
        //std::cout << "ERROR_INVALID_PARAMETER" << std::endl;
        return ERROR_INVALID_PARAMETER;
    }
    // Get a pointer to the existing DACL.
    dwRes = GetNamedSecurityInfo(
        pszObjName,                    //
        SE_FILE_OBJECT,                // file or directory
        DACL_SECURITY_INFORMATION,    // The DACL of the object is being referenced.
        NULL, 
        NULL, 
        &pOldDACL, 
        NULL, 
        &pSD
    ); 
    if (ERROR_SUCCESS != dwRes) 
    { 
        //std::cout << "GetNamedSecurityInfo faild: " << dwRes << std::endl;
        return dwRes; 
    }  
    // Get ACL List
    dwRes = GetExplicitEntriesFromAcl(
            pOldDACL,
            &nent,
            &ea
        ); 
    if (ERROR_SUCCESS != dwRes) 
    { 
        //std::cout << "GetExplicitEntriesFromAcl faild" << std::endl;
        return dwRes; 
    } 
    if(nent == 0)
    {
        //std::cout << "get acls faild" << std::endl; 
        return nent;
    }
    //foreach ACLs
    TCHAR AccoutName[128] = {0};
    std::vector<TCHAR*> AccessMakeList;
    for (dwAceIndex = 0; dwAceIndex < nent; dwAceIndex++) 
    { 
        if (ea[dwAceIndex].Trustee.TrusteeForm == TRUSTEE_IS_SID) 
        {    
            //initialize
            memset(AccoutName, 0, sizeof(AccoutName));
            AccessMakeList.clear();

            //conver sid to account name string
            SIDToAccountName(ea[dwAceIndex].Trustee.ptstrName, AccoutName);
            //get account‘s permission MASK
            AccessPermissionsToACCESSMASK(ea[dwAceIndex].grfAccessPermissions, AccessMakeList);
            
            //1. check whether current account is in ACEBaseline
            //ignore UnKnownAccount
            if( lstrcmp(AccoutName, _T("UnKnownAccount")) == 0 )
            {
                continue;
            }
            ACEBaseMap::iterator it = ACEBaseLine.find(AccoutName); 
            if(it == ACEBaseLine.end()) 
            {
                std::wcout << pszObjName << " " << AccoutName << " is no in ACEBaseLine" << std::endl;
            }
            else 
            {
                //3. get account‘s permission ACEBaseline
                std::vector<TCHAR*> permissionACEBaseline = (*it).second;

                //3. ok, we go on check the account‘s AccessMakeList whether is Out of range permissionACEBaseline
                for ( std::vector<TCHAR*>::iterator it = AccessMakeList.begin(); it != AccessMakeList.end(); it++)
                { 
                    TCHAR* permission = (*it);
                    //ignore UnKnownPermission
                    if( lstrcmp(permission, _T("UnKnownPermission")) == 0 )
                    {
                        continue;
                    }
                    //check permission
                    if( find(permissionACEBaseline.begin(), permissionACEBaseline.end(), permission) != permissionACEBaseline.end() )
                    {
                        //ok
                    }
                    else
                    {
                        std::wcout << pszObjName << " " << "AccoutName: " << AccoutName << " " << permission << " is Out of range" << std::endl;
                    } 
                }
            } 
        } 
    }
     
    if(pSD != NULL) 
        LocalFree((HLOCAL) pSD); 
    if(pNewDACL != NULL) 
        LocalFree((HLOCAL) pNewDACL); 

    return dwRes;
}
/*
1. isFileOrDirectory = 1: file
2. isFileOrDirectory = 0: directory
*/
void listFileRecursive(TCHAR* szPath, vector<TCHAR*>& fileList, int isFileOrDirectory )
{ 
    TCHAR szFilePath[MAX_PATH];
    TCHAR szFullPath[MAX_PATH];
    WIN32_FIND_DATA FindFileData;
    HANDLE hListFile; 

    //构造代表子目录和文件夹路径的字符串,使用通配符“*”
    lstrcpy(szFilePath, szPath);
    lstrcat(szFilePath, _T("\\*"));
    //查找第一个文件/目录,获得查找句柄
    hListFile = FindFirstFile(szFilePath, &FindFileData); 
    if(hListFile == INVALID_HANDLE_VALUE)
    { 
        return;
    }
    else
    {        
        do
        {
            memset(szFullPath, 0, sizeof(szFullPath)); 
            // 过滤“.”和“..”,不需要遍历
            if(lstrcmp(FindFileData.cFileName, TEXT(".")) == 0 || lstrcmp(FindFileData.cFileName, TEXT("..")) == 0)
            {
                continue;
            }
            wsprintf(szFullPath, _T("%s\\%s"), szPath, FindFileData.cFileName); 
            TCHAR* newszFullPath = new TCHAR[MAX_PATH];
            lstrcpy(newszFullPath, szFullPath);
             
            //directory
            if(isFileOrDirectory == 0)
            {
                if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 )
                {
                    fileList.push_back(newszFullPath);
                    listFileRecursive(newszFullPath, fileList, isFileOrDirectory );
                }
            }
            else
            { 
                //executable file
                ATL::CString filename = (ATL::CString)FindFileData.cFileName; 
                if( filename.Right(4) == ".exe" || filename.Right(4) == ".vbs" )
                {  
                    fileList.push_back(newszFullPath);
                }
            }
        }
        while(FindNextFile(hListFile, &FindFileData));
    }
    return;
} 
/* converts
"\Device\HarddiskVolume3"                                -> "E:"
"\Device\HarddiskVolume3\Temp"                           -> "E:\Temp"
"\Device\HarddiskVolume3\Temp\transparent.jpeg"          -> "E:\Temp\transparent.jpeg"
"\Device\Harddisk1\DP(1)0-0+6\foto.jpg"                  -> "I:\foto.jpg"
"\Device\TrueCryptVolumeP\Data\Passwords.txt"            -> "P:\Data\Passwords.txt"
"\Device\Floppy0\Autoexec.bat"                           -> "A:\Autoexec.bat"
"\Device\CdRom1\VIDEO_TS\VTS_01_0.VOB"                   -> "H:\VIDEO_TS\VTS_01_0.VOB"
"\Device\Serial1"                                        -> "COM1"
"\Device\USBSER000"                                      -> "COM4"
"\Device\Mup\ComputerName\C$\Boot.ini"                   -> "\\ComputerName\C$\Boot.ini"
"\Device\LanmanRedirector\ComputerName\C$\Boot.ini"      -> "\\ComputerName\C$\Boot.ini"
"\Device\LanmanRedirector\ComputerName\Shares\Dance.m3u" -> "\\ComputerName\Shares\Dance.m3u"
returns an error for any other device type
*/
DWORD GetDosPathFromNtPath(const WCHAR* u16_NTPath, CString* ps_DosPath)
{
    DWORD u32_Error;

    if (_wcsnicmp(u16_NTPath, L"\\Device\\Serial", 14) == 0 || // e.g. "Serial1"
        _wcsnicmp(u16_NTPath, L"\\Device\\UsbSer", 14) == 0)   // e.g. "USBSER000"
    {
        HKEY h_Key; 
        if (u32_Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Hardware\\DeviceMap\\SerialComm", 0, KEY_QUERY_VALUE, &h_Key))
            return u32_Error;

        WCHAR u16_ComPort[50];

        DWORD u32_Type;
        DWORD u32_Size = sizeof(u16_ComPort); 
        if (u32_Error = RegQueryValueEx(h_Key, u16_NTPath, 0, &u32_Type, (BYTE*)u16_ComPort, &u32_Size))
        {
            RegCloseKey(h_Key);
            return ERROR_UNKNOWN_PORT;
        }

        *ps_DosPath = u16_ComPort;
        RegCloseKey(h_Key);
        return 0;
    }

    if (_wcsnicmp(u16_NTPath, L"\\Device\\LanmanRedirector\\", 25) == 0) // Win XP
    {
        *ps_DosPath  = L"\\\\";
        *ps_DosPath += (u16_NTPath + 25);
        return 0;
    }

    if (_wcsnicmp(u16_NTPath, L"\\Device\\Mup\\", 12) == 0) // Win 7
    {
        *ps_DosPath  = L"\\\\";
        *ps_DosPath += (u16_NTPath + 12);
        return 0;
    }

    WCHAR u16_Drives[300];
    GetLogicalDriveStrings(300, u16_Drives);

    WCHAR* u16_Drv = u16_Drives;
    while (u16_Drv[0])
    {
        WCHAR* u16_Next = u16_Drv +wcslen(u16_Drv) +1;

        u16_Drv[2] = 0; // the backslash is not allowed for QueryDosDevice()

        WCHAR u16_NtVolume[1000];
        u16_NtVolume[0] = 0;

        // may return multiple strings!
        // returns very weird strings for network shares
        QueryDosDevice(u16_Drv, u16_NtVolume, sizeof(u16_NtVolume) /2);

        int s32_Len = (int)wcslen(u16_NtVolume);
        if (s32_Len > 0 && _wcsnicmp(u16_NTPath, u16_NtVolume, s32_Len) == 0)
        {
            *ps_DosPath  =  u16_Drv;
            *ps_DosPath += (u16_NTPath + s32_Len);
            return 0;
        }

        u16_Drv = u16_Next;
    }
    return ERROR_BAD_PATHNAME;
}
//system32目录
void initializeSystem32DirACLBaseLine(TCHAR* lpszFullPath, ACLBaseMap& ACLBaseLine)
{
    TCHAR* newszFullPathRoot = new TCHAR[MAX_PATH];
    lstrcpy(newszFullPathRoot, lpszFullPath);

    //1.1: WinBuiltinUsersSid
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinUsersSid")].push_back(_T("READ_CONTROL"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinUsersSid")].push_back(_T("SYNCHRONIZE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_READ"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinUsersSid")].push_back(_T("GENERIC_READ"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinUsersSid")].push_back(_T("GENERIC_EXECUTE"));
    //1.2: WinBuiltinPowerUsersSid
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("DELETE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("READ_CONTROL"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("SYNCHRONIZE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("STANDARD_RIGHTS_READ"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("GENERIC_READ"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("GENERIC_WRITE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinPowerUsersSid")].push_back(_T("GENERIC_EXECUTE"));
    //1.3: WinBuiltinAdministratorsSid
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("DELETE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("READ_CONTROL"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_DAC"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_OWNER")); 
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("SYNCHRONIZE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_READ"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_ALL"));
    ACLBaseLine[newszFullPathRoot][_T("WinBuiltinAdministratorsSid")].push_back(_T("GENERIC_ALL")); 
    //1.4:WinLocalSystemSid
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("DELETE")); 
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("READ_CONTROL"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("WRITE_DAC"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("WRITE_OWNER"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("SYNCHRONIZE"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_READ"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_ALL"));
    ACLBaseLine[newszFullPathRoot][_T("WinLocalSystemSid")].push_back(_T("GENERIC_ALL"));
    //1.5: WinCreatorOwnerSid
    ACLBaseLine[newszFullPathRoot][_T("WinCreatorOwnerSid")].push_back(_T("GENERIC_ALL"));
}
//system32目录下可执行文件
void initializeSystem32SubFileACLBaseLine(TCHAR* lpszFullPath, ACLBaseMap& ACLBaseLine)
{
    TCHAR* path = new TCHAR[MAX_PATH];
    lstrcpy(path, lpszFullPath); 
    vector<TCHAR*> fileList;
    listFileRecursive(path, fileList, 1);
    for ( std::vector<TCHAR*>::iterator it = fileList.begin(); it != fileList.end(); it++)
    {
        TCHAR* newszFullPath = new TCHAR[MAX_PATH];
        newszFullPath = (*it);
        //2.1: WinBuiltinAdministratorsSid
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("DELETE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_DAC")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_OWNER")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_ALL"));  
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("SYNCHRONIZE"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));  
        //2.2:WinLocalSystemSid
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("DELETE")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("WRITE_DAC")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("WRITE_OWNER")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_ALL")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("READ_CONTROL")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("SYNCHRONIZE")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_READ")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_WRITE")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));  
        //2.3: WinBuiltinUsersSid
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("READ_CONTROL"));  
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("SYNCHRONIZE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));  
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
        //2.4: WinInteractiveSid
        ACLBaseLine[newszFullPath][_T("WinInteractiveSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinInteractiveSid")].push_back(_T("SYNCHRONIZE"));
        ACLBaseLine[newszFullPath][_T("WinInteractiveSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinInteractiveSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
        ACLBaseLine[newszFullPath][_T("WinInteractiveSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
        //2.5: WinServiceSid
        ACLBaseLine[newszFullPath][_T("WinServiceSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinServiceSid")].push_back(_T("SYNCHRONIZE"));
        ACLBaseLine[newszFullPath][_T("WinServiceSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinServiceSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
        ACLBaseLine[newszFullPath][_T("WinServiceSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
        //2.6: WinBatchSid
        ACLBaseLine[newszFullPath][_T("WinBatchSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinBatchSid")].push_back(_T("SYNCHRONIZE"));
        ACLBaseLine[newszFullPath][_T("WinBatchSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinBatchSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
        ACLBaseLine[newszFullPath][_T("WinBatchSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
    } 
    //if can not get system32 filelist, ACLBaseline is null
}
//C:\\Documents and Settings\\All Users\\Application Data子目录
void initializeApplicationDataSubDirACLBaseLine(TCHAR* lpszFullPath, ACLBaseMap& ACLBaseLine)
{
    TCHAR* path = new TCHAR[MAX_PATH];
    lstrcpy(path, lpszFullPath);
    vector<TCHAR*> fileList; 
    listFileRecursive(path, fileList, 0);
    for ( std::vector<TCHAR*>::iterator it = fileList.begin(); it != fileList.end(); it++)
    {
        TCHAR* newszFullPath = new TCHAR[MAX_PATH];
        newszFullPath = (*it);

        //1.1: WinBuiltinUsersSid
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("DELETE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("WRITE_DAC")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("WRITE_OWNER")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_ALL"));   
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("SYNCHRONIZE"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));  
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("GENERIC_READ"));  
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("GENERIC_EXECUTE"));  
        //1.2: WinBuiltinAdministratorsSid
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("DELETE"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_DAC"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_OWNER")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("SYNCHRONIZE"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_ALL")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("GENERIC_ALL")); 
        //1.3:WinLocalSystemSid
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("DELETE")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("WRITE_DAC"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("WRITE_OWNER"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("SYNCHRONIZE"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_ALL")); 
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("GENERIC_ALL")); 
        //1.4: WinCreatorOwnerSid 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("GENERIC_ALL")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("DELETE")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("READ_CONTROL")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("WRITE_DAC")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("WRITE_OWNER")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("SYNCHRONIZE")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("STANDARD_RIGHTS_READ")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("STANDARD_RIGHTS_WRITE")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
        ACLBaseLine[newszFullPath][_T("WinCreatorOwnerSid")].push_back(_T("STANDARD_RIGHTS_ALL")); 
        //1.5: WinBuiltinPowerUsersSid
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("DELETE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("READ_CONTROL")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("READ_CONTROL")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("WRITE_DAC")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("WRITE_OWNER")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("SYNCHRONIZE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("STANDARD_RIGHTS_READ")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("STANDARD_RIGHTS_WRITE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinPowerUsersSid")].push_back(_T("STANDARD_RIGHTS_ALL"));  
    } 
}
//web root及其子目录
void initializeWebRootSubDirACLBaseLine(TCHAR* lpszFullPath, ACLBaseMap& ACLBaseLine) 
{
    TCHAR* path = new TCHAR[MAX_PATH];
    lstrcpy(path, lpszFullPath);
    vector<TCHAR*> fileList; 
    listFileRecursive(path, fileList, 0);
    for ( std::vector<TCHAR*>::iterator it = fileList.begin(); it != fileList.end(); it++)
    {
        TCHAR* newszFullPath = new TCHAR[MAX_PATH];
        newszFullPath = (*it);

        //1.1: WinLocalSystemSid
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("DELETE"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("READ_CONTROL"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("WRITE_DAC"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("WRITE_OWNER"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("SYNCHRONIZE"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_READ"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_WRITE"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE"));
        ACLBaseLine[newszFullPath][_T("WinLocalSystemSid")].push_back(_T("STANDARD_RIGHTS_ALL")); 
        //1.2: WinBuiltinAdministratorsSid
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("DELETE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("READ_CONTROL")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_DAC")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_OWNER")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("SYNCHRONIZE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_READ")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_WRITE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_ALL")); 
        //1.3: WinBuiltinUsersSid
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("READ_CONTROL")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("SYNCHRONIZE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_READ")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_WRITE")); 
        ACLBaseLine[newszFullPath][_T("WinBuiltinUsersSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
    }
    return;
}
//mysql plugin目录
void initializeMysqlPluginDirACLBaseLine(TCHAR* lpszFullPath, ACLBaseMap& ACLBaseLine)
{
    TCHAR* newszFullPath = new TCHAR[MAX_PATH];
    lstrcpy(newszFullPath, lpszFullPath);

    //1.1: WinBuiltinAdministratorsSid
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("DELETE")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("READ_CONTROL")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_DAC")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("WRITE_OWNER")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("SYNCHRONIZE")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_REQUIRED")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_READ")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_WRITE")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_EXECUTE")); 
    ACLBaseLine[newszFullPath][_T("WinBuiltinAdministratorsSid")].push_back(_T("STANDARD_RIGHTS_ALL")); 
}
//初始化所有ACL安全基线
void initializeACLBaseLine(ACLBaseMap& ACLBaseLine)
{
    //1. %SystemRoot%/system32/
    TCHAR lpszSystem32FullPath[MAX_PATH];
    GetSystemDirectory(lpszSystem32FullPath, sizeof(lpszSystem32FullPath));
    initializeSystem32DirACLBaseLine(lpszSystem32FullPath, ACLBaseLine);

    //2. %SystemRoot%/system32/xx(xx.exe、xx.vbs)
    initializeSystem32SubFileACLBaseLine(lpszSystem32FullPath, ACLBaseLine);
    
    //3. C:/Documents and Settings/All Users/Application Data/ 
    //4. C:/Documents and Settings/All Users/Application Data/xx(sub directory)  
    TCHAR* lpszApplicationDataFullPath = _T("C:\\Documents and Settings\\All Users\\Application Data");   
    initializeApplicationDataSubDirACLBaseLine(lpszApplicationDataFullPath, ACLBaseLine);  

    //5. web root
    //6. web root/xx(sub directory) 
    ifstream fin("C:\\Program Files (x86)\\Alibaba\\Aegis\\globalcfg\\webpath");  
    if (fin)
    {
        string s;  
        while( fin >> s ) 
        {    
            CString tmp = (CString)s.c_str();   
            initializeWebRootSubDirACLBaseLine((TCHAR*)tmp.GetString(), ACLBaseLine);  
        }
    }
    else
    {
        ifstream fin("C:\\Program Files\\Alibaba\\Aegis\\globalcfg\\webpath");
        string s;  
        while( fin >> s ) 
        {    
            CString tmp = (CString)s.c_str();  
            initializeWebRootSubDirACLBaseLine((TCHAR*)tmp.GetString(), ACLBaseLine);  
        }
    }

    //7. mysql plugin directory
    TCHAR path[_MAX_PATH + 1] = {0};
    int mysqlPid = GetProcessidFromName(_T("mysqld"));
    if(mysqlPid != 0)
    {
        EnableDebugPriv();
        HANDLE h_Process = OpenProcess(
            PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
            FALSE,
            mysqlPid
        );   
        if (h_Process != NULL )  
        {   
            DWORD dRes = GetProcessImageFileName(h_Process, path, MAX_PATH); 
            if( dRes )
            {
                CString* csPath = new CString;
                GetDosPathFromNtPath(path, csPath);
                (*csPath) = (*csPath).Mid(0, (*csPath).ReverseFind(_T(\\)));
                (*csPath).Append(_T("\\..\\lib\\plugin"));
                initializeMysqlPluginDirACLBaseLine((TCHAR*)(*csPath).GetString(), ACLBaseLine); 
            } 
        }   
    } 
    //end initialize
}
//检测本机指定目录的ACL设置在安全基线内
void checkACLsByLoopACLBaseLine( ACLBaseMap& ACLBaseLine )
{
    for ( ACLBaseMap::iterator it = ACLBaseLine.begin(); it != ACLBaseLine.end(); it++)
    {
        ACEBaseMap ACEBaseLine = (*it).second;
        checkACLsByPathName((*it).first, ACEBaseLine);
    }    
    return;
}

..
else if (action == "--windowsAclLeakCheck")
{
    //initialize ACL baseline 
    //std::map<TCHAR*, map<TCHAR*, vector<TCHAR*>, cmp_str>, cmp_str> ACLBaseLine; 
    ACLBaseMap ACLBaseLine;
    initializeACLBaseLine(ACLBaseLine);  
     
    //loop ACLBaseLine, and check all the path
    checkACLsByLoopACLBaseLine(ACLBaseLine); 
}

0x8: 功能 & 兼容性测试

1. windows 7: 测试通过
2. windows server 2003: 测试通过 
3. windows server 2008: 测试通过
4. windows server 2012: 测试通过 

Relevant Link:

Copyright (c) 2015 Little5ann All rights reserved

 

Windows Directory ACL Security Check By ACL Baseline

标签:

原文地址:http://www.cnblogs.com/LittleHann/p/4705880.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!