Today we received a request for help from a journal we host. They had published a fake issue in their OJS.
We noticed that there are many journals experiencing the same problem. Basically, an issue is published without articles, but with a DOI. Several issues can now be found through this search: Google Search
In the case we investigated, we identified that an attacker had logged in through the account of one of the editors and imported the fake issue from an XML. In other words, it wasn’t a vulnerability being exploited in OJS, but the use of third-party accounts, possibly with leaked or fragile passwords.
Interesting, I hadn’t seen this before. I mentioned on another thread that we have seen reports of privilege escalations via old XSS attacks; have you looked at the journal you host to see if this might’ve been the vector? (Looking through a mysqldump of the database for <script might also give you something to investigate.)
Regards,
Alec Smecher
Public Knowledge Project Team
We did not identify how they obtained the credentials of legitimate users, but we were able to identify a pattern of similar attempts in this and other journals:
Log in with a regular journal user
They try to access the XML import area
If there is no permission and there is another compromised login in the same OJS, they restart the process.
Now specifically about the case where they succeeded in publishing an issue, and which I reported above, is that it is a journal that came from OJS 2.4.x, so there were more opportunities for exploitation until the upgrade took place. As of OJS 3.3.x we have not identified any vulnerabilities being exploited.
When we migrate an OJS to our hosting, we look for registered users who don’t look legitimate. In the case of this journal, at the time of the upgrade 4 users were deactivated who had JS code in their biography or other field.
In addition, today I found JS code in the abstract of a published article. OJS doesn’t display it and it seems to have been inserted back in the days of OJS 2.4.x.
Thanks for the suggestions, Alec.
We’ll let you know if we make any further progress.
Hmm, I wonder if they aren’t working through some third party username/password database looking for shared credentials, attempting to log in to OJS with them, and when they can, POSTing an XML file to determine whether they’ve got a manager or admin account.
If you see anything more, please let me know (PM if it’s sensitive).
Thanks,
Alec Smecher
Public Knowledge Project Team
Had the same issue. More info about the situation.
The attacker somehow (using NativeXMLPlugin) created file public/journals/1/lanciau.php and executed it several times with POST method. As a result, passwords of all journal managers (and some random users) were changed, and also their emails were modified (like user@domain → user1@domain) making them unable to restore passwords with the “Forgot password” function.
User kominfo was created and added to managers
Also I had writable some code directories where I encountered modified files with line eval($_SERVER['HTTP_KOMINFO']); added.
Regards,
Vasyl
As far as we’ve been able to ascertain so far, the fake issues are created when someone with a Journal Manager account is able to log into OJS with a username and password. Then they import an XML file to create the fake issue, and in your case, your OJS is vulnerable to an old attack.
In order to import the issue, they must already have Journal Manager access. That could be possible through a stored XSS attack, or dictionary attack for weak passwords, for example. Stored XSS attacks are known to exist in out of date OJS installs like yours.
Long story short, OJS 3.1.2-1 has been unmaintained for some time, and I would definitely recommend upgrading. We’re still making sure we have a complete picture of this issue, but continuing to run 3.1.2-1 isn’t viable.
Regards,
Alec Smecher
Public Knowledge Project Team
Investigating this further, these appear to be automated attacks against bug #9464, which was disclosed and given a CVE in 2023 ( CVE-2023-47271). The fix for the issue was included in OJS/OMP/OPS 3.3.0-16 and later for 3.3.0-x, and OJS/OMP/OPS 3.4.0-4 (3.4.0-x). Folks running up-to-date versions of OJS/OMP/OPS are safe, unless they were already hacked via a malicious XML import before they upgraded.
In order for the hack to have been executed, the attacker must have already had Journal Manager credentials in order to perform an XML import. They may have obtained these through a dictionary attack (weak or re-used passwords), stored XSS attack (there are some of these in out-of-date releases of OJS/OMP/OPS), or some other mechanism. Once a user has Journal Manager credentials, needless to say, they can perform a number of malicious actions; this XML upload is just one.
If you are running a version of OJS/OMP/OPS that contains the fix, and an attacker uploads the malicious XML file, you will still see a fake issue created – however, the PHP part of the payload will not be successfully created. This will leave an empty issue lying around, but the attacker will not be able to execute malicious scripts.
This is a good reminder to keep your OJS/OMP/OPS up to date. Looking through the journals affected by this issue, many of them use OJS 3.1.x, for example. It is not safe to use releases that are so far out of date.
Regards,
Alec Smecher
Public Knowledge Project Team
I suspect you mean OJS 3.2.1-4 rather than 3.2.4, right?
There was a different vulnerability in the UserImportExportPlugin that allowed for someone with Journal Manager access to escalate that to Administrator access. It’s filed with patches here. However, in order to make use of the attack, a user must already have a Journal Manager account – which is already a very significant breach.
OJS 3.2.1-4 is very old, and there are known flaws in it including e.g. XSS attacks that could allow a malicious user to steal Journal Manager credentials. I strongly suggest upgrading at least to the current LTS release and keeping up to date.
Regards,
Alec Smecher
Public Knowledge Project Team
Yes, sorry, it is 3.2.1.4 version. I’m investigating this incident and one thing is a bit strange. Malicious user registered his account in OJS (i can see that from his username/email address) but the date of registration/last login is set to October 2024, while the attack was performed in January 2025. I put effort to do more checking (restored old db backup) and i’m sure this user was created in January 2025 on the day of the attack and not in October 2024. I’m not sure how is this possible? I guess only way would be to get direct DB access and update those fields, but this sounds a bit odd to do. Regarding update, you are 100% right, but we depend on other systems that connect directly to the OJS, so we first have to refactor them to be able to update. However, this is now priority that we will start working on.
If the attack was performed via a stored XSS, it would take this path:
The malicious user would register an attack and store a malicious piece of Javascript in their profile, or in a submission, etc. (Older releases of OJS are known to have some of these types of flaws; they have been corrected in later releases.)
When the Journal Manager or Administrator logs in, the malicious Javascript is executed in their browser, causing it to e.g. upgrade the user account’s credentials, or import malicious XML, etc.
Then the attacker could use the results from #2 to access the system without needing to log in via OJS.
So it’s entirely possible that an attack could have happened in January 2025, even if the malicious account doesn’t appear to have been accessed since October 2024.
Regards,
Alec Smecher
Public Knowledge Project Team
Thank you for info. I’m really diving into this (logs) to see what was going on. For now i think this is what happened:
Attacker logged in into OJS (i don’t know which credentials were used - maybe auth. logging would be good feature to implement)
He used importexport/plugin/UserImportExportPlugin/uploadImportXML to upload malicious script/scripts
After that he logged in as another user that had an admin role. This user was created by attacker with registration/last login fields set to “October 2024.” although attack was done in January 2025. I’m still trying to figure out how exactly this user was created. How i know that account was created in January? Because lets say his user_id was 1500, the next regular user_id 1501 is registered on the same date in January when attack happened, the next regular user_id 1502 same thing, so clearly that happened on the very same day.
I believe i know which journal editorial was targeted to get credentials in 1. Not sure how he got it (maybe the way you say, by XSS attack, maybe some other way) but i will now send email to that editorial board to change passwords. I will also try to find out the rest of the puzzle and will get back with my findings.
Unfortunately i can’t use the patches you provided because they are not for this version of OJS, so for now i just removed those plugins. Thx.
The UserImportExportPlugin was probably used in 2. to create a new user with administrator credentials according to the bug I linked above. Then, in turn, that account was probably used to install malicious scripts e.g. via uploading a custom plugin.
Regards,
Alec Smecher
Public Knowledge Project Team
Yeah probably like that. One more question. I see that we have many users with username set to “uundefined*” where * is a number. Do you know anything about this? Thx.
Those are probably run-of-the-mill spam user registrations. There are various configuration options (in config.inc.php) and plugins (in the plugin gallery) to help reduce spam. If you’ve got questions about that, I’d suggest looking for another relevant thread on the forum, or starting a fresh one.
Regards,
Alec Smecher
Public Knowledge Project Team
I thought it’s maybe connected with this, bcs. some users look very legit (real name / email address). I tried searching forum but didn’t find anything regarding that. Will investigate further. Thank you.