-
Fuzzer는 미래가 있을까?ETC 2021. 3. 19. 00:40
퍼저를 써서 버그를 찾을 수 있을까?
최근 여러 종류의 Fuzzer가 쏟아져 나오고 있고 각 툴의 README.md 파일을 보면 여러 CVE 번호가 나열되어있다. 이를 보면 최신 퍼저들도 나름 선방하고 있는 듯 하다. 어마어마한 자원을 쓰는 구글의 클러스터 퍼저를, 큰 자원을 들이지 않고 선방한다는 것은 대단한 일이라고 생각한다.
구글이 퍼징에 이만한 자원을 투자한다는 것은 그만큼 퍼징이 버그를 찾는데 실용성이 있다는 반증아닐까? 그렇지 않았으면 막대한 자원들을 굳이 퍼저에 쏟지 않았을 테니까. 물론, 그렇게 무시무시한 자원을 투입하면 거의 전수조사에 가까운 수준이 아니냐, 버그를 못찾는게 이상하지 않느냐 반문한다면, 나 역시 공감한다.
결국, 우리는 버그를 찾으려고 퍼저를 쓴다. 그렇다면 퍼저를 쓰려는 사람들에게 있어서 가장 중요한 질문은, "이런 각박한 상황에서 나는 퍼저를 써서 버그를 찾을 수 있을까?"일 것이다. 구글뿐만 아니라 다른 회사, 개인들도 많은 자원을 투자해 퍼징을 돌리고 있을텐데, 같은 퍼저를 같은 방식으로 돌린다면 나는 승산이 없지 않을까?라는 의심이 계속 들 수 밖에 없다.
실제로 메이저 프로그램을 퍼징해 나온 버그를 리포트해보면, Duplicate가 나거나, Patched라는 답변을 받을 때가 의외로 많다. 나만의 경험은 아닌 것 같은게, 여러 사람들의 포스팅에서도 많이 언급되고, 당장 여러 Credit만 보더라도... 어떻게 보면 퍼저가 많은 버그를 찾고있다는 반증이지만, 남이 찾지 못한 버그를 내가 찾는다는건 보장하지 않는다. 그렇다면 큰 질문을 바꿔서 내가 돌리는 퍼징은 대체 가망이 있는걸까 없는걸까?
개인이 돌리는 퍼징은 가망이 없을까?
퍼저가 점점 발전하고 있는 것은 확실하다. 그렇지만 아직 퍼저가 가야할 길은 멀다고 생각한다. 유명 해킹 컨퍼런스나 보안 학회들을 보면 아직도 퍼저는 발전하고 있으며, 새로운 방법으로 퍼징을 시도하면 많은 Security 버그가 나온다. 이는 분명 발전하고 있다는 좋은 징조이다. 하지만 이와 동시에 가야 할 길도 멀다. 예를 들어, 여러 퍼저에서 많이 사용하는 Code Coverage와 버그는 정비례 관계일까? Coverage와 버그는 어느 정도의 상관관계가 있고, 새로운 테스트 케이스를 생성하는데 있어 방향을 제시해주는 좋은 지표 중 하나인 것은 분명하다. 하지만 이런 지표들은 실험적인 데이터로만 의미가 있을수도 있다는 것을 보이고 있는것이지, 이론적으로 어떤 요소들이 의미를 갖는지에 대해서 명확하게 설명하지 못하고있다.
많은 엔지니어링, 일종의 직관, 정립된 이론 등이 골고루 섞여 좋은 결과를 내고 있을 뿐 "어떤 방향으로 어떻게 만들어야 좋다!" 라는 정립된 이론은 없다. 자원과 시간이 무한해서 이상적인 Symbolic-Execution을 수행한다거나, 모든 Path Coverage를 커버한다거나 하는 것은 당연히 모든 테스트를 해봤다고 말 할 수 있겠지만 현실적으로 불가능하다. 그래서 현재로서는 지금보다 fine-grained하게, 유의미한 방향성이 있는 것들을 차용해 발전시키고 있다고 생각한다.
공개된 퍼저들은 어떨때는 너무 General해서 원하는 결과를 얻기 어렵거나, 너무 Specific해 다른 바이너리에는 적용하기 어려운 경우도 있다. 툴에 따라서는 지원을 하지 않아 제대로 동작하지 않는 것들도 있으며, 복잡하거나 많은 배경지식을 요하기도 한다. 그래서 범용적이지만 간단하고 강력한 AFL, honggfuzz, BFF와 같은 퍼저가 많이 사용되는 것 같다. 이러한 툴들을 잘 이용하면 준메이저~메이저급 프로그램의 버그를 찾는것도 충분히 가능하다고 생각한다.
컴퓨팅 파워도 중요하고, 어떤 퍼저를 쓰느냐도 중요하다. 하지만 가장 중요한건 전략, 어택 벡터, 양질의 시드, 그리고 버그의 선점과 경험과 같은 것들이라고 생각한다. 좋은 전략이 있으면 직접 퍼저를 만들어서 사용할 수도 있고, 좋은 어택 벡터가 있으면 이미 잘 만들어진 퍼저를 차용해서 사용하면 된다. 나는 이런 상황이 가망이 없는 정도는 아니라고 생각한다.
그렇다면 요즘 대세는?
사실 요즘 대세는 잘 모르겠다. 누구는 오디팅, 누군가는 퍼징이 답이라고 한다. 우문현답이지만 버그를 찾는 가장 좋은 방법은 개개인마다 다르다고 생각한다. 오디팅을 잘하는 사람들은 퍼징으로는 찾기 어려운 로직 버그를 찾기도 하며, 퍼저를 잘 만드는 사람은 새로운 퍼징 방식을 고안해 버그를 뭉터기로 찾기도한다. 때로는 코드 오디팅과 퍼징을 적절히 섞을수도 있다. ChakraCore에 JIT이 적용되기 시작한 시점에 loki의 버그를 보면 비슷한 유형의 코드들이 수두룩하다. 혹시 jitting을 대상으로 비슷한 코드들이 나오도록 간단하게 퍼저를 만든게 아닐까? 물론, 굇수라 그냥 오디팅으로만 찾았을 수도 있지만 :)..
크로미움이나 pwn2own, ZDI등을 팔로우업 하다보면 유행하는 어택 벡터가 보인다. 누군가는 남들이 노리지 않는 새로운 어택 벡터를 찾아나서거나, 새로 추가되는 기능의 코드를 오디팅 하기도 한다. 또한 기존 CVE와 비슷한 유형의 오래된 버그가 다시 발생하는 것을 보고 과거 취약점을 답습하기도 한다. 어떤 방식이든 사실 다 좋은 방식이라고 생각한다. 상대적으로 쏟을 시간이 많으면 오디팅을 할 수도 있고, 시간이 부족하면 퍼저에 의존할 수도 있다. 답습 후 비슷한 유형의 버그를 잘 찾는 것 같으면 그 또한 좋다. 나는 시간도 많지 않고, 모든 파트를 오디팅 할 자신도 없기에 퍼저를 쓴다.
사람이 하는 일이기에 철옹성같은 프로그램에서도 구멍이 존재하며, 지금도 새로운 버그는 계속 나오고 있다. 관련 이론들도 발전하고 있고, 새로운 방식을 차용한 퍼저들은 계속해서 나오고있다. 심지어 자원을 빌려주고 개인이 만든 퍼저를 돌려주는 서비스도 있다. 이렇게까지 하는 이유는 뭘까? 내가 생각하기에 퍼징은 아직까진 조금이나마 미래가 있는 것 같다. 물론 퍼징의 미래를 고민하며 의미가 있는지를 생각하기 보다는, 목표를 설정하고 당장 오디팅을 시작하거나, 남는 자원에 어떠한 퍼징이라도 돌리는 행동력, 실천이 가장 중요하다고 생각한다. :)