Hello BIRD maintainers,
I would like to report a possible issue in BIRD.
### Summary
BIRD appears to accept a BGP UPDATE containing `AS4_AGGREGATOR` with
AS number
0 from a non-AS4 peer. When the same UPDATE also contains `AGGREGATOR`
with
`AS_TRANS`, BIRD's AS4 transition processing converts the `AS4_AGGREGATOR`
value into the effective `AGGREGATOR` attribute.
In dynamic testing, BIRD installed the route with:
```text
BGP.aggregator: 192.0.2.9 AS0
```
and then exported the route to a downstream non-AS4 peer with:
```text
AGGREGATOR flags=0xc0 as=0 addr=192.0.2.9
```
I am reporting this as an RFC 7607 conformance / input-validation
issue, not as
a high-impact security vulnerability.
### Expected Behavior
RFC 7607 Section 2 says that a BGP speaker MUST NOT originate or
propagate a
route with AS number zero in the `AS_PATH`, `AS4_PATH`, `AGGREGATOR`, or
`AS4_AGGREGATOR` attributes.
An UPDATE containing AS 0 in `AS4_AGGREGATOR` should cause the
`AS4_AGGREGATOR` attribute to be considered malformed under RFC 7607 and
handled according to RFC 6793. In other words, the attribute should be
discarded and the UPDATE may continue to be processed.
However, the `AS4_AGGREGATOR` value must not become the effective
`AGGREGATOR` attribute, and BIRD must not install or export the route with
`AGGREGATOR AS=0`.
### Actual Behavior
BIRD continues processing the UPDATE, but the malformed `AS4_AGGREGATOR`
value becomes the effective `AGGREGATOR` attribute. The route is
installed with
`BGP.aggregator: 192.0.2.9 AS0`, and BIRD exports an `AGGREGATOR`
attribute
whose AS field is 0.
### Steps to Reproduce
1. Start BIRD with a dynamic BGP listener:
```bird
router id 127.0.0.1;
protocol device {
}
protocol bgp as4agg_as0 {
local 127.0.0.1 port 11918 as 65001;
neighbor range 127.0.0.0/8 <http://127.0.0.0/8> external;
dynamic name "poc";
multihop;
ipv4 {
import all;
export all;
};
}
```
2. Connect an upstream peer from `127.0.0.2`, AS 65002, without
advertising AS4
capability.
3. Send an UPDATE for `203.0.113.0/24` <http://203.0.113.0/24`>
containing:
```text
ORIGIN = IGP
AS_PATH = 65002
NEXT_HOP = 127.0.0.2
AGGREGATOR = AS_TRANS / 192.0.2.9
AS4_AGGREGATOR = AS 0 / 192.0.2.9
```
4. Query the local RIB:
```text
birdc show route 203.0.113.0/24 <http://203.0.113.0/24> all
```
5. Connect a downstream peer from `127.0.0.3`, AS 65003, also without AS4
capability, and inspect the UPDATE exported by BIRD.
### Dynamic Verification
This was reproduced against:
```text
BIRD version 2.19.0+branch.master.880200b1f94c
```
Local RIB:
```text
203.0.113.0/24 <http://203.0.113.0/24> unreachable [poc1 ... from
127.0.0.2] * (100) [AS65002i]
Type: BGP univ
BGP.origin: IGP
BGP.as_path: 65002
BGP.next_hop: 127.0.0.2
BGP.local_pref: 100
BGP.aggregator: 192.0.2.9 AS0
```
Downstream export:
```text
[+] Exported AGGREGATOR flags=0xc0 as=0 addr=192.0.2.9
VERDICT: NON_COMPLIANT_REPRODUCED_ACCEPTED_AND_PROPAGATED
```
### Source Analysis
`AS4_AGGREGATOR` decoding checks whether the session is already
AS4-capable and
whether the attribute length is 8, but it does not check whether the
AS field is
0:
```c
static void
bgp_decode_as4_aggregator(...)
{
if (s->as4_session)
DISCARD(NEW_BGP, "AS4_AGGREGATOR");
if (len != 8)
DISCARD(BAD_LENGTH, "AS4_AGGREGATOR", len);
bgp_set_attr_data(to, s->pool, BA_AS4_AGGREGATOR, flags, data, len);
}
```
During AS4 transition processing, if both `AGGREGATOR` and
`AS4_AGGREGATOR` are
present and `AGGREGATOR` has `AS_TRANS`, BIRD uses `AS4_AGGREGATOR` as the
effective `AGGREGATOR`:
```c
if (a2 && a4)
{
u32 a2_asn = get_u32(a2->u.ptr->data);
if (a2_asn != AS_TRANS)
return;
/* Use AS4_AGGREGATOR instead of AGGREGATOR */
a2->u.ptr = a4->u.ptr;
}
```
There appears to be no AS 0 validation on either `AGGREGATOR` or
`AS4_AGGREGATOR`.
### Comparison
FRR checks AS 0 for both `AGGREGATOR` and `AS4_AGGREGATOR`. If the AS
is 0, FRR
logs the condition and does not mark the attribute as present for
propagation.
### Impact
The practical impact is interoperability and malformed route
propagation. BIRD
may propagate a route with invalid AS 0 aggregator metadata, which can
cause
downstream implementations with stricter RFC 7607 handling to reject,
withdraw,
or otherwise handle the route inconsistently.
This does not directly imply route hijacking. `AGGREGATOR` is not the
primary
AS loop detection input; `AS_PATH` and `AS4_PATH` are.
### Suggested Fix Direction
Add AS 0 validation for `AGGREGATOR` and `AS4_AGGREGATOR` during decode or
before AS4 transition reconstruction. In particular, an
`AS4_AGGREGATOR` whose
first four bytes decode to ASN 0 should not be allowed to become the
effective
`AGGREGATOR` attribute or be propagated downstream.