[Oisf-devel] Help with XFF

Anoop Saldanha anoopsaldanha at gmail.com
Thu Jul 19 15:15:52 UTC 2012


Hi Ignacio,

On Wed, Jul 18, 2012 at 9:17 PM, I. Sanchez <sanchezmartin.ji at gmail.com> wrote:
> Hi there!
>
> I am trying to implement support for XFF (X-Forwarded-For). As a first step,
> I would like to modify the alert-debuglog.c to replace the srcip of the
> triggered alert by the client IP address specified by the XFF header, in
> case the XFF has been enabled at the suricata.yaml file and the header is
> present in the request.

What does this conf variable in the yaml allow?

Replacing the srcip for the packet is wrong, since the info printed is
not the srcip for the packet, but we will end up presenting the wrong
ip as the packet srcip.  The right thing would be to check if XFF is
present in the http state and if yes, print the ip specified by the
the header separately.

if (XFF-header present) {
    MemBufferWrite("XFF-header: srcip");
}

>
> I am inserting the XFF extraction code at the AlertDebugLogger function,
> right after:
>
>     char srcip[46], dstip[46];
>
>     if (PKT_IS_IPV4(p)) {
>         PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip,
> sizeof(srcip));
>         PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip,
> sizeof(dstip));
>     } else if (PKT_IS_IPV6(p)) {
>         PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip,
> sizeof(srcip));
>         PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip,
> sizeof(dstip));
>     }
>
>
> My code is currently:
>
>     /* XFF Code */
>     // strcpy(srcip,"0");
>     if (aft->debuglog_ctx->flags & ALERT_DEBUGLOG_XFF) {
>         // strcpy(srcip,"1");
>         HtpState *htp_state=NULL;
>         htp_tx_t *tx = NULL;
>         htp_header_t *h_xff = NULL;
>         size_t idx = 0;
>         if (p->flow && AppLayerGetProtoFromPacket(p) == ALPROTO_HTTP &&
>                         AppLayerTransactionGetLoggedId(p->flow) >= 0 &&
>                         HtpTransactionGetLoggableId(p->flow) >= 0) {
>             // strcpy(srcip,"2");
>             htp_state = (HtpState *) AppLayerGetProtoStateFromPacket(p);
>             size_t logged = (size_t)
> AppLayerTransactionGetLoggedId(p->flow);
>             size_t loggable = (size_t) HtpTransactionGetLoggableId(p->flow);
>             if ( htp_state && htp_state->connp && htp_state->connp->conn &&
> logged < loggable) {
>                 // strcpy(srcip,"3");
>                 for (idx = logged; idx < loggable; idx++) {
>                     // strcpy(srcip,"4");
>                     tx = list_get(htp_state->connp->conn->transactions,
> idx);
>                     if (tx != NULL && tx->request_headers != NULL) {
>                         // strcpy(srcip,"5");
>                         h_xff = table_getc(tx->request_headers,
> aft->debuglog_ctx->xff_header);
>                         if (h_xff != NULL) {
>                             // strcpy(srcip,"6");
>                             if (bstr_len(h_xff->value) >
> ALERT_DEBUGLOG_XFF_MINLEN - 1 &&
>
> bstr_len(h_xff->value) < 44) {
>                                 strcpy(srcip,bstr_ptr(h_xff->value));
>                                 // strcpy(srcip,"7");
>                             }
>                         }
>                     }
>                 }
>             }
>         }
>     }
>
> The problem is that it never arrives to "step 3" because logged is always >=
> loggable (even though the XFF header is present in the request which
> triggered the alert). I suspect this happens because at the point the alert
> is triggered, the http transaction is not yet finished (it works fine in
> log-httplog).
>
> How should I modify the code to extract the XFF header, if available, even
> when the transaction is not finished?
>

Debuglog depends on the presence of alerts and I see no way around it.
 Instead you can retrieve the available transactions from the
htp_state, pick the one which has the xff header and you have the ip
you need.

int size = (int)list_size(htp_state->connp->conn->transactions);
for (idx = 0; idx < size; idx++) {

    tx = list_get(htp_state->connp->conn->transactions, idx);
    if (tx == NULL)
        continue;

    if (tx has xff_header)
        break;
    tx = NULL;
}

if (tx != NULL) {
    /* this tx has the xff header set.  use the ip */
    xff_ip = retrieve_xff_header_value_for_tx(tx);
}

> Thank you! Regards,
>
>
>   Ignacio Sanchez
> _______________________________________________
> Oisf-devel mailing list
> Oisf-devel at openinfosecfoundation.org
> http://lists.openinfosecfoundation.org/mailman/listinfo/oisf-devel



-- 
Anoop Saldanha



More information about the Oisf-devel mailing list