CSRF(Cross Site Request Forgery)

跨站请求伪造,

Low

cs-l

$_GET 变量:预定义的 $_GET 变量用于收集来自 method=”get” 的表单中的值。$_GET 变量是一个数组,内容是由 HTTP GET 方法发送的变量名称和值。可在url中直接设置

"UPDATE users SET password = '$pass_new' WHERE user = '" . $current_user . "';"$current_user变量直接插入到查询语句中。

Attack:

/?password_new=1&password_conf=1&Change=1

Medium

cs-m.

stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false:检查 HTTP_REFERER 是否包含 SERVER_NAME。如果包含(即 stripos 返回的不是 false

$_SERVER[ ‘HTTP_REFERER’ ]->referer

$_SERVER[ ‘SERVER_NAME’ ])->host

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

$change = false;
$request_type = "html";
$return_message = "Request Failed";

if ($_SERVER['REQUEST_METHOD'] == "POST" && array_key_exists ("CONTENT_TYPE", $_SERVER) && $_SERVER['CONTENT_TYPE'] == "application/json")
{
$data = json_decode(file_get_contents('php://input'), true);
$request_type = "json";
if (array_key_exists("HTTP_USER_TOKEN", $_SERVER) &&
array_key_exists("password_new", $data) &&
array_key_exists("password_conf", $data) &&
array_key_exists("Change", $data)) {
$token = $_SERVER['HTTP_USER_TOKEN'];
$pass_new = $data["password_new"];
$pass_conf = $data["password_conf"];
$change = true;
}
} else
{
if (array_key_exists("user_token", $_REQUEST) &&
array_key_exists("password_new", $_REQUEST) &&
array_key_exists("password_conf", $_REQUEST) &&
array_key_exists("Change", $_REQUEST))
{
$token = $_REQUEST["user_token"];
$pass_new = $_REQUEST["password_new"];
$pass_conf = $_REQUEST["password_conf"];
$change = true;
}
}

if ($change) {
// Check Anti-CSRF token
checkToken( $token, $_SESSION[ 'session_token' ], 'index.php' );

// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = mysqli_real_escape_string ($GLOBALS["___mysqli_ston"], $pass_new);
$pass_new = md5( $pass_new );

// Update the database
$current_user = dvwaCurrentUser();
$insert = "UPDATE `users` SET password = '" . $pass_new . "' WHERE user = '" . $current_user . "';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $insert );

// Feedback for the user
$return_message = "Password Changed.";
}
else {
// Issue with passwords matching
$return_message = "Passwords did not match.";
}

mysqli_close($GLOBALS["___mysqli_ston"]);

if ($request_type == "json")
{
generateSessionToken();
header ("Content-Type: application/json");
print json_encode (array("Message" =>$return_message));
exit;
} else
{
echo "<pre>" . $return_message . "</pre>";
}
}

// Generate Anti-CSRF token
generateSessionToken();

?>

添加功能:处理接受json信息;检验token(一次一换,随机生成)

  1. array_key_exists ("CONTENT_TYPE", $_SERVER)

$_SERVER超级全局数组,包含关于头信息、路径和脚本位置的信息。

  1. $_SERVER['CONTENT_TYPE'] == "application/json"传入请求的内容类型是否为JSON。

  2. $data = json_decode(file_get_contents('php://input'), true);

使用file_get_contents('php://input')读取请求体中的原始POST数据,并将JSON数据解码为PHP数组。参数true表示结果数据应该是一个关联数组。

  1. array_key_exists("user_token", $_REQUEST)

    $_REQUEST数组包含来自$_GET$_POST$_COOKIE的数据。

  2. header ("Content-Type: application/json");设置响应的内容类型为application/json

  3. `print json_encode (array(“Message” =>$return_message));``

$return_message变量编码为JSON格式的字符串并打印。

Impossible

cs-im

add:验证旧密码

PDO::PARAM_STR:这是绑定参数的类型。在这里,它表示参数类型是字符串(PDO::PARAM_STR)。

其他

  1. ftp与命令行了解 ftp> bye

  2. SameSite

    SameSite=None:允许Cookie在所有上下文中发送,包括跨站请求。需要设置Secure属性。

    SameSite=Lax:允许Cookie在顶级导航和第三方网站发起的GET请求时发送,在安全性和可用性之间取得平衡。

    SameSite=Strict:Cookie只在同站请求时发送

1
2
3
4
5
6
7
8
9
setcookie("exampleCookie", "value", [
'expires' => time() + 3600, // 1小时
'path' => '/',
'domain' => 'example.com',
'secure' => true, // 确保Cookie仅通过HTTPS发送
'httponly' => true, // Cookie仅通过HTTP协议访问
'samesite' => 'Strict' // 仅限同站请求发送Cookie
]);