6

Я хочу туннелировать подкоманду через соединение, прослушивая порт, выполняя подкоманду (для подключения к этому порту), а затем пересылая данные через соединение:Последствия безопасности сокета при туннелировании подкоманды

package main 

import (
    "fmt" 
    "net" 
    "os" 
    "os/exec" 
) 

func main() { 
    ln, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: localhost}) 
    if err != nil { 
     fmt.Fprintln(os.Stderr, err) 
     os.Exit(1) 
    } 
    defer ln.Close() 

    port := ln.Addr().(*net.TCPAddr).Port 

    cmd := exec.Command(
     "git", 
     "clone", 
     fmt.Sprintf("git://127.0.0.1:%d/project.git", port), 
    ) 

    cmd.Stdout = os.Stdout 
    cmd.Stderr = os.Stderr 

    if err := cmd.Start(); err != nil { 
     fmt.Fprintln(os.Stderr, err) 
     os.Exit(1) 
    } 
    defer cmd.Process.Kill() 

    errs := make(chan error, 1) 
    go func() { 
     errs <- cmd.Wait() 
    }() 

    conns := make(chan net.Conn, 1) 
    go func() { 
     conn, err := ln.Accept() 
     if err == nil { 
      conns <- conn 
     } else { 
      fmt.Println(err) 
      errs <- err 
     } 
    }() 

    select { 
    case err := <-errs: 
     fmt.Fprintln(os.Stderr, err) 
     os.Exit(1) 
    case conn := <-conns: 
     defer conn.Close() 
     // TODO Tunnel data from `conn` through another connection. 
    } 

    fmt.Println("done.") 
} 

var localhost = net.IPv4(127, 0, 0, 1) 

Тем не менее, гонка здесь между временем, когда мы начинаем слушать и время, когда суб-команда фактически подключается к слушателю, где другой процесс может подключиться к слушателю. Я считаю, что эта гонка может быть использована злоумышленником для связи с процессом на другом конце соединения и достижения результатов, которые в противном случае требовали бы повышения привилегий для выполнения (например, атаки, требующие специальных разрешений, заменяют команду git вредоносными программами или просто считывая содержимое клонированного каталога, в этом случае).

Должно ли это быть проблемой? Если да, то можно ли это предотвратить? Хотя вопрос задается с использованием Go в качестве примера, приветствуются ответы и комментарии на любом языке.

ответ

0

Да, это проблема. Его можно предотвратить, используя некоторую форму аутентификации, чтобы ваш сервер разрешал подключения только от законных клиентов.

+1

Как можно добавить аутентификацию в этом случае, так как я не могу изменить клиента? –

0

Расширение на ответ Уоррена Дью, предполагая, что другой конец туннеля подключается к SSH-серверу, тогда это будет выполнять аутентификацию сервера/клиента Git.

Более общий подход к «добавлению» аутентификации в подкоманду для этой цели заключается в том, чтобы обернуть подкоманду в контейнер, такой как докер, и иметь туннель подкоманды через соединение, которое само аутентифицируется. Хотя состояние гонки в туннеле все еще присутствует, оно находится на более высоком уровне (то есть внутри контейнера), что означает, что злоумышленник без привилегий не сможет использовать условие гонки в базовой системе. Недостатком этого подхода является присущая ему сложность и накладные расходы (хотя и минимальные) на выполнение подкоманды в контейнере.