Skip to content

Commit

Permalink
feat(veinmind-weakpass): support caching_sha2_password and enhance My…
Browse files Browse the repository at this point in the history
…ISAM pkg (chaitin#235)
  • Loading branch information
asjdf authored and DVKunion committed May 23, 2023
1 parent 8ff7842 commit a21f9ff
Show file tree
Hide file tree
Showing 14 changed files with 439 additions and 97 deletions.
3 changes: 1 addition & 2 deletions plugins/go/veinmind-escalate/pkg/priv.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package pkg
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
Expand Down Expand Up @@ -172,7 +171,7 @@ func isPrivileged(container api.Container) bool {
return false
}

status, err := ioutil.ReadFile(filepath.Join(func() string {
status, err := os.ReadFile(filepath.Join(func() string {
fs := os.Getenv("LIBVEINMIND_HOST_ROOTFS")
if fs == "" {
return "/"
Expand Down
1 change: 1 addition & 0 deletions plugins/go/veinmind-malicious/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/chaitin/libveinmind v1.5.6
github.com/chaitin/veinmind-common-go v1.4.2
github.com/joho/godotenv v1.4.0
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/testwill/go-clamd v1.0.0
gorm.io/driver/sqlite v1.4.4
gorm.io/gorm v1.24.3
Expand Down
7 changes: 5 additions & 2 deletions plugins/go/veinmind-malicious/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -697,11 +697,13 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
Expand Down Expand Up @@ -1275,6 +1277,7 @@ golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
4 changes: 3 additions & 1 deletion plugins/go/veinmind-weakpass/hash/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package hash
// All 注册所有的hash方法 service模块可以通过hash的ID获取具体的hash实例
var All = []Hash{
&Plain{},
&MysqlNative{},
&MySQL{},
&MysqlNative{}, // This is the one we want to remove
&CachingSha2Password{}, // This is the one we want to remove
&Shadow{},
}
6 changes: 3 additions & 3 deletions plugins/go/veinmind-weakpass/hash/base.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package hash

type Hash interface {
// Match 密码匹配方式
Match(hash, guess string) (flag bool, err error)

// ID 加密算法的ID
ID() string

// Match 密码匹配方式
Match(hash, guess string) (flag bool, err error)
}
22 changes: 21 additions & 1 deletion plugins/go/veinmind-weakpass/hash/hash_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
package hash

import (
"encoding/base64"
"testing"

"github.com/stretchr/testify/assert"
)

func TestHashMysqlNativePassword_Hash(t *testing.T) {
func TestHashMysqlNative(t *testing.T) {
mysqlNative := &MysqlNative{}
// password which got from file mysql.ibd in docker image
stringGotFromFile := "*6bb4837eb74329105ee4568dda7dc67ed2ca2ad9"
stringInDict := "123456"
find, _ := mysqlNative.Match(stringGotFromFile, stringInDict)
assert.True(t, find)

stringGotFromFile = "6bb4837eb74329105ee4568dda7dc67ed2ca2ad9"
find, _ = mysqlNative.Match(stringGotFromFile, stringInDict)
assert.False(t, find)
}

func TestHashCachingSha2Password(t *testing.T) {
cachingSha2Password := &CachingSha2Password{}
// password which got from file mysql.ibd in docker image
b64PwdFromFile := "JEEkMDA1JFodUGBzOkJlVwx/bwRYfwg8f3hoV3ZxRUN3c3JGa3pwa0kuVWxXbEpSeEM1ZkVYVUhscU42WFVuaGpHTS5zNwFixZPBAQICRkAAAAAgfAAAOPokJQ=="
stringInDict := "123456"
pwd, err := base64.StdEncoding.DecodeString(b64PwdFromFile)
if err != nil {
t.Fatal(err)
}
find, _ := cachingSha2Password.Match(string(pwd), stringInDict)
assert.True(t, find)
find, _ = cachingSha2Password.Match(string(pwd), "12345678")
assert.False(t, find)
}

func TestHashShadow(t *testing.T) {
Expand Down
213 changes: 213 additions & 0 deletions plugins/go/veinmind-weakpass/hash/mysql_native_password.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
package hash

import (
"bytes"
"crypto/sha1"
"crypto/sha256"
"errors"
"fmt"
"strconv"
"strings"
)

var _ Hash = (*MySQL)(nil)

type MySQL struct {
}

func (m *MySQL) ID() string {
return "mysql"
}

func (m *MySQL) Match(hash, guess string) (flag bool, err error) {
var checker Hash
if len(hash) > 3 && hash[:3] == "$A$" {
checker = &CachingSha2Password{}
} else {
checker = &MysqlNative{}
}
return checker.Match(hash, guess)
}

var _ Hash = (*MysqlNative)(nil)

type MysqlNative struct {
}

Expand All @@ -25,3 +49,192 @@ func (i *MysqlNative) Match(hash, guess string) (flag bool, err error) {
}
return false, errors.New("mysql_passwd: malformed entry ")
}

var _ Hash = (*CachingSha2Password)(nil)

type CachingSha2Password struct {
}

func (i *CachingSha2Password) ID() string {
return "caching_sha2_password"
}

func (i *CachingSha2Password) Match(hash, guess string) (flag bool, err error) {
if hash[:3] == "$A$" {
return checkHashingPassword([]byte(hash[:70]), guess)
}
return false, errors.New("mysql_passwd: malformed entry ")
}

const (
// MIXCHARS is the number of characters to use in the mix
MIXCHARS = 32
// SALT_LENGTH is the length of the salt
SALT_LENGTH = 20 //nolint: revive
// ITERATION_MULTIPLIER is the number of iterations to use
ITERATION_MULTIPLIER = 1000 //nolint: revive
)

func b64From24bit(b []byte, n int, buf *bytes.Buffer) {
b64t := []byte("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")

w := (int64(b[0]) << 16) | (int64(b[1]) << 8) | int64(b[2])
for n > 0 {
n--
buf.WriteByte(b64t[w&0x3f])
w >>= 6
}
}

// sha256Hash is an util function to calculate sha256 hash.
func sha256Hash(input []byte) []byte {
res := sha256.Sum256(input)
return res[:]
}

// 'hash' function should return an array with 32 bytes, the same as SHA-256
// From https://github.com/pingcap/tidb/blob/ff78940594893cb970df58000dbc69cd5631e696/parser/auth/caching_sha2.go#L72 with some fix
func hashCrypt(plaintext string, salt []byte, iterations int, hash func([]byte) []byte) string {
// Numbers in the comments refer to the description of the algorithm on https://www.akkadia.org/drepper/SHA-crypt.txt

// 1, 2, 3
bufA := bytes.NewBuffer(make([]byte, 0, 4096))
bufA.Write([]byte(plaintext))
bufA.Write(salt)

// 4, 5, 6, 7, 8
bufB := bytes.NewBuffer(make([]byte, 0, 4096))
bufB.Write([]byte(plaintext))
bufB.Write(salt)
bufB.Write([]byte(plaintext))
sumB := hash(bufB.Bytes())
bufB.Reset()

// 9, 10
var i int
for i = len(plaintext); i > MIXCHARS; i -= MIXCHARS {
bufA.Write(sumB[:MIXCHARS])
}
bufA.Write(sumB[:i])

// 11
for i = len(plaintext); i > 0; i >>= 1 {
if i%2 == 0 {
bufA.Write([]byte(plaintext))
} else {
bufA.Write(sumB[:])
}
}

// 12
sumA := hash(bufA.Bytes())
bufA.Reset()

// 13, 14, 15
bufDP := bufA
for range []byte(plaintext) {
bufDP.Write([]byte(plaintext))
}
sumDP := hash(bufDP.Bytes())
bufDP.Reset()

// 16
p := make([]byte, 0, sha256.Size)
for i = len(plaintext); i > 0; i -= MIXCHARS {
if i > MIXCHARS {
p = append(p, sumDP[:]...)
} else {
p = append(p, sumDP[0:i]...)
}
}

// 17, 18, 19
bufDS := bufA
for i = 0; i < 16+int(sumA[0]); i++ {
bufDS.Write(salt)
}
sumDS := hash(bufDS.Bytes())
bufDS.Reset()

// 20
s := make([]byte, 0, 32)
for i = len(salt); i > 0; i -= MIXCHARS {
if i > MIXCHARS {
s = append(s, sumDS[:]...)
} else {
s = append(s, sumDS[0:i]...)
}
}

// 21
bufC := bufA
var sumC []byte
for i = 0; i < iterations; i++ {
bufC.Reset()
if i&1 != 0 {
bufC.Write(p)
} else {
bufC.Write(sumA[:])
}
if i%3 != 0 {
bufC.Write(s)
}
if i%7 != 0 {
bufC.Write(p)
}
if i&1 != 0 {
bufC.Write(sumA[:])
} else {
bufC.Write(p)
}
sumC = hash(bufC.Bytes())
sumA = sumC
}

// 22
buf := bytes.NewBuffer(make([]byte, 0, 100))
buf.Write([]byte{'$', 'A', '$'})
rounds := fmt.Sprintf("%03X", iterations/ITERATION_MULTIPLIER)
buf.Write([]byte(rounds))
buf.Write([]byte{'$'})
buf.Write(salt)

b64From24bit([]byte{sumC[0], sumC[10], sumC[20]}, 4, buf)
b64From24bit([]byte{sumC[21], sumC[1], sumC[11]}, 4, buf)
b64From24bit([]byte{sumC[12], sumC[22], sumC[2]}, 4, buf)
b64From24bit([]byte{sumC[3], sumC[13], sumC[23]}, 4, buf)
b64From24bit([]byte{sumC[24], sumC[4], sumC[14]}, 4, buf)
b64From24bit([]byte{sumC[15], sumC[25], sumC[5]}, 4, buf)
b64From24bit([]byte{sumC[6], sumC[16], sumC[26]}, 4, buf)
b64From24bit([]byte{sumC[27], sumC[7], sumC[17]}, 4, buf)
b64From24bit([]byte{sumC[18], sumC[28], sumC[8]}, 4, buf)
b64From24bit([]byte{sumC[9], sumC[19], sumC[29]}, 4, buf)
b64From24bit([]byte{0, sumC[31], sumC[30]}, 3, buf)

return buf.String()
}

// checkHashingPassword checks if a caching_sha2_password or tidb_sm3_password authentication string matches a password
// From https://github.com/pingcap/tidb/blob/ff78940594893cb970df58000dbc69cd5631e696/parser/auth/caching_sha2.go#L223 with some fix
func checkHashingPassword(pwHash []byte, password string) (bool, error) {
pwHashParts := bytes.Split(pwHash, []byte("$"))
if len(pwHashParts) < 3 {
return false, errors.New("failed to decode hash parts")
}

hashType := string(pwHashParts[1])
if hashType != "A" {
return false, errors.New("digest type is incompatible")
}

iterations, err := strconv.ParseInt(string(pwHashParts[2]), 16, 64)
if err != nil {
return false, errors.New("failed to decode iterations")
}
iterations = iterations * ITERATION_MULTIPLIER
salt := pwHashParts[3][:SALT_LENGTH]

newHash := hashCrypt(password, salt, int(iterations), sha256Hash)

return bytes.Equal(pwHash, []byte(newHash)), nil
}
32 changes: 32 additions & 0 deletions plugins/go/veinmind-weakpass/hash/passwd_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package hash

import (
"errors"
)

// PasswordMethod represents the entryption method.
type PasswordMethod uint8

// Password represents the data field inside.
type Password struct {
// Method of current password.
Method PasswordMethod

// MethodString of the current password.
MethodString string

// Salt inside the password.
Salt string

// Hash hased value of the password.
Hash string
}

func (pw *Password) Match(guesses []string) (string, bool) {
panic("not implemented")
return "", false
}

func ParsePassword(pass *Password, phrase string) error {
return errors.New("not implemented")
}
Loading

0 comments on commit a21f9ff

Please sign in to comment.