Skip to content

abnormal TS payload causes pluto daemon to restart in libreswan 4.9 #954

Closed
@Zhaodl1

Description

@Zhaodl1

Hi, I found a bug in libreswan-4.9 which caused the pluto daemon to restart by sending several crafted IKEv2 messages to the server.

process

first, send correct IKE_SA_INIT message and IKE_AUTH message so that the IPSEC_SA and CHILD_SA are established successfully.

then, send a REKEY_CHILD_SA message with an incorrect TSi payload. specifically, the Selector Length of the Traffic Selector need to be a different value from the real length(samller or larger, it doesn't matter). This will cause a crash when the server trys to parse this payload.

my conf

conn ikev2_test

    authby=secret
    ike=aes128-sha1;modp1536
    keyexchange=ike
    phase2=esp
    phase2alg=aes128-sha1
    compress=no
    pfs=no
    auto=add
    type=tunnel
    left=192.168.100.31
    leftnexthop=%defaultroute
    right=192.168.100.30
    rightnexthop=%defaultroute

my pluto.log for parsing the REKEY_CHILD_SA message

when parsing 1 traffic selectors , the pluto restart

Dec 20 06:04:47.516841: | *received 204 bytes from 192.168.100.30:36062 on ens33 192.168.100.31:500 using UDP
Dec 20 06:04:47.516901: | d8 ef b8 ef 3b 3a f8 a4 41 06 0f 82 7d 60 77 86
Dec 20 06:04:47.516904: | 2e 20 24 08 00 00 00 02 00 00 00 cc 29 00 00 b0
Dec 20 06:04:47.516906: | e6 8b 54 3f 30 cb cc 93 70 a6 79 47 ff c1 d3 7f
Dec 20 06:04:47.516908: | 83 6d d7 2b 44 b5 86 75 64 fb cb f0 f9 f3 e5 b7
Dec 20 06:04:47.516910: | 94 60 b4 26 3e 16 fc 6d 2d 76 9d 8e 82 11 59 c1
Dec 20 06:04:47.516911: | c3 5a 68 2c 01 5e 4f ed 8d b7 e7 56 b3 23 24 cc
Dec 20 06:04:47.516913: | dd bf e5 76 03 a3 33 36 83 5e 06 f2 71 bf 75 86
Dec 20 06:04:47.516915: | 07 f8 01 da 32 01 9e 89 9c aa a0 98 62 72 96 b8
Dec 20 06:04:47.516917: | 38 ef 32 31 1a 6f d2 50 d8 50 0f 92 49 cb 33 20
Dec 20 06:04:47.516919: | 4b 2c b0 7b f8 a4 8a ea 8f f8 ca 94 84 cf a7 ff
Dec 20 06:04:47.516921: | f1 e7 19 df c1 6b ae f9 6a c7 dc ca 3a dc ea 72
Dec 20 06:04:47.516923: | d5 08 2e 70 2f 79 15 52 a8 bf 07 ea fc 8b 3c 96
Dec 20 06:04:47.516925: | 26 0c cf 18 c3 44 f2 ea f2 09 af 5c
Dec 20 06:04:47.516933: | **parse ISAKMP Message:
Dec 20 06:04:47.516937: | initiator SPI: d8 ef b8 ef 3b 3a f8 a4
Dec 20 06:04:47.516940: | responder SPI: 41 06 0f 82 7d 60 77 86
Dec 20 06:04:47.516942: | next payload type: ISAKMP_NEXT_v2SK (0x2e)
Dec 20 06:04:47.516944: | ISAKMP version: IKEv2 version 2.0 (rfc4306/rfc5996) (0x20)
Dec 20 06:04:47.516946: | exchange type: ISAKMP_v2_CREATE_CHILD_SA (0x24)
Dec 20 06:04:47.516949: | flags: ISAKMP_FLAG_v2_IKE_INIT (0x8)
Dec 20 06:04:47.516952: | Message ID: 2 (00 00 00 02)
Dec 20 06:04:47.516955: | length: 204 (00 00 00 cc)
Dec 20 06:04:47.516957: | processing version=2.0 packet with exchange type=ISAKMP_v2_CREATE_CHILD_SA (36)
Dec 20 06:04:47.516960: | I am the IKE SA Original Responder receiving an IKEv2 CREATE_CHILD_SA request
Dec 20 06:04:47.516970: | State DB: found IKEv2 state #1 in ESTABLISHED_IKE_SA (find_v2_ike_sa)
Dec 20 06:04:47.516974: | #1 st.st_msgid_lastrecv 1 md.hdr.isa_msgid 00000002
Dec 20 06:04:47.516981: | Message ID: IKE #1 not a duplicate - message request 2 is new (SKEYSEED is known) (initiator: .sent=-1 .recv=-1 .recv_frags=0 .wip=-1 .last_sent=36587.248097 .last_recv=36587.248097 responder: .sent=1 .recv=1 .recv_frags=0 .wip=-1 .last_sent=36587.284336 .last_recv=36587.284331)
Dec 20 06:04:47.516983: | unpacking clear payload
Dec 20 06:04:47.516985: | Now let's proceed with payload (ISAKMP_NEXT_v2SK)
Dec 20 06:04:47.516988: | ***parse IKEv2 Encryption Payload:
Dec 20 06:04:47.516991: | next payload type: ISAKMP_NEXT_v2N (0x29)
Dec 20 06:04:47.516993: | flags: none (0x0)
Dec 20 06:04:47.516995: | length: 176 (00 b0)
Dec 20 06:04:47.516998: | processing payload: ISAKMP_NEXT_v2SK (len=172)
Dec 20 06:04:47.517002: | looking for transition from ESTABLISHED_IKE_SA matching CREATE_CHILD_SA request: SK (ignoring secured payloads)
Dec 20 06:04:47.517026: | trying: process rekey IKE SA request (CREATE_CHILD_SA)
Dec 20 06:04:47.517028: | matching by ignoring secured payloads
Dec 20 06:04:47.517088: | authenticator matched
Dec 20 06:04:47.517102: | stripping 4 octets as pad
Dec 20 06:04:47.517105: | #1 ikev2 ISAKMP_v2_CREATE_CHILD_SA decrypt success
Dec 20 06:04:47.517108: | Now let's proceed with payload (ISAKMP_NEXT_v2N)
Dec 20 06:04:47.517112: | **parse IKEv2 Notify Payload:
Dec 20 06:04:47.517114: | next payload type: ISAKMP_NEXT_v2SA (0x21)
Dec 20 06:04:47.517116: | flags: none (0x0)
Dec 20 06:04:47.517118: | length: 12 (00 0c)
Dec 20 06:04:47.517121: | Protocol ID: IKEv2_SEC_PROTO_ESP (0x3)
Dec 20 06:04:47.517123: | SPI size: 4 (04)
Dec 20 06:04:47.517126: | Notify Message Type: v2N_REKEY_SA (0x4009)
Dec 20 06:04:47.517128: | processing payload: ISAKMP_NEXT_v2N (len=4)
Dec 20 06:04:47.517130: | Now let's proceed with payload (ISAKMP_NEXT_v2SA)
Dec 20 06:04:47.517133: | **parse IKEv2 Security Association Payload:
Dec 20 06:04:47.517135: | next payload type: ISAKMP_NEXT_v2Ni (0x28)
Dec 20 06:04:47.517137: | flags: none (0x0)
Dec 20 06:04:47.517140: | length: 44 (00 2c)
Dec 20 06:04:47.517142: | processing payload: ISAKMP_NEXT_v2SA (len=40)
Dec 20 06:04:47.517144: | Now let's proceed with payload (ISAKMP_NEXT_v2Ni)
Dec 20 06:04:47.517146: | **parse IKEv2 Nonce Payload:
Dec 20 06:04:47.517148: | next payload type: ISAKMP_NEXT_v2TSi (0x2c)
Dec 20 06:04:47.517149: | flags: none (0x0)
Dec 20 06:04:47.517152: | length: 36 (00 24)
Dec 20 06:04:47.517154: | processing payload: ISAKMP_NEXT_v2Ni (len=32)
Dec 20 06:04:47.517156: | Now let's proceed with payload (ISAKMP_NEXT_v2TSi)
Dec 20 06:04:47.517158: | **parse IKEv2 Traffic Selector - Initiator - Payload:
Dec 20 06:04:47.517160: | next payload type: ISAKMP_NEXT_v2TSr (0x2d)
Dec 20 06:04:47.517162: | flags: none (0x0)
Dec 20 06:04:47.517164: | length: 24 (00 18)
Dec 20 06:04:47.517166: | number of TS: 1 (01)
Dec 20 06:04:47.517168: | processing payload: ISAKMP_NEXT_v2TSi (len=16)
Dec 20 06:04:47.517170: | Now let's proceed with payload (ISAKMP_NEXT_v2TSr)
Dec 20 06:04:47.517173: | **parse IKEv2 Traffic Selector - Responder - Payload:
Dec 20 06:04:47.517175: | next payload type: ISAKMP_NEXT_v2NONE (0x0)
Dec 20 06:04:47.517177: | flags: none (0x0)
Dec 20 06:04:47.517179: | length: 24 (00 18)
Dec 20 06:04:47.517181: | number of TS: 1 (01)
Dec 20 06:04:47.517183: | processing payload: ISAKMP_NEXT_v2TSr (len=16)
Dec 20 06:04:47.517187: | looking for transition from ESTABLISHED_IKE_SA matching CREATE_CHILD_SA request: SK{N(REKEY_SA),SA,Ni,TSi,TSr}
Dec 20 06:04:47.517189: | trying: process rekey IKE SA request (CREATE_CHILD_SA)
Dec 20 06:04:47.517191: | secured payloads do not match
Dec 20 06:04:47.517192: | trying: process rekey IKE SA response (CREATE_CHILD_SA)
Dec 20 06:04:47.517195: | message role does not match response
Dec 20 06:04:47.517197: | trying: process rekey Child SA request (CREATE_CHILD_SA)
Dec 20 06:04:47.517198: | secured message matched
Dec 20 06:04:47.517201: | selected state microcode process rekey Child SA request (CREATE_CHILD_SA)
Dec 20 06:04:47.517205: | #1 updating local interface from 192.168.100.31:500 to 192.168.100.31:500 using md->iface (update_ike_endpoints() +2598 /programs/pluto/state.c)
Dec 20 06:04:47.517210: | #1.st_v2_transition PARENT_R1->ESTABLISHED_IKE_SA -> ESTABLISHED_IKE_SA->ESTABLISHED_IKE_SA (v2_dispatch() +2292 /programs/pluto/ikev2.c)
Dec 20 06:04:47.517215: | Message ID: IKE #1 responder starting message request 2 (initiator: .sent=-1 .recv=-1 .recv_frags=0 .wip=-1 .last_sent=36587.248097 .last_recv=36587.248097 responder: .sent=1 .recv=1 .recv_frags=0 .wip=2 .last_sent=36587.284336 .last_recv=36587.284331)
Dec 20 06:04:47.517218: | calling processor process rekey Child SA request (CREATE_CHILD_SA)
Dec 20 06:04:47.517221: | CREATE_CHILD_SA IPsec SA rekey Protocol IKEv2_SEC_PROTO_ESP
Dec 20 06:04:47.517223: | parsing 4 raw bytes of IKEv2 Notify Payload into SPI
Dec 20 06:04:47.517229: | SPI
Dec 20 06:04:47.517232: | 0d bb 3a 00 ..:.
Dec 20 06:04:47.517234: | CREATE_CHILD_S to rekey IPsec SA(0x0dbb3a00) Protocol IKEv2_SEC_PROTO_ESP
Dec 20 06:04:47.517237: | v2 CHILD SA #2 found using their inbound (our outbound) SPI, in STATE_V2_ESTABLISHED_CHILD_SA
Dec 20 06:04:47.517239: | State DB: found IKEv2 state #2 in ESTABLISHED_CHILD_SA (find_v2_child_sa_by_outbound_spi)
Dec 20 06:04:47.517242: | #1 hasa a rekey request for "ikev2_test" #2 TSi TSr
Dec 20 06:04:47.517246: | addref fd@NULL (duplicate_state() +1538 /programs/pluto/state.c)
Dec 20 06:04:47.517252: | entry state hash_table_entries.serialno@0x55a1f6e50ea8 "ikev2_test" #3 initialized
Dec 20 06:04:47.517255: | entry state hash_table_entries.connection_serialno@0x55a1f6e50ea8 $2 initialized
Dec 20 06:04:47.517257: | entry state hash_table_entries.reqid@0x55a1f6e50ea8 "ikev2_test" #3: reqid=0 initialized
Dec 20 06:04:47.517261: | entry state hash_table_entries.ike_initiator_spi@0x55a1f6e50ea8 "ikev2_test" #3: 00 00 00 00 00 00 00 00 initialized
Dec 20 06:04:47.517264: | entry state hash_table_entries.ike_spis@0x55a1f6e50ea8 "ikev2_test" #3: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 initialized
Dec 20 06:04:47.517266: | creating state object #3 at 0x55a1f6e50ea8
Dec 20 06:04:47.517283: | entry state hash_table_entries.serialno@0x55a1f6e50ea8 "ikev2_test" #3 added to hash table bucket 0x55a1f5778b20
Dec 20 06:04:47.517286: | entry state hash_table_entries.connection_serialno@0x55a1f6e50ea8 $2 added to hash table bucket 0x55a1f5774ea0
Dec 20 06:04:47.517289: | entry state hash_table_entries.reqid@0x55a1f6e50ea8 "ikev2_test" #3: reqid=0 added to hash table bucket 0x55a1f576e0a0
Dec 20 06:04:47.517292: | entry state hash_table_entries.ike_initiator_spi@0x55a1f6e50ea8 "ikev2_test" #3: d8 ef b8 ef 3b 3a f8 a4 added to hash table bucket 0x55a1f576dbc0
Dec 20 06:04:47.517295: | entry state hash_table_entries.ike_spis@0x55a1f6e50ea8 "ikev2_test" #3: d8 ef b8 ef 3b 3a f8 a4 41 06 0f 82 7d 60 77 86 added to hash table bucket 0x55a1f57671c0
Dec 20 06:04:47.517298: | pstats #3 ikev2.child started
Dec 20 06:04:47.517301: | duplicating state object #1 "ikev2_test" as #3 for IPSEC SA
Dec 20 06:04:47.517304: | #3 setting local endpoint to 192.168.100.31:500 from #1.st_localport (duplicate_state() +1553 /programs/pluto/state.c)
Dec 20 06:04:47.517310: | child state #3: UNDEFINED(ignore) => REKEY_CHILD_R0(established IKE SA)
Dec 20 06:04:47.517313: | #3.st_v2_transition NULL -> REKEY_CHILD_R0->ESTABLISHED_CHILD_SA (new_v2_child_state() +1636 /programs/pluto/state.c)
Dec 20 06:04:47.517317: | constructing ESP/AH proposals with default DH NONE for ikev2_test (Child SA proposals (initiating rekey))
Dec 20 06:04:47.517322: | converting proposal AES_CBC_128-HMAC_SHA1_96 to ikev2 ...
Dec 20 06:04:47.517328: | ... ikev2_proposal: 1:ESP=AES_CBC_128-HMAC_SHA1_96-NONE-ENABLED+DISABLED
Dec 20 06:04:47.517331: | TSi: parsing 1 traffic selectors
Dec 20 06:04:48.074282: | releasing whack fd@(nil) for (main() +1602 /programs/pluto/plutomain.c)
Dec 20 06:04:48.074334: | delref fd@NULL (main() +1602 /programs/pluto/plutomain.c)
Dec 20 06:04:48.074348: | delref fd@NULL (main() +1602 /programs/pluto/plutomain.c)
Dec 20 06:04:48.074360: | checking IKEv1 state table

related code in ikev2_ts.c

I think this is the code that causes the error. When parsing an incorrect TSi payload with wrong selecter length, pbs_in_struct return early, so the ts_body_pbs is not initialized.

        struct ikev2_ts_header ts_h;
	struct pbs_in ts_body_pbs;

	d = pbs_in_struct(&ts_pd->pbs, &ikev2_ts_header_desc,
		  &ts_h, sizeof(ts_h), &ts_body_pbs);

	switch (ts_h.isath_type) {
	case IKEv2_TS_IPV4_ADDR_RANGE:
	case IKEv2_TS_IPV6_ADDR_RANGE:
	{
		ts->ipprotoid = ts_h.isath_ipprotoid;

		/* read and fill in port range */
		struct ikev2_ts_portrange pr;

		d = pbs_in_struct(&ts_body_pbs, &ikev2_ts_portrange_desc,
			  &pr, sizeof(pr), NULL);

I also tested several other versions, it seems to have the same problem in libreswan 4.5 - 4.8

Metadata

Metadata

Assignees

No one assigned

    Labels

    CVEreproduceda test reproducing the problem has been added to the testsuite

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions