기존 코드의 문제점
기존 코드는 다음과 같은 문제점을 지닌다. 결론부터 말하면 매우 휴리스틱하며,
- isSanitized 함수의 의미론적 불일치
CBRANCH가 있으면 무조건 Safe 판정. 실제로 sink를 지배하고 있는지 보고 있지 않다. - 하드코딩된 Sink 모델
만약 memcpy가 아니라 memmove/strncpy 이런 함수라면? 인자 위치가 다를 것. - 제어 의존성은 휴리스틱으로, 데이터 의존성만 보고 있음
Upgrade 요소
먼저 Sink를 담을 요소를 memcpy로 한정짓지 않기 위해 따로 table을 뺀다. 예를 들어
Map<String, SinkSpec> Sinks = Map.of {
"memcpy", new SinkSpec(2, 0), //1번 인자 : size 인자 위치, 2번 인자 : bound 계산을 위한 버퍼 위치
"memmove", new SinkSpec(2, 0),
}
와 같은 식으로 Table을 정의한다면 각 Sink들에 따라 인자 순서가 달라져도 좀 더 정확한 판단을 할 수 있지 않을까 싶다.
다음으로 Source다. 추후 Taint 등을 사용한다면 필요하므로 Source를 한번 더 정의한다면
- 네트워크 입력 함수의 리턴이나 출력 인자
예를 들어 recv(sock, buf, …)이라면 buf에 공격자 데이터가 담길 것이고, 이런 것을 오염으로 마킹한다. - LOAD
모든 LOAD를 무조건 위협으로 보는 것이 아닌 이미 오염된 메모리 영역에서만 읽는 LOAD로 좁히기 - 함수 파라미터
외부에서 들어오는 파라미터. 다만 이건 추후 확장 영역으로 남기고자 한다.
다음으로 Dataflow인데, 기존처럼 def-use 흐름의 visited 흐름은 비슷하게 가져가되 상수면 무조건 안전, LOAD면 무조건 경고같은 판정을 수집 과정에서 바로 확인하지 않고 여기서는 의존성 관계만 수집하고, 판정을 따로 뺀다. 이 때 판정 방식은 동일하게 sink에서 getDef 함수를 가지고 역추적을 수행한다.
다음으로 Heartbleed의 핵심인 경계값 체크 로직이 들어가 있는가다. isSanitized 함수를 개선하기 위해 sink에 도달한 taint 값 v에 대해서 CBRANCH가 존재하고, 그 CBRANCH의 BB가 sink의 BB를 지배하며, sink가 검사 통과 edge에 위치하면 경계값 체크가 정상적으로 수행된다 생각하면 될 것이라 생각한다.
(여기서 더 나간다면 Z3 등을 통해서 SAT 여부를 판단하지 않을까…싶다.)