Archive for November 21st, 2019

Abusing Web Filters Misconfiguration for Reconnaissance, (Fri, Nov 22nd)

Yesterday, an interesting incident was detected while working at a customer SOC. They use a “next-generation” firewall that implements a web filter based on categories. This is common in many organizations today: Users’ web traffic is allowed/denied based on an URL categorization database (like “adult content”, “hacking”, “gambling”, …). How was it detected? 

We received notifications about suspicious traffic based on bad websites detection (read: “not allowed” in the firewall policy). The alert could be read like:

The IP x.x.x.x  tried to access the URL xxxxxxxxx (matching category: xxxxxxxxx)

Why was it more suspicious than usual? It was generated by an “external” IP address (not belonging from any subnet – routed or non-routable). This was strange and it deserved some deeper investigations! No routing issue, no spoofing, it looked like the traffic was really coming from the wild Internet and triggered the web filter. After a deeper check with the team in charge of the firewall, they discovered the mistake: The web filter was also applied on incoming interfaces and the default denied page was returned to the visitor! The offending IP address was (ab)using the web filter feature to perform some reconnaissance: To detect which web sites are allowed/denied by the organization. How? Just visit the website to be tested by connecting to the public address of the target! 

To achieve this, just adapt your ‘/etc/hosts’ (UNIX) or ‘%SYSTEM%driversetchosts’ (Windows) and add a static entry:


Where ‘x.x.x.x.’ is an IP address belonging to the customer.

Not very practical if you must test a lot of sites. Thanks to curl[1], we can automate this in a nice way. Let’s save our malicious sites to be tested in a file, one hostname per line:

$ echo <sites.txt

Now, use the power of curl! It has a nice feature to resolve sites to a specific address (via the ‘–resolve’ parameter):

$ cat sites.txt | while read URL
  curl -s --resolve $URL:x.x.x.x http://$URL | grep -i “blocked” >/dev/null || echo “$URL is NOT blocked”

This command will visit potential malicious URLs by connecting to the customer’s IP address. If the website is not allowed in the policy, the default access denied page will be displayed and we search for an interesting keyword like ‘blocked’. Keep this in mind in your future security tests, always try to access a suspicious URL combined with an IP address of your target.

Since this incident, the firewall policy has been fixed!


Xavier Mertens (@xme)
Senior ISC Handler – Freelance Cyber Security Consultant

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Reposted from SANS. View original.

Posted in: SANS

Leave a Comment (0) →

Gathering information to determine unusual network traffic, (Thu, Nov 21st)

When working with threat intelligence, it’s vital to collect indicators of compromise to be able to determine possible attack patterns. What could be catalogued as unusual network traffic? This is all traffic that is not being seen normally in the network, meaning that after building a frequence table all IP addresses shown less than 1% are suspicious and should be investigated.

What do we need to build a frequence table? We could use a sniffer and then process the network capture to speed things.

Another alternative is to use libpcap to gather information about the incoming protocols and the timestamp that packets were seen. For this diary, we will show a C program using libpcap that will take timestamp and the following information from protocols:

Protocol Fields (CSV file) Log file
TCP year,month,day,hour,minute,second,source IP, source port tcplog.csv
UDP year,month,day,hour,minute,second,source IP, source port udplog.csv
ICMP year,month,day,hour,minute,second,source IP, ICMP Type number icmplog.csv

How to we build the program?

  • We need to define all protocol headers: ethernet, IP, TCP, UDP and ICMP

struct ethernetheader {

        unsigned char ether_dhost[ETHER_ADDR_LEN];    /* destination host address */

        unsigned char ether_shost[ETHER_ADDR_LEN];    /* source host address */

        unsigned short ether_type;                     /* IP? ARP? RARP? etc */


Check the ethernet frame. Same fields.

struct ipheader {

        unsigned char  ip_vhl;                 /* version <> 2 */

        unsigned char  ip_tos;                 /* type of service */

        unsigned short ip_len;                 /* total length */

        unsigned short ip_id;                  /* identification */

        unsigned short ip_off;                 /* fragment offset field */

        #define IP_RF 0x8000            /* reserved fragment flag */

        #define IP_DF 0x4000            /* dont fragment flag */

        #define IP_MF 0x2000            /* more fragments flag */

        #define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */

        unsigned char  ip_ttl;                 /* time to live */

        unsigned char  ip_p;                   /* protocol */

        unsigned short ip_sum;                 /* checksum */

        struct  in_addr ip_src,ip_dst;  /* source and dest address */


Check the IP header. Same fields too.

/* TCP header */

typedef unsigned int tcp_seq;

struct tcpheader {

        unsigned short th_sport;               /* source port */

        unsigned short th_dport;               /* destination port */

        tcp_seq th_seq;                 /* sequence number */

        tcp_seq th_ack;                 /* acknowledgement number */

        unsigned char  th_offx2;               /* data offset, rsvd */

#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)

        unsigned char  th_flags;

        #define TH_FIN  0x01

        #define TH_SYN  0x02

        #define TH_RST  0x04

        #define TH_PUSH 0x08

        #define TH_ACK  0x10

        #define TH_URG  0x20

        #define TH_ECE  0x40

        #define TH_CWR  0x80


        unsigned short th_win;                 /* window */

        unsigned short th_sum;                 /* checksum */

        unsigned short th_urp;                 /* urgent pointer */


Same goes for the TCP header.

struct udpheader {

unsigned short int udp_srcport;

unsigned short int udp_destport;

        unsigned short int udp_len;

        unsigned short int udp_chksum;


Same goes for UDP header.

struct icmpheader {

u_int8_t type; /* message type */

u_int8_t code; /* type sub-code */

u_int16_t checksum;

union {

struct {

      u_int16_t id;

      u_int16_t sequence;

        } echo; /* echo datagram */

        u_int32_t gateway; /* gateway address */

struct {

      u_int16_t __unused;

      u_int16_t mtu;

        } frag; /* path mtu discovery */

        } un;


Same goes for ICMP header.

  • We find the capture device:

dev = pcap_lookupdev(errbuf);

if (dev == NULL) {

fprintf(stderr, “Couldn’t find capture device: %sn”,errbuf);



  • We get the netmask for the capture device:

if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {

fprintf(stderr, “Couldn’t get netmask for device %s: %sn”, dev, errbuf);

net = 0;

mask = 0;


  • We open the capture device:

handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);

if (handle == NULL) {

fprintf(stderr, “Couldn’t open device %s: %sn”, dev, errbuf);



  • We make sure we are capturing on an ethernet device:

if (pcap_datalink(handle) != DLT_EN10MB) {

fprintf(stderr, “%s is not an Ethernetn”, dev);



  • We implement the capture filter by compiling and installing it:

char filter_exp[] = “ip”;

if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {

fprintf(stderr, “Couldn’t parse filter %s: %sn”,

filter_exp, pcap_geterr(handle));



if (pcap_setfilter(handle, &fp) == -1) {

fprintf(stderr, “Couldn’t install filter %s: %sn”, filter_exp, pcap_geterr(handle));



  • We define the pcap_loop() function to invoke packet_process() to process packets:

pcap_loop(handle, 0, packet_process, NULL);

  • We define a switch-case code inside the packet_process() function to gather the information from packets and save it to the statistics log:

ethernet = (struct ethernetheader*)(packet);

ip = (struct ipheader*)(packet + SIZE_ETHERNET);

size_ip = IP_HL(ip)*4;

if (size_ip >= 20) {

switch(ip->ip_p) {



tcp = (struct tcpheader*)(packet + SIZE_ETHERNET + size_ip);

size_tcp = TH_OFF(tcp)*4;

if (size_ip >= 20){








udp = (struct udpheader*)(packet + SIZE_ETHERNET + size_ip);







icmp = (struct icmpheader*)(packet + SIZE_ETHERNET + size_ip);






printf(“Protocol: unknownn”);




After executing the program, you will get the three log files:

Want to download the whole source code? Go to

Manuel Humberto Santander Peláez
SANS Internet Storm Center – Handler
Twitter: @manuelsantander
e-mail: msantand at isc dot sans dot org

(c) SANS Internet Storm Center. Creative Commons Attribution-Noncommercial 3.0 United States License.

Reposted from SANS. View original.

Posted in: SANS

Leave a Comment (0) →