Skip to content

Latest commit

 

History

History

werk

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

RuCTF 2023 | werk

Description

The service is pretty simple: it allows users to register and get registration info.

User's field payment-info is exposed as attack data.

Vulnerability

User's access token is generated by standard math/rand generator, using the creation timestamp as a seed:

var alpha = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")

func RandomString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = alpha[rand.Intn(len(alpha))]
	}
	return string(b)
}

// ...

rand.Seed(time.Now().UnixMilli())

salt := RandomString(20)

return GetBaseHash(username + salt)

The username could be taken from checksystem as public flag_id. So we need to brutforce the salt.

Example sploit: werk.sploit.go

Unfortunately, we've made a mistake: the salt space is too large, and simple bruteforcing would take very long time. There are around 60_000 possible salts for every round, so we need to reduce the search space somehow.

One of possible solutions, found by C4T BuT S4D team, is using checksystem as a side-channel. The checksystem exposes flag_id just after it was generated, so we could continiously download flag_ids and monitor its changes. If there is new flag_id in checksystem, it means that this flag_id was generated between two consecutive checks, so we have a small interval of time which need to be bruteforced.

If we ask the checksystem every N seconds, the search space is reduces to 60_000 / N. For example, if we ask checksystem every second, we only need to bruteforce 1000 salts per minute (~17 RPS). Since the service is written in Go, it is fast enough to handle the bruteforce.

Fix

Just shuffle letters in the alphabet, then salts become unpredictable from the attacker side:

var alpha = []rune("m7pewEK6iIQL0kVxbD2rovAqZsdJgGXcT89a5tYzhBOPClRSW3MyjfF1HNn4Uu")

Conclusion

While the service has the solution, it was tested very bad before the game. We are very sorry for that. We will test our services better next time.