0%

pikachu靶场通关指南(一)

前言

最近需要找实习了,来Pikachu靶场再复习一下重要类型的漏洞,具体搭建指南网上应有尽有,此处不再赘述。

Burt Force

相关:

安全认证策略:
用户密码设置是否足够复杂

每次认证是否使用安全验证码

对尝试登陆的行为是否进行判断和限制(连续5次错误登陆锁定账号等)

是否采用双因素认证

经验:

暴力破解流程

  • 找到登录接口的脆弱性
    • 尝试登录—抓包—观察验证元素和response,判断是否可以暴力破解
  • 优化字典
  • 自动化工具

生成高效字典

  • 比如常用的用户名/密码TOP500
  • 脱裤后的账号密码(社工库)
  • 根据特定的对象(比如手机、生日和银行卡号等)按照指定的规则来生成密码

字典优化技巧

  • 根据注册提示进行优化,如注册要求密码8位以上,就去掉少于8位的密码
  • 爆破管理后台时,账号是 admin / administrator / root 的可能性较高

验证码绕过(on server)服务器

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
if(isset($_POST['submit'])) {
if (empty($_POST['username'])) {
$html .= "<p class='notice'>用户名不能为空</p>";
} else {
if (empty($_POST['password'])) {
$html .= "<p class='notice'>密码不能为空</p>";
} else {
if (empty($_POST['vcode'])) {
$html .= "<p class='notice'>验证码不能为空哦!</p>";
} else {
// 验证验证码是否正确
if (strtolower($_POST['vcode']) != strtolower($_SESSION['vcode'])) {
$html .= "<p class='notice'>验证码输入错误哦!</p>";
//应该在验证完成后,销毁该$_SESSION['vcode']
}else{

$username = $_POST['username'];
$password = $_POST['password'];
$vcode = $_POST['vcode'];

$sql = "select * from users where username=? and password=md5(?)";
$line_pre = $link->prepare($sql);

$line_pre->bind_param('ss',$username,$password);

if($line_pre->execute()){
$line_pre->store_result();
//虽然前面做了为空判断,但最后,却没有验证验证码!!!
if($line_pre->num_rows()==1){
$html.='<p> login success</p>';
}else{
$html.= '<p> username or password is not exists~</p>';
}
}else{
$html.= '<p>执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'</p>';
}
}
}
}
}
}

源码中比较完验证码后,并没有销毁该验证码。所以猜测验证码一直有效,可以不停重放数据包。

所以可以通过验证码重放,来绕过验证码爆破用户民共和密码。

成功爆破出目前pikachu的用户及密码

验证码绕过(on client)服务器

可以看到用js生成随机字符作为验证码候选,然后创建验证码并进行验证。所以在本案例下,可利用知道用户名或密码的前提下,可以对另一个参数进行暴力枚举。

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
<script language="javascript" type="text/javascript">
var code; //在全局 定义验证码
function createCode() {
code = "";
var codeLength = 5;//验证码的长度
var checkCode = document.getElementById("checkCode");
var selectChar = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');//所有候选组成验证码的字符,当然也可以用中文的

for (var i = 0; i < codeLength; i++) {
var charIndex = Math.floor(Math.random() * 36);
code += selectChar[charIndex];
}
//alert(code);
if (checkCode) {
checkCode.className = "code";
checkCode.value = code;
}
}

function validate() {
var inputCode = document.querySelector('#bf_client .vcode').value;
if (inputCode.length <= 0) {
alert("请输入验证码!");
return false;
} else if (inputCode != code) {
alert("验证码输入错误!");
createCode();//刷新验证码
return false;
}
else {
return true;
}
}


createCode();
</script>

Token防爆破

抓包发现有 token

Repeater后可以看到返回包里有新的 token,即下一次登陆要使用的 token 值在此次登陆的返回包里,而且是明文传输,所以爆破时一定是单线程。

intruder模块:设置Grep Extract

设置线程为1

添加返回包里的 token 值,有效载荷选递归搜索

成功爆破

XSS

对XSS的熟悉程度取决于对浏览器机制和HTML、JS的了解程度。这部分涉及内容较多,需要多加练习。

反射型XSS(get)

比较好绕过,F12更改输入框maxlength,或者直接在URL中补全</script>即可。js代码正确即可被浏览器执行。

反射型XSS(post)

此处同上,只不过URL不显示

存储型XSS

注入语句会写入数据库中,每次进入都会执行

同上

DOM型XSS

DOM: Document Object Model文档对象模型,DOM型XSS是一种特殊类型的反射型XSS。

当网页到达浏览器,浏览器会为网页创建一个Document object文档对象,然后生成各个子文档对象,其中每个页面元素对应一个文档对象,每个文档对象包含属性、方法和事件。

我们可以通过JS脚本对文档对象进行编辑从而修改页面的元素。客户端脚本程序可以通过DOM来动态修改页面内容,客户端获取DOM中的数据并在本地执行。基于此,JS脚本就可以用来实现XSS。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="xssd_main">
<script>
function domxss(){
var str = document.getElementById("text").value;
document.getElementById("dom").innerHTML = "<a href='"+str+"'>what do you see?</a>";
}
//试试:'><img src="#" onmouseover="alert('xss')">
//试试:' onclick="alert('xss')">,闭合掉就行
</script>
<!--<a href="" onclick=('xss')>-->
<input id="text" name="text" type="text" value="" />
<input id="button" type="button" value="click me!" onclick="domxss()" />
<div id="dom"></div>
</div>

通过 getElementById 获取到了标签 Id 为 text的内容赋值给str

然后又把 str 的内容通过字符串拼接的方式写到了 a 标签的 href 属性中,而a标签会写到Id 为 dom的 div 标签中。

因此通过闭合的方式构造Payload

1
' onclick=alert("xss")>

DOM型XSS不经过后台交互,前端输入被DOM给获取,通过DOM又在前端输出

DOM型XSS-X

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="xssd_main">
<script>
function domxss(){
var str = window.location.search;
var txss = decodeURIComponent(str.split("text=")[1]);
var xss = txss.replace(/\+/g,' ');
// alert(xss);

document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
}
//试试:'><img src="#" onmouseover="alert('xss')">
//试试:' onclick="alert('xss')">,闭合掉就行
</script>
<!--<a href="" onclick=('xss')>-->
<form method="get">
<input id="text" name="text" type="text" value="" />
<input id="submit" type="submit" value="请说出你的伤心往事"/>
</form>
<div id="dom"></div>
</div>

首先定义一个domxss函数:

利用 window.location.search 获取浏览器中URL的内容,然后赋值给 str

然后经过URL解码和字符串分隔,取出URL中的参数内容;

把 “+” 替换为 “ ”(空格),赋值给 xss;

把 xss 拼接到 a 标签中,然后写到 Id 为 dom 的 div 标签中。

与之前DOM不同的是,它的输入是从浏览器的URL中获取的,很像反射型XSS(get)

构造的Payload同上

1
' onclick=alert("xss")>

XSS之盲打

为攻击场景,输入的内容不会在当前输出,而是提交到后台。若输入一串js,管理员登录后台管理界面,后台会输出我们提交的内容

输入常见xss一句话,登陆管理员界面即可看到一登陆进来就遭受攻击。

XSS之过滤

常见xss一句话输入,被后台过滤,大小写即可绕过。也可用<img src=x onerror=alert(‘xss’)>。

实际场景中,或多或少都会有过滤,但是有些逻辑不严谨,也可被绕过。

绕过思路:

  • 前端限制绕过:直接抓包重放,或修改html前端代码。如反射型XSS(get)中限制输入20个字符。
  • 大小写:比如
  • 双写:<script>。针对后台把
你想在文章末尾对读者说的话