카테고리 없음

파이썬 랜덤 어택

진모씨 2014. 1. 13. 13:20

파이썬의 랜덤 함수 중 random.Random().getrandbits 를 쓸 때는 주의해야 될거에요.

일단 '32의 배수' 단위로 쓰지 마세요.

그리고 31, 30 등 32보다 약간 작은 숫자도 쓰지 마세요.


파이썬의 랜덤 함수 구조는 이래요.

메르센 트위스트 라고도 하는데, 그 구조를 이용해요.


624번 어떤 랜덤 테이블을 쓰는데, 이를 state라고 불러요.

http://svn.python.org/view/python/trunk/Modules/_randommodule.c?view=markup

소스를 참고하면 알 수 있어요.


getrandbits 함수는 genrand_int32 라는 함수로 32비트 단위로 숫자를 불러와요.

만약 getrandbits(32)를 쓴다면.. :( 그 수가 그대로 나오네요!


genrand_int32는 이렇게 리턴해요.

    y = mt[self->index++];
    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680UL;
    y ^= (y << 15) & 0xefc60000UL;
    y ^= (y >> 18);
    return y;


네, y를 구할 수 있겠죠?

mt가 저희가 볼수도 있고 지정할 수도 있는 state값이에요.

getstate, setstate로 불러오고 지정할 수 있어요.


소스를 보다 보면, 처음에 랜덤 함수를 호출하고 그 다음 624번 getrandbits(32)를 자신이 호출한다면 state값을 알아낼 수 있다는 것을 알 수 있어요.

물론 64도 마찬가지겠죠? 분리하면 되거든요.

그래서 이 값을 getrandbits에서 리틀 엔디안 형식으로 저장해요.

그 다음 그걸 정수로 만들죠.


그러니 그러지 마셔요!

이 문제가 30c3 ctf guess 라는 100점짜리 문제로 나왔는데, 구글에 'python getrandbits attack' 이라고 치면 나올거에요.


별개로, random 함수는 6~7번 오른쪽으로 시프트한 값을 실수연산해서 쓰기 때문에 공격이 잘 될지는 모르겠네요, 대신 브루트포스 범위가 엄청 줄어들긴 하겠죠.