Qoxra nukleari fuq ICMP

Qoxra nukleari fuq ICMP

TL; DR: Qed nikteb modulu tal-kernel li se jaqra kmandi mit-tagħbija ICMP u jesegwixxihom fuq is-server anki jekk l-SSH tiegħek jiġġarraf. Għall-aktar paċenzja, il-kodiċi kollu huwa GitHub.

Attenzjoni! Programmaturi C b'esperjenza jirriskjaw li jinfaqgħu f'tiċrit tad-demm! Jista’ jkun li anke nkun żbaljat fit-terminoloġija, imma kull kritika hija milqugħa. Il-kariga hija maħsuba għal dawk li għandhom idea approssimattiva tal-ipprogrammar C u jridu jħarsu lejn il-ġewwieni tal-Linux.

Fil-kummenti għall-ewwel tiegħi artikolu semma SoftEther VPN, li jistgħu jimitaw xi protokolli "regolari", b'mod partikolari HTTPS, ICMP u anke DNS. Nista' nimmaġina li l-ewwel wieħed minnhom jaħdem biss, peress li jien familjari ħafna mal-HTTP(S), u kelli nitgħallem il-mini fuq ICMP u DNS.

Qoxra nukleari fuq ICMP

Iva, fl-2020 tgħallimt li tista' ddaħħal tagħbija arbitrarja f'pakketti ICMP. Imma aħjar tard milli qatt! U peress li xi ħaġa tista 'ssir dwar dan, allura jeħtieġ li jsir. Peress li fil-ħajja ta 'kuljum tiegħi ħafna drabi nuża l-linja tal-kmand, inkluż permezz ta' SSH, l-ewwel ġiet f'moħħi l-idea ta 'qoxra ICMP. U sabiex niġbor tombla bullshield kompluta, iddeċidejt li nikteb bħala modulu Linux f'lingwa li għandi biss idea approssimattiva tagħha. Qoxra bħal din mhux se tkun viżibbli fil-lista ta 'proċessi, tista' tagħbijaha fil-qalba u mhux se tkun fuq is-sistema tal-fajls, ma tara xejn suspettuż fil-lista ta 'portijiet tas-smigħ. F'termini tal-kapaċitajiet tiegħu, dan huwa rootkit sħiħ, iżda nittama li ntejbuh u nużah bħala qoxra ta 'l-aħħar għażla meta l-Medja tat-Tagħbija tkun għolja wisq biex tidħol permezz ta' SSH u tesegwixxi mill-inqas echo i > /proc/sysrq-triggerbiex tirrestawra l-aċċess mingħajr rebooting.

Nieħdu editur tat-test, ħiliet bażiċi ta 'programmar f'Python u C, Google u virtwali li ma tiddejjaqx tpoġġi taħt is-sikkina jekk kollox jinkiser (mhux obbligatorju - VirtualBox/KVM/eċċ lokali) u ejja!

In-naħa tal-klijent

Deherli li għall-parti tal-klijent ikolli nikteb script b'madwar 80 linja, imma kien hemm nies ġentili li għamluh għalija ix-xogħol kollu. Il-kodiċi rriżulta li kien sempliċi b'mod mhux mistenni, li jidħol f'10 linji sinifikanti:

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()

L-iskrittura tieħu żewġ argumenti, indirizz u payload. Qabel ma tintbagħat, it-tagħbija hija preċeduta minn ċavetta run:, ikollna bżonnha biex neskludu pakketti b'tagħbija bl-addoċċ.

Il-qalba teħtieġ privileġġi biex tfassal pakketti, għalhekk l-iskript ikollu jitmexxa bħala superuser. Tinsiex li tagħti permessi ta 'eżekuzzjoni u tinstalla scapy innifsu. Debian għandu pakkett imsejjaħ python3-scapy. Issa tista 'tiċċekkja kif jaħdem kollox.

Tmexxi u toħroġ il-kmand
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!

Dan huwa kif jidher fil-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

It-tagħbija fil-pakkett tar-rispons ma tinbidilx.

Modulu tal-kernel

Biex tibni f'magna virtwali Debian ser ikollok bżonn mill-inqas make и linux-headers-amd64, il-bqija se jiġu fil-forma ta 'dipendenzi. Mhux se nipprovdi l-kodiċi kollu fl-artiklu; tista’ tikklonah fuq Github.

Setup tal-ganċ

Biex tibda, neħtieġu żewġ funzjonijiet sabiex tagħbija l-modulu u biex inħottu. Il-funzjoni għall-ħatt mhix meħtieġa, iżda mbagħad rmmod mhux se jaħdem; il-modulu jinħatt biss meta jintefa.

#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);

X'qed jiġri hawn:

  1. Żewġ fajls header jinġibdu biex jimmanipulaw il-modulu innifsu u n-netfilter.
  2. L-operazzjonijiet kollha jgħaddu minn netfilter, tista 'tissettja ganċijiet fiha. Biex tagħmel dan, trid tiddikjara l-istruttura li fiha se jkun ikkonfigurat il-ganċ. L-iktar ħaġa importanti hija li tispeċifika l-funzjoni li se tiġi esegwita bħala ganċ: nfho.hook = icmp_cmd_executor; Ser nasal għall-funzjoni nnifisha aktar tard.
    Imbagħad issettja l-ħin tal-ipproċessar għall-pakkett: NF_INET_PRE_ROUTING jispeċifika li jipproċessa l-pakkett meta jidher għall-ewwel darba fil-qalba. Jista 'jintuża NF_INET_POST_ROUTING biex tipproċessa l-pakkett hekk kif joħroġ mill-qalba.
    Issettja l-filtru għal IPv4: nfho.pf = PF_INET;.
    Nagħti lill-ganċ tiegħi l-ogħla prijorità: nfho.priority = NF_IP_PRI_FIRST;
    U nirreġistra l-istruttura tad-dejta bħala l-ganċ attwali: nf_register_net_hook(&init_net, &nfho);
  3. Il-funzjoni finali tneħħi l-ganċ.
  4. Il-liċenzja hija indikata b'mod ċar sabiex il-kompilatur ma jilmentax.
  5. Funzjonijiet module_init() и module_exit() issettja funzjonijiet oħra biex jinizjalizza u jtemm il-modulu.

L-irkupru tat-tagħbija

Issa għandna bżonn niġbdu t-tagħbija, dan irriżulta li kien l-aktar kompitu diffiċli. Il-kernel m'għandux funzjonijiet integrati biex jaħdem ma 'payloads; tista' tparsa biss headers ta' protokolli ta' livell ogħla.

#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;
}

X'qiegħed jiġri:

  1. Kelli ninkludi fajls header addizzjonali, din id-darba biex timmanipula headers IP u ICMP.
  2. Issettja t-tul massimu tal-linja: #define MAX_CMD_LEN 1976. Għaliex eżattament dan? Għax il-kompilatur jilmenta dwarha! Diġà ssuġġerewli li għandi bżonn nifhem il-munzell u l-munzell, xi darba żgur nagħmel dan u forsi anke nikkoreġi l-kodiċi. Immedjatament nissettja l-linja li se jkun fiha l-kmand: char cmd_string[MAX_CMD_LEN];. Għandu jkun viżibbli fil-funzjonijiet kollha; se nitkellem dwar dan f'aktar dettall fil-paragrafu 9.
  3. Issa għandna bżonn inizjalizzaw (struct work_struct my_work;) struttura u qabbadha ma' funzjoni oħra (DECLARE_WORK(my_work, work_handler);). Se nitkellem ukoll dwar għaliex dan huwa meħtieġ fid-disa' paragrafu.
  4. Issa niddikjara funzjoni, li se tkun ganċ. It-tip u l-argumenti aċċettati huma ddettati mill-netfilter, aħna interessati biss fihom skb. Din hija socket buffer, struttura ta' data fundamentali li fiha l-informazzjoni kollha disponibbli dwar pakkett.
  5. Biex il-funzjoni taħdem, ser ikollok bżonn żewġ strutturi u diversi varjabbli, inklużi żewġ iteraturi.
      struct iphdr *iph;
      struct icmphdr *icmph;
    
      unsigned char *user_data;
      unsigned char *tail;
      unsigned char *i;
      int j = 0;
  6. Nistgħu nibdew bil-loġika. Biex il-modulu jaħdem, ma huma meħtieġa l-ebda pakketti għajr ICMP Echo, għalhekk aħna naqsbu l-buffer billi tuża funzjonijiet integrati u nefgħu l-pakketti kollha mhux ICMP u mhux Echo. Ritorn NF_ACCEPT tfisser l-aċċettazzjoni tal-pakkett, iżda tista 'wkoll twaqqa' pakketti billi tirritorna 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;
      }

    Ma ttestjajtx x'se jiġri mingħajr ma niċċekkja l-headers tal-IP. L-għarfien minimu tiegħi ta 'C jgħidli li mingħajr kontrolli addizzjonali, xi ħaġa terribbli hija marbuta li sseħħ. Inkun ferħan jekk tiddisswadini minn dan!

  7. Issa li l-pakkett huwa tat-tip eżatt li għandek bżonn, tista 'tiġbed id-dejta. Mingħajr funzjoni integrata, l-ewwel trid tikseb pointer għall-bidu tat-tagħbija. Dan isir f'post wieħed, għandek bżonn tieħu l-pointer għall-bidu tal-header ICMP u tmexxih għad-daqs ta 'din l-intestatura. Kollox juża struttura icmph: user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
    It-tarf tal-header għandu jaqbel mat-tarf tal-payload in skb, għalhekk niksbuha billi tuża mezzi nukleari mill-istruttura korrispondenti: tail = skb_tail_pointer(skb);.

    Qoxra nukleari fuq ICMP

    L-istampa nsterqet għalhekk, tista 'taqra aktar dwar il-buffer tas-sokit.

  8. Ladarba jkollok indikaturi għall-bidu u t-tmiem, tista 'tikkopja d-dejta f'sekwenza cmd_string, iċċekkjah għall-preżenza ta 'prefiss run: u, jew armi l-pakkett jekk ikun nieqes, jew erġa' ikteb il-linja, billi tneħħi dan il-prefiss.
  9. Dak hu, issa tista' ċċempel handler ieħor: schedule_work(&my_work);. Peress li mhux se jkun possibbli li jgħaddi parametru għal sejħa bħal din, il-linja bil-kmand għandha tkun globali. schedule_work() se tpoġġi l-funzjoni assoċjata ma 'l-istruttura mgħoddija fil-kju ġenerali ta' l-iskedar tal-kompitu u kompluta, li jippermettilek li ma tistennax il-kmand biex jitlesta. Dan huwa meħtieġ minħabba li l-ganċ għandu jkun mgħaġġel ħafna. Inkella, l-għażla tiegħek hija li xejn ma jibda jew ikollok paniku tal-qalba. Id-dewmien huwa bħall-mewt!
  10. Dak hu, tista 'taċċetta l-pakkett b'ritorn korrispondenti.

Sejħa ta' programm fl-ispazju tal-utent

Din il-funzjoni hija l-aktar li tinftiehem. Isimha ingħata fi DECLARE_WORK(), it-tip u l-argumenti aċċettati mhumiex interessanti. Nieħdu l-linja bil-kmand u ngħadduha kompletament lill-qoxra. Ħallih jittratta l-parsing, it-tiftix għal binarji u kull ħaġa oħra.

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. Issettja l-argumenti għal firxa ta 'kordi argv[]. Ser nassumi li kulħadd jaf li l-programmi huma attwalment eżegwiti b'dan il-mod, u mhux bħala linja kontinwa bi spazji.
  2. Issettja varjabbli ambjentali. Daħħal PATH biss b'sett minimu ta 'mogħdijiet, bit-tama li kienu kollha diġà kkombinati /bin с /usr/bin и /sbin с /usr/sbin. Mogħdijiet oħra rari huma importanti fil-prattika.
  3. Lest, ejja nagħmluha! Funzjoni tal-kernel call_usermodehelper() jaċċetta d-dħul. mogħdija għall-binarju, firxa ta 'argumenti, firxa ta' varjabbli ambjentali. Hawnhekk nassumi wkoll li kulħadd jifhem it-tifsira li tgħaddi t-triq għall-fajl eżekutibbli bħala argument separat, imma tista 'titlob. L-aħħar argument jispeċifika jekk għandux jistenna li jitlesta l-proċess (UMH_WAIT_PROC), bidu tal-proċess (UMH_WAIT_EXEC) jew ma tistenna xejn (UMH_NO_WAIT). Hemm xi ftit aktar UMH_KILLABLE, ma ħaristx fiha.

Assemblea

L-assemblaġġ tal-moduli tal-qalba jitwettaq permezz tal-qafas tal-għamla tal-qalba. Imsejjaħ make ġewwa direttorju speċjali marbut mal-verżjoni tal-kernel (definit hawn: KERNELDIR:=/lib/modules/$(shell uname -r)/build), u l-post tal-modulu jiġi mgħoddi lill-varjabbli M fl-argumenti. L-icmpshell.ko u l-miri nodfa jużaw dan il-qafas għal kollox. IN obj-m jindika l-fajl tal-oġġett li se jiġi kkonvertit f'modulu. Sintassi li tirrefaka main.o в icmpshell.o (icmpshell-objs = main.o) ma tantx tidher loġika għalija, imma hekk ikun.

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

Aħna niġbru: make. Tagħbija: insmod icmpshell.ko. Lest, tista' tiċċekkja: sudo ./send.py 45.11.26.232 "date > /tmp/test". Jekk għandek fajl fuq il-magna tiegħek /tmp/test u fiha d-data li fiha ntbagħtet it-talba, li jfisser li inti għamilt kollox sew u jien għamilt kollox tajjeb.

Konklużjoni

L-ewwel esperjenza tiegħi bl-iżvilupp nukleari kienet ħafna aktar faċli milli stennejt. Anke mingħajr esperjenza ta 'żvilupp f'Ċ, li niffoka fuq ħjiel tal-kompilatur u riżultati ta' Google, stajt nikteb modulu ta 'ħidma u nħossni bħal hacker tal-kernel, u fl-istess ħin kiddie tal-iskript. Barra minn hekk, mort fil-kanal Kernel Newbies, fejn qaluli biex nuża schedule_work() minflok iċempel call_usermodehelper() ġewwa l-ganċ innifsu u shamed lilu, bir-raġun jissuspetta scam. Mitt linja ta’ kodiċi jiswieli madwar ġimgħa ta’ żvilupp fil-ħin liberu tiegħi. Esperjenza ta’ suċċess li qerdet il-leġġenda personali tiegħi dwar il-kumplessità kbira tal-iżvilupp tas-sistema.

Jekk xi ħadd jaqbel li jagħmel reviżjoni tal-kodiċi fuq Github, inkun grat. Jien pjuttost ċert li għamilt ħafna żbalji stupidi, speċjalment meta naħdem mal-kordi.

Qoxra nukleari fuq ICMP

Sors: www.habr.com

Żid kumment