天天看点

[2021祥云杯]secrets_of_admin

[2021祥云杯]secrets_of_admin

这题也是直接提供了源代码

[2021祥云杯]secrets_of_admin

老样子,先看看有没有啥危险函数,没发现的话只能一个路由一个路由慢慢的审了

先看主路由吧

[2021祥云杯]secrets_of_admin

有get和post两种请求方式

get请求应该就是正常访问该页面

post请求获取了username和passwd后,判断完数据类型就把他们传递给了DB.Login()

[2021祥云杯]secrets_of_admin

DB.Login()应该是把用来判断用户输入的用户名和密码和数据库保存的是否一致来判断登录

回到主路由的代码,如果登陆成功,他会把用户的一些信息仍token里

[2021祥云杯]secrets_of_admin

接下来看到admin路由的get方法

[2021祥云杯]secrets_of_admin

已请求这个路由他就会调用checkAuth方法

[2021祥云杯]secrets_of_admin

这个方法的作用也很简单,就是不允许superuser使用,注释也说明了该方法的作用

回到admin路由的get方法

[2021祥云杯]secrets_of_admin

它会将username作为参数调用DB.listFile方法

[2021祥云杯]secrets_of_admin

从这个方法的那句sql语句我们就应该知道,它会获取传入用户的所有所拥有文件名和对应checksum的值(这里checksum的作用我们先不做说明)

admin路由获取了登录用户在数据库中存储的信息后,会把他们写入自己的token

到这里admin路由的get方法就结束了

接下来看admin路由的post方法

[2021祥云杯]secrets_of_admin

还是先禁止superuser用户访问

[2021祥云杯]secrets_of_admin

接下来获取content的信息,并对content的信息进行waf过滤

[2021祥云杯]secrets_of_admin

接下来这里有个html的模板,如果content能经过前面的过滤,就会把content放进html模板中

[2021祥云杯]secrets_of_admin

接下来uuid随机生成一个标识符作为pdf文件的名字,然后根据上面的html模板生成一个pdf文件,并把这个文件发送到./files目录下

接下来对pdf的文件名调用getCheckSum方法,总的概括就是根据文件名生成一段随机数

[2021祥云杯]secrets_of_admin

然后将文件名和对应的随机数checksum一起放到数据库里superuser所属下

[2021祥云杯]secrets_of_admin
[2021祥云杯]secrets_of_admin

接下来看/api/files路由

[2021祥云杯]secrets_of_admin

这个路由就比较简单粗暴了,只能本地访问,然后将username, filename, checksum写进数据库,这三个参数的信息我们是可控的

最后看/api/files/:id路由,这个路由还是先禁止superuser用户访问

[2021祥云杯]secrets_of_admin

接着根据用户名与我们在url中输入的id(也就是checksum)去数据库中匹配对应的文件名,并在./files路径下访问该文件名

[2021祥云杯]secrets_of_admin
[2021祥云杯]secrets_of_admin

到这里所有的路由就分析完了,我们再来看看数据库

[2021祥云杯]secrets_of_admin

这些是数据库的初始化,我们可以从中得到admin的密码,并且可以知道flag这个文件名是superuser用户的

整理下信息:

1.我们目前知道的flag属与superuser

2.唯一的读文件函数在/api/files/:id路由,他不允许superuser访问,而且只能读取./files目录下的文件,读文件的条件是只要知道用户名和文件对应的checksum就行

3.admin知道它拥有的文件,也可以添加任意文件名和对应checksum到他那里,但是得本地访问

4.admin路由下生成的pdf文件全归superuser所有,并且会在./files生成相应的文件

5.readfile读文件时,它是将文件名拼接到路径上的,而且根据源代码得目录我们知道flag就在files目录下,任何人都可以读取该文件

根据以上信息得出思路:

首先我们要深刻意识到数据库中存的仅仅只是一个文件名,而且flag文件就在files目录下,只要文件名和既定路径拼接合理,那谁都可以读到flag文件

flag这个文件名又是属与superuser,用superuser去读那是不可能的了,那我们可以构造给admin一个文件名,让他文件名不是flag,和路径拼接到一起时又可以读到flag文件,所以我们可以考虑目录穿越…/files/flag或者是直接用./flag

既然如此那我们得把文件名和对应的checksum写到数据库里去,这就得用到ssrf了

ssrf的利用点说实话我自己并不是很清楚在哪里,找了一下大佬的WP看看,才知道我们在 content 中传入一个正常的 HTML 标签理论上也是可以直接解析的。那我们可以在 content 中传入一个可以自动触发 src 属性的标签,用这个 src 属性触发 SSRF 并访问 /api/files 路由为 admin 用户创建 flag 文件记录。

看了另一个大佬WP才知道html-pdf库也存在一个任意文件读取

但不管咋样ssrf利用点就是content这里

贴上两个大佬处copy的payload

content[]=<img+src%3D"http%3A//127.0.0.1:8888/api/files?username%3Dadmin%26filename%3D./flag%26checksum%3D123">

content[]=%3Cscript%3E%0Avar%20xhr%20%3D%20new%20XMLHttpRequest()%3Bxhr.open(%22GET%22%2C%20%22http%3A%2F%2F127.0.0.1%3A8888%2Fapi%2Ffiles%3Fusername%3Dadmin%26filename%3D.%2Fflag%26checksum%3D123%22%2C%20true)%3Bxhr.send()%3B%0A%3C%2Fscript%3E

           

在admin处post请求payload后,在api/files/id访问对应的checksum值即可

[2021祥云杯]secrets_of_admin
[2021祥云杯]secrets_of_admin
[2021祥云杯]secrets_of_admin
[2021祥云杯]secrets_of_admin
[2021祥云杯]secrets_of_admin
[2021祥云杯]secrets_of_admin

继续阅读