[Dnsmasq-discuss] dnsmasq mishandles some cases when bad dns response packet is received
Geert Stappers
stappers at stappers.nl
Sun Nov 13 13:15:43 UTC 2022
On Sun, Nov 13, 2022 at 10:23:55AM +0800, zhangJiangyu via Dnsmasq-discuss wrote:
> On Sat, Nov 12, 2022 at 04:15:38PM +0800, Geert Stappers via Dnsmasq-discuss wrote:
> > On Sat, Nov 12, 2022 at 10:30:09AM +0800, ZhangJiangyu 张江瑜 via Dnsmasq-discuss wrote:
> > > Hi,
> > >
> > > Description
> > >
> > > When the DNS forwarder iteratively queries the malicious domain name
> > > server, it returns some malformed dns packets, and dnsmasq returns the
> > > packet to the client without proper verification, which will give the
> > > user a distrust or malicious data. Other authoritative dns servers
> > > have done correct verification. there are three bugs below, you can
> > > start a fake domain name server locally and return specific data.
> > >
> > > Steps to reproduce
> > >
> > > 1、Turn on a fake name server and return a specific payload.
>
> > How?
>
> You need a few steps to reproduce:
>
> * Run the command (sudo python3 dns_server.py "response filename
> path") to listen on port 53. This will start a fake dns server,
> receive the request, and return the result.
> * Start the dnsmasq software to listen on port 5353.
> * The configuration file is as follows:
> "port=5353
> no-daemon
> no-resolv
> server = 127.0.0.1
server = 127.0.0.1#53531
See below for why
> bind-interfaces
> no-hosts"
> * Run the command (./dnsmasq -C ./dnsmasq.conf) to start the dnsmasq.
> * Run the command (python3 dns_request.py "request filename path"
> 5353) to send the request, dnsmasq will forward the request to our
> fake dns server, return the message and then return it to the client.
> * Analyze the message returned to the client, you will find that
> there is a problem with the message, and the correct verification
> is not done.
>
> Next, I will give the download link of the corresponding python
> script, request file and response file, which can be reproduced after
> downloading.
>
> * dns_server.py
> * https://643684107.oss-cn-beijing.aliyuncs.com/dns/dns_server.py
} import os
} import sys
} import socket
} import struct
} import threading
}
} def done(sock):
} try:
} sock.shutdown(socket.SHUT_RDWR)
} sock.close()
} except Exception as e:
} pass
}
} # The UDP server is contacted first
} def udp_server(name):
} sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
} sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
} server_address = '0.0.0.0'
} server_port = 53
server_port = 53531 # avoid conflict with existing DNS
}
} sock.bind((server_address, server_port))
} while True:
} try:
} recvd, client_address = sock.recvfrom(65535)
}
} print(recvd)
}
} inputfile = name
} data = None
} with open(inputfile, 'rb') as f:
} data = f.read()
} data = data[4:]
} data = data[2:]
}
} print(recvd[:2] + data)
}
} if len(recvd) > 2:
} sent = sock.sendto(recvd[:2] + data, client_address)
} except Exception as e:
} pass
}
} done(sock)
}
} def main():
} global stop_server
}
} stop_server = False
}
} # Sets up one server on UDP port 53
} udp_server(sys.argv[1])
}
} os._exit(0)
}
}
} if __name__ == '__main__':
} main()
> * dns_request.py
> * https://643684107.oss-cn-beijing.aliyuncs.com/dns/dns_request.py
> * first bug:
> * request file: https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/request1
> * response file: https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/response1
> * second bug:
> * request file: https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/request2
> * response file: https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/response2
> * third bug:
> * request file: https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/request3
> * response file: https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/response3
>
This worked for me:
wget https://643684107.oss-cn-beijing.aliyuncs.com/dns/dns_server.py
wget https://643684107.oss-cn-beijing.aliyuncs.com/dns/dns_request.py
wget https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/request1
wget https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/request2
wget https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/request3
wget https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/response3
wget https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/response2
wget https://qu-hexo-static.oss-cn-hangzhou.aliyuncs.com/ping/response1
Upon "run" I get something like:
| $ python3 dns_request.py request3 5353
| b'12\x81\x80\x00\x01\x02\x00\x01\x06cert01\x07example...\x03ns2\xc0\x13'
| $
The how to reproduce question is answered. Thanks.
However I don't understand the problem.
What I think what would help for getting more attention to the "problem",
is having a `request0` and `response0` that is a valid / known good
CERT query. With `host -p 5353 -t CERT cert01.example.com 127.0.0.1`
or `dig @127.0.0.1 -p 5353 -t CERT cert01.example.com` being a replacement
for the `python3 dns_request.py request0 5353`.
Groeten
Geert Stappers
--
Silence is hard to parse
More information about the Dnsmasq-discuss
mailing list