Go-Database

1. 数据库的基本操作

GO官方教程:https://golang.google.cn/doc/tutorial/database-access

MongoDB

安装镜像:

sudo docker pull mongo

运行一个mongo容器,端口映射直接使用mongo的默认端口:

docker run --name AMongo -p 27017:27017 mongo

运行客户端,与前一个容器连接:

docker run -it --link AMongo:mongo --rm mongo sh -c 'exec mongo "172.17.0.2:27017/store"'

执行命令:

>db.transactions.insert([
  {
    "ccnum": "4444333322221111",
    "date": "2019-01-05",
    "amount": 100.12,
    "cvv": "1234",
    "exp": "09/2020"
  },
  {
    "ccnum": "4444123456789012",
    "date": "2019-01-07",
    "amount": 2400.18,
    "cvv": "5544",
    "exp": "02/2021"
  },
  {
    "ccnum": "4465122334455667",
    "date": "2019-01-29",
    "amount": 1450.87,
    "cvv": "9876",
    "exp": "06/2020"
  }
]);


> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
store   0.000GB
> use store
switched to db store
> db.transactions.find()
{ "_id" : ObjectId("621b2859e0ecbb07b4acdd37"), "ccnum" : "4444333322221111", "date" : "2019-01-05", "amount" : 100.12, "cvv" : "1234", "exp" : "09/2020" }
{ "_id" : ObjectId("621b2859e0ecbb07b4acdd38"), "ccnum" : "4444123456789012", "date" : "2019-01-07", "amount" : 2400.18, "cvv" : "5544", "exp" : "02/2021" }
{ "_id" : ObjectId("621b2859e0ecbb07b4acdd39"), "ccnum" : "4465122334455667", "date" : "2019-01-29", "amount" : 1450.87, "cvv" : "9876", "exp" : "06/2020" }

go语言查询需要先下载依赖库:

go get gopkg.in/mgo.v2

连接测试:

package main

import (
	"fmt"
	"log"

	mgo "gopkg.in/mgo.v2"
)

type Transaction struct {
	CCNum      string  `bson:"ccnum"`
	Date       string  `bson:"date"`
	Amount     float32 `bson:"amount"`
	Cvv        string  `bson:"cvv"`
	Expiration string  `bson:"exp"`
}

func main() {
	// 1. connect to mongo db
	session, err := mgo.Dial("127.0.0.1")
	if err != nil {
		log.Panicln(err)
	}
	defer session.Close()

	// 2. query
	results := make([]Transaction, 0)
	if err := session.DB("store").C("transactions").Find(nil).All(&results); err != nil {
		log.Panicln(err)
	}

	// 3. output
	for _, txn := range results {
		fmt.Println(txn.CCNum, txn.Date, txn.Amount, txn.Cvv, txn.Expiration)
	}
}

2. 数据库矿工

接下来写一个工具,检查数据库的列名等信息,判断是否为密码、hash等敏感信息,然后窃取。

接口

因为数据库种类很多,所以先创建接口,定义基本的库、表、列结构,以及方法。

type DatabaseMiner interface {
	GetSchema() (*Schema, error)
}

type Schema struct {
	Databases []Database
}

type Database struct {
	Name   string
	Tables []Table
}

type Table struct {
	Name    string
	Columns []string
}

func getRegex() []*regexp.Regexp {
	return []*regexp.Regexp{ // ignore case
		regexp.MustCompile(`(?i)social`),
		regexp.MustCompile(`(?i)ssn`),
		regexp.MustCompile(`(?i)pass(word)?`),
		regexp.MustCompile(`(?i)hash`),
		regexp.MustCompile(`(?i)ccnum`),
		regexp.MustCompile(`(?i)card`),
		regexp.MustCompile(`(?i)security`),
		regexp.MustCompile(`(?i)key`),
	}
}

func Search(m DatabaseMiner) error {
	schema, err := m.GetSchema()
	if err != nil {
		return err
	}

	re := getRegex()
	for _, database := range schema.Databases {
		for _, table := range database.Tables {
			for _, field := range table.Columns {
				for _, r := range re {
					if r.MatchString(field) {
						fmt.Println(database)
						fmt.Printf("[+] HIT: %s\n", field)
					}
				}
			}
		}
	}
	return nil
}

最终的实现是3层遍历:

  1. 遍历数据库;
  2. 遍历表;
  3. 获取一条数据,遍历列名。

MongoDB miner

package main

import (
	"flag"
	"fmt"

	"github.com/blackhat-go/bhg/ch-7/db/dbminer"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson" // binary json
)

type MongoMiner struct {
	Host    string
	session *mgo.Session
}

func (m *MongoMiner) connect() error {
	s, err := mgo.Dial(m.Host)
	if err != nil {
		return err
	}
	m.session = s
	return nil
}

func (m *MongoMiner) GetSchema() (*dbminer.Schema, error) {
	var schema = new(dbminer.Schema)

	// 1. get databases
	dbnames, err := m.session.DatabaseNames()
	if err != nil {
		return nil, err
	}

	// 2. get collections of each database
	for _, dbname := range dbnames {
		var defaultDbs = [3]string{"admin", "config", "local"}
		var bContinue = false
		for _, defaultDb := range defaultDbs {
			if dbname == defaultDb {
				bContinue = true
				break
			}
		}
		if bContinue {
			continue
		}

		db := dbminer.Database{Name: dbname, Tables: []dbminer.Table{}}
		fmt.Printf("find db:%s\n", dbname)
		collections, err := m.session.DB(dbname).CollectionNames()
		if err != nil {
			return nil, err
		}

		// 3. get docs of each collection
		for _, collection := range collections {
			table := dbminer.Table{Name: collection, Columns: []string{}}
			fmt.Printf("find collection:%s\n", collection)

			// query one doc
			var docRaw bson.Raw
			err := m.session.DB(dbname).C(collection).Find(nil).One(&docRaw)
			if err != nil {
				return nil, err
			}

			var doc bson.RawD
			if err := docRaw.Unmarshal(&doc); err != nil {
				if err != nil {
					return nil, err
				}
			}

			// 4. get column names of the doc
			for _, col := range doc {
				fmt.Printf("find column:%s\n", col.Name)
				table.Columns = append(table.Columns, col.Name)
			}
			db.Tables = append(db.Tables, table)
		}
		schema.Databases = append(schema.Databases, db)
	}
	return schema, nil
}

func NewMiner(host string) (*MongoMiner, error) {
	m := MongoMiner{Host: host}
	err := m.connect()
	if err != nil {
		return nil, err
	}
	return &m, nil
}

func main() {
	var (
		pStrFlagHost = flag.String("host", "", "The host ip of MongoDB.")
		// pStrFlagPort = flag.String("port", "", "The port of MongoDB.") 27017 default
	)
	flag.Parse()
	fmt.Printf("host:%s\n", *pStrFlagHost)
	mm, err := NewMiner(*pStrFlagHost)
	if err != nil {
		panic(err)
	}
	fmt.Printf("NewMiner ok\n")
	if err := dbminer.Search(mm); err != nil {
		panic(err)
	}
}

运行:

sudo go run db/db/mongo/main.go -host 127.0.0.1
host:127.0.0.1
NewMiner ok
find db:store
find collection:transactions
find column:_id
find column:ccnum
find column:date
find column:amount
find column:cvv
find column:exp
[DB] = store
    [TABLE] = transactions
       [COL] = _id
       [COL] = ccnum
       [COL] = date
       [COL] = amount
       [COL] = cvv
       [COL] = exp

[+] HIT: ccnum

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值